
Gravity – An embeddable programming language - creolabs
http://gravity-lang.org
======
tom_mellior
"The VM code is about 2K lines long, the multipass compiler code is about 3K
lines and the shared code is about 2K lines long."

I was surprised by these numbers so I checked, and this is highly misleading
(or very much out of date). The parser alone
([https://github.com/marcobambini/gravity/blob/master/src/comp...](https://github.com/marcobambini/gravity/blob/master/src/compiler/gravity_parser.c))
is over 2K lines, and with the lexer and the AST definitions the _frontend_ of
the compiler is already comfortably above 3K lines. Also, the VM
([https://github.com/marcobambini/gravity/blob/master/src/runt...](https://github.com/marcobambini/gravity/blob/master/src/runtime/gravity_vm.c))
is about 2K lines, but then there is another 3K lines in another "runtime"
file
([https://github.com/marcobambini/gravity/blob/master/src/runt...](https://github.com/marcobambini/gravity/blob/master/src/runtime/gravity_core.c)).

Still, it's not a huge project, and it might be interesting as a point of
study for people interested in compilers (to bytecode) or bytecode
interpreters. The input syntax looks pretty as well.

Interestingly,
[https://github.com/marcobambini/gravity/blob/master/src/runt...](https://github.com/marcobambini/gravity/blob/master/src/runtime/gravity_vm.c)
also serves as a nice illustration of the fact that if tabs are allowed in
source code, people will _mix_ them with spaces, resulting in code that looks
bad unless you have the exact same tab width preferences as the author.

~~~
davelnewton
I'm not sure how the parser and lexer/etc. line count matters for the VM line
count. _shrug_

Definitely something I'll be looking at for my embedded work; it may fill a
gap in my toolchain. And boo-hiss tabs.

~~~
Sean1708
> And boo-hiss tabs.

At the risk of starting a flame-war: boo-hiss not using a formatter.

~~~
davelnewton
Orthogonal. Once you have tabs, any viewing of that file will rely on the tab
size set by whatever viewer you're using: mixing tabs and spaces basically
never works. At least if it's _just_ tabs everything will be seen wrong
consistently.

The only reliable mechanism is spaces-only.

:p

~~~
Sean1708
But if you're using a formatter then it doesn't matter whether you use tabs,
spaces, minimal whitespace, or any mix thereof because that's what the
formatter is for.

Also if you're using a formatter then you can do the correct thing and use
tabs for indentation and spaces for alignment, because the formatter will
ensure that the output is consistent.

~~~
davelnewton
The output is consistent if your tab settings are always the same when you
look at your code, and you use the same tab size across all languages.

I view code in multiple ways, have different indentations for different
languages (not many different now), and have clients that enforce difference
indentation settings. It just doesn't work.

~~~
Sean1708
> The output is consistent if your tab settings are always the same when you
> look at your code, and you use the same tab size across all languages.

I don't really understand what you're getting at here to be honest, surely if
you change your tab settings it's because you _want_ the code to look
different?

> I view code in multiple ways, have different indentations for different
> languages (not many different now),

This is exactly what tabs are great for! You can set the tab width based on
language without having to force that choice on anyone else.

> clients that enforce difference indentation settings

Again, formatter.

~~~
davelnewton
I'm not sure if you're being deliberately obtuse, or just never look at files
in only one way. I don't have that luxury.

Say I have a project that has Java and Rhino (JavaScript) files. My IDE/editor
is configured for Java with TAB==4, JavaScript TAB==2. Everything looks great
in my editor, because it knows things.

Now I'm using `less` or `cat` in my shell. Or ssh-ing to a remote box because
of an emergency production issue. Or whatever. Now when I look at the file
things no longer line up as originally intended, because when I view them
outside of the (relatively) smarter IDE the TAB characters are at the mercy of
whatever I am using to view the file.

You _cannot_ simply rely on local tab width settings if files use a mix of
tabs and spaces for indentation and alignment: if you change the tab width
then alignment breaks. If you never align anything, great, tabs work great for
indentation (except for when you can't trivially change it, then they suck).
But indentation isn't the only thing tabs are used for.

There's the rub: TAB characters will always be at the mercy of how I'm viewing
the file, which I do not always have control over, and certainly not
(trivially) based on the type of the file.

~~~
Sean1708
> You cannot simply rely on local tab width settings if files use a mix of
> tabs and spaces for indentation and alignment: if you change the tab width
> then alignment breaks.

Ah I think you've misunderstood what I meant by tabs for indentation and space
for alignment (something which you will be controlling with a formatter
because that's the entire premise of my original comment). I'm not sure how to
make it more clear, so I'll give you an example.

    
    
      class SomeClass {
      [tab]functions some_method(with, arguments) {
      [tab][tab]return a_function_call(with,
      [tab][tab]                       lots,
      [tab][tab]                       and,
      [tab][tab]                       lots,
      [tab][tab]                       of,
      [tab][tab]                       arguments);
      [tab]}
      }
    

Is that clearer?

~~~
davelnewton
Yup! Now view that across multiple languages, viewers, and tab sizes.

------
stinos
For anyone who considers this interesting and/or looking for alternatives:
apart from the well-known Lua there's also MicroPython [1] whos specs actually
read a lot like the specs of Gravity but then some more (well, it's Python 3.5
minus a couple of features, also compiles with C99 compilers, is fairly small
for being a Python, embeddable, more mature at this point, been tested on more
platforms/architectures, ...).

[1] [http://micropython.org/](http://micropython.org/)
[https://github.com/micropython/micropython/](https://github.com/micropython/micropython/)

~~~
SlowRobotAhead
Just a nitpick... but I’ve seen people who aren’t working on what i would
consider typical embedded recommend eLua and MicroPython readily without ever
mentioning the downsides that mPy needs 128k+ ROM and includes a ridiculous
standard lib most of which you would never use on embedded, and eLua supports
some Cortex m3 and is a dead project. These two you mentioned are more of
people using Rasp Pi syyle embedded (Cortex m-series vs Cortex A/R series...
small devices vs phone processors).

The issue is everyone has this “great idea” for an embedded language to
replace C which means device headers in the Lang, and that’s way too much to
support.

If the goal is to replace C imo it’s a waste of time. But there is a market
IMO for an embedded lang that you can execute tests and scripts from C in a VM
that can foreign function interface back to C functions.

There is on that uses JS called mJS but I found the one of the guys that
supports it to be extremely rude and unhelpful. Documention is lacking. You
basically need to be an expert in JS to get started. And then they doubled
their ROM use age from 23k to ~50k. But it does seem to be the best out there
for the goals I stated.

I’m still on the hunt.

~~~
fundamental
It depends upon what's the target you're trying to embed into. If you're
trying to put something on a PIC or an 8 bit AVR, you're down to something
like assembly, C, or a very low memory language like forth. If you're looking
at larger targets like the ESP32, then you can use an embeddable python, ruby,
lua, js, etc without being too concerned. On something like a raspberry pi
compute time likely ends up being more of a concern than memory or build
complexities.

The other target is trying to embed some interpreter in a larger application,
which ends up being mostly constrained by how nice the language is as well as
how nice the C API barrier ends up being.

C is certainly not going anywhere, but it is pretty cool that other options
are being built to lower the barrier of entry for some application domains.

~~~
nickpsecurity
One project used ATS for an 8-bitter:

[http://metasepi.org/doc/metasepi-icfp2015-arduino-
ats.pdf](http://metasepi.org/doc/metasepi-icfp2015-arduino-ats.pdf)

[http://www.ats-lang.org](http://www.ats-lang.org)

Chez Scheme used to run on 8-bit platform, too. Then there's Pascal and BASIC
dialects for microcontrollers. Astrobe has Oberon dialect for ARM Cortex's.
AVR-Ada lets you use Ada with AVR's. OcaPIC put Ocaml subset on PIC
microcontrollers.

People are using C because most people already use C with the ecosystem
benefits that follow. Although C and assembly are dominant, there are other
options available if people think their pro's and con's line up with their
needs.

~~~
PeCaN
Always cool to see ATS in the wild. Higher-order functions on an 8-bit CPU
makes me happy. :D

------
bakery2k
Is it possible to embed Gravity in my C/C++ project and safely run _untrusted_
Gravity code?

The Lua implementation supports the creation of sandboxes to run untrusted
scripts, but this is a feature that other embeddable languages (e.g. Wren,
Python) don't seem to support.

I feel like this would be a basic requirement - or is it common to embed a
scripting language without limiting what scripts are able to do?

~~~
kevin_thibedeau
Tcl is the granddaddy of embeddable scripting languages. It has had safe sub-
interpreters for untrusted code for quite a while. They were added back when
it had a shot of being a contender against JavaScript and safe script
evaluation was deemed necessary.

------
creatornator
A while back I was interested in learning more about programming compilers, so
I checked this project out. I actually added array map, filter, reduce, and
sort methods to the language, which was fun and a learning process.

~~~
evincarofautumn
That’s great! You’re the kind of person the hobbyist programming language
development community needs. I’d encourage anyone who’s interested in learning
more about compilers to see how they can contribute to a new language—it’s a
great learning experience, one less thing for the primary author to do (a
programming language can be an enormous undertaking), and who knows, you may
be helping to build the next big thing.

------
vitriol83
Can anyone suggest a good embedded language with static or at least optional
typing ? I feel this is a gap in the market for embedded languages.

~~~
mastax
Dyon
[https://github.com/PistonDevelopers/dyon](https://github.com/PistonDevelopers/dyon)

(Interesting and very easy to modify, maybe not "production ready")

~~~
tomp
Thanks for this!

This is by far the most _what the fuck_ language that I've seen in a long
while. It displays an astonishing amount of creativity and novel (at least to
me) ideas, most of which are probably bad and won't survive for long, but some
of them are really cool! Things like "packed loops"

    
    
        for i, j { println(list[i][j]) }
    

or using `return` as a variable without exiting

    
    
        return = 8
    

Really cool!

~~~
Narishma
I seem to recall something similar in an old language (maybe Pascal?) where
the way to return something was to assign it to the name of the function.

~~~
semi-extrinsic
Fortran does this (still does in F2008). But usually I end up using
subroutines instead, since I want the code in question to modify more than one
object. Functions can only return one object, and the overhead of
packing/unpacking to a struct is annoying.

What Fortran really needs to get is first-class string handling and saner IO.
Apart from that being a pain, modern Fortran is a nice language to use.

------
inputcoffee
As a hobbyist I love seeing new languages. I look at their features and a few
simple examples and immediately imagine they'll solve all the issues I have
faced with other languages.

I generally appreciate the massive amount work that goes into something like
this.

But when I want to work on a project, I am wary of using something new. I just
know in my heart I'll set the wrong flag on the compiler and the binary will
end up in a directory I can't find and it'll take me two days to figure out
how to do it.

My question is this: if the main strength of this language is that uses Swift-
like syntax, and lets you develop native apps in Android and iOS, why not just
make an Android compiler for Swift?

~~~
heavenlyblue
"issues I have faced with other languages"

Which ones, specifically?

~~~
inputcoffee
I mean that in the generic sense when you grow a project (I use python mostly)
and run into issues invariably with the size and complexity.

------
pq0ak2nnd
As an embedded programmer, it is still very hard to displace C and will be for
some time. The two main reasons: the compilers are well-behaved, and the debug
tools are very, very mature. One thing newcomers overlook is the importance of
understanding what the compiler does to the code. C++ is notorious for being
painfully unpredictable, and in the embedded world, that is a death sentence.
mbed is learning this the hard way. On the other side, debug tools are
critical. Unlike the decade long surge of web-related programming with its
sophisticated GUI-based debugging, embedded is a completely different beast,
and requires much more attention to detail since reprogramming costs are so
high. Because C has such a robust hardware debugging ecosystem, it is a clear
winner.

It'll be a long time before anything knocks C down as #1 in the embedded
space. Even as the definition of embedded stretches to include *nix variants
(like Yocto), there will always be the squeeze to get rid of that and run bare
metal with C.

~~~
mbo
I think you're getting confused between embeddable languages (Guile, Lua and
kin), and languages for embedded development (you mentioned C).

~~~
pq0ak2nnd
You are correct, sir.

------
weberc2
I’m a little bummed about the class-based bit; I generally want
structs/records, not classes. Specifically, I want to avoid inheritance
altogether (yes I know I don’t have to use it, but I still have to interact
with it when libraries or coworkers use it). Still, this is a neat little
scripting language, and best of luck.

~~~
developer2
On the off chance you're not already acquainted, you might really like Go.
There are no classes, thus struct types are the bread and butter. "Methods"
are lightweight syntactic sugar combining structs and functions; structs
effectively double as classes, but the scope and complexity they offer are
perhaps easier to juggle compared to the typical object-oriented language.

The inheritance mechanism, implemented via interfaces, is interesting because
it stresses conformance to behavior rather than explicit relationships between
types. If your Circle struct type walks and talks like a Shape, then it is
implicitly usable as a Shape. It's functionally identical to explicitly
defined inheritance between types in other languages, but there's something
about the _feel_ of developing with Go's interfaces. You begin to think more
about the simple behaviors that each type should exhibit, rather than drawing
hard lines in the sand about the hierarchy of relationships. Circles and
Squares don't extend a base Shape type. Rather, a Circle can calculate its
surface area. A Square can do the same. Conveniently, it just so happens that
any type that can calculate its area is promoted to being usable anywhere a
Shape is expected.

~~~
SlowRobotAhead
Is there a Go VM for 32bit embedded?

~~~
developer2
The parent I replied to made me think so strongly of Go that I forgot the
context regarding embedded systems. A quick search shows support for ARM;
beyond that, I don't know if any options exist.

~~~
SlowRobotAhead
When a language says ARM like that, they mean the ARM that runs your phone.
Not the ARMs that run your Fitbit.

------
ainar-g
>null

>dynamic typing

>naked if-else bodies

I'm sorry, but I just don't see how this improves on anything. How will
GravLang make me a better, more productive programmer? How will it make my
programs more robust?

Don't get me wrong, as a hobby project it's fine, but as a "real" language it
doesn't have any selling points to me.

~~~
api
It doesn't improve _much_ on e.g. JavaScript or Python. That's not the point.
The point is that it's a small fast zero-dependency embeddable language that
could be used for e.g. scripting in games or small devices.

Wren is another nice one:

[https://github.com/munificent/wren](https://github.com/munificent/wren)

~~~
ainar-g
Don't we have already Lua for that? It even has a state-of-the-art JIT
compiler.

I am all in for competition, but I can't see how both of these languages could
improve over Lua.

~~~
lasagnaphil
Although LuaJIT is crazy fast, it can't be used on iOS, so we first need to
compare this with the unJITted version of Lua.

Lua is pretty simple and elegant, but has its woes on being too flexible and
wonky (especially with nil and global variables). It also doesn't support OOP
syntax directly, so everyone started to create their own wonky class system,
which broke easily because of Lua's wonkiness. Gravity seems like a good
embedding language packaging a nice OOP syntax with a lot of syntactic sugar
(such as properties and access specifiers), so I think some UI/game developers
would choose this over Lua.

~~~
api
Can anything interesting be used on iOS?

~~~
lasagnaphil
There are some nice non-JIT embedded languages such as Angelscript (resembles
C++, uses refcounting instead of GC), Squirrel (extension of Lua syntax to
support classes and other nice features), and recently Wren (has a nice class
system and uses fibers for concurrency).

~~~
api
Does Apple still prohibit any form of downloaded code or scripting or did they
finally ease that?

~~~
0xCMP
They do if the user can download and execute the code themselves. If the
underlying app uses it (e.g. React Native app downloads updated bundle) and
user can't touch it then it's okay.

------
bitmapbrother
>Gravity syntax is designed to be familiar to people coming from C-like
languages like Javascript, Swift, C++, C# and many more. We started working on
this new language a year before Apple announced Swift and we were happily
surprised to discovered how similar both syntax appear.

Amusing how the language looks so much like Kotlin - a language released in
2011 and 3 years before Swift.

~~~
vorg
> syntax is designed to be familiar to people coming from C-like languages
> like Javascript, Swift, C++, C# and many more

Besides Kotlin, other such modern C-like languages are Java, Dart, Go, and
Groovy. But because Gravity is dynamically typed, a better peer language
comparison would be Javascript, Groovy, Dart, and Swift. Each of those
languages was designed for a specific platform, i.e:

    
    
      * Javascript for the web in 1995
    
      * Apache Groovy for the JVM in 2003 (still used for Gradle build scripts)
    
      * Dart for the JVM and for Javascript (and more latterly for Fucshia, Android, and iOS) in 2011
    
      * Swift for iOS in 2014
    

It's good to see modern dynamically typed languages reject Python's
indentation and Ruby's `end` keyword, and settle around curly braces for
scoping.

~~~
hajile
Dart has always had optional static types. With 2.0, those be come mandatory.
If you are familiar with Swift, then dart would be Swift with a GC rather than
ref counting and without tuples (or rather, the reverse would be true as dart
is older than Swift).

------
yoz-y
Seeing the overall style of the documentation logos and copy, I am kind of
surprised that embedding this from Swift is not covered.

~~~
lasagnaphil
Most scripting languages provide only a C interface, because it is what most
of the other languages are universally compatible with. C++ codebases can use
"extern C", other compiled languages like Rust or Swift can use C interop (for
example:
[https://developer.apple.com/documentation/swift/swift_standa...](https://developer.apple.com/documentation/swift/swift_standard_library/c_interoperability))

------
cmjqol
At first look I love how the language is designed.

Now I'm curious about the "embedded" part . Apple doesn't allow any VM or JIT
to be embedded for iOS application. Either I'm missing something or else this
tech is not compliant with Apple Security Guidelines.

~~~
Matthias247
As far as I understand the bytecode is interpreted (not JITed to native
instructions), which is afaik OK on iOS.

------
craftoman
Such an underrated project. IMHO if this one was launched by Facebook or
Google now things would be different like 15k+ plus stars on GitHub and tech
news sites posting articles with titles like "a new game changer language" and
stuff.

------
bjoli
Does anyone have numbers on how light it is? How much memory Does it need? How
big is the library? Does it compare favourably to Lua or Guile? Guile
shouldn't be hard to beat for size, but that's generally not what they try to
achieve.

------
loa-in-backup
"Getting started" link from github readme points to 404.

Edit: so does "language documentation" link.

------
mcguire
" _It is a class-based concurrent scripting language with a modern Swift like
syntax._ "

So, it looks like every other language designed in the last 40 years? This is
good?

~~~
lasagnaphil
In the realm of embedded languages (which is dominated by Lua), Gravity seems
like a great improvement.

A lot of game developers attach a small scripting language to their game
engines because C++ isn't a good language for rapid game logic prototyping,
and takes ages to compile. The majority of them use Lua for this purpose. Lua
is certainly simple and elegant, but has its shortcomings (no direct support
for classes, 1-based indexing, indexing a wrong field returns nil, can
accidentally declare global variables on assignment, lack of syntactic
sugar...) I've looked at other languages such as Angelscript, Squirrel, Wren,
etc..., to use for game development, but I think Gravity is the cleanest and
has the most features so far. I'm still curious about the performance though
(If it runs about the same as non-JIT Lua I'll call it a success, given how
Lua is much simpler than Gravity)

Even if you aren't a game developer, scripting languages also has its use with
UI development. The majority of UI developers use Javascript with a
combination of web technologies, so that's one example. Even QT developers use
a scripting language called Qt Quick (which also resembles Javascript a bit),
because C++ can be too tedious for rapid prototyping. The author of Gravity
have also developed this language for mobile UI Development, so it seems good
for its intended usage.

The language isn't particularily shining on new concepts, but I think it will
be very useful for some of us.

~~~
sitkack
The semantics and capabilities of Gravity mirror those of Lua almost exactly.
Class systems, there are literally hundreds to choose from, basic
Object/Method support is built into the language. As for globals detection,
[http://lua-users.org/wiki/DetectingUndefinedVariables](http://lua-
users.org/wiki/DetectingUndefinedVariables) and non-existent attribute lookup
[https://www.lua.org/pil/13.4.4.html](https://www.lua.org/pil/13.4.4.html)

Anyone programing in Lua should be well versed in
[http://www.luafaq.org/gotchas.html](http://www.luafaq.org/gotchas.html)

Gravity's class system is inflexible compared to Lua where it has Multiple
Inheritance [https://github.com/limadm/lua-oo](https://github.com/limadm/lua-
oo) Prototypical OO [https://github.com/nusov/lua-
object](https://github.com/nusov/lua-object) or anything else you desire.

As for extending syntax and semantics, [http://lua-
users.org/wiki/MetatableEvents](http://lua-users.org/wiki/MetatableEvents)
provide a clean mechanism to do so.

Lua coroutines are more powerful than Gravity's fibers.

I was hoping that Gravity had pattern matching support, but it looks like it
does not.

Given that Lua has _more_ capabilities than Gravity could you substantiate

> Lua is much simpler than Gravity

In what ways?

~~~
lasagnaphil
You can create elaborate class systems using metatables in Lua; the problem is
that there are hundreds of them. I've done some Lua programming using Love2D,
and one of the painful parts was that a lot of the major libraries implemented
different class systems (or rolled one of their own), making it hard to
include in a single codebase. (At least Lisp has CLOS as its common class
system...) Also you can mitigate the "undeclared variable = nil" problem using
a script like strict.lua
([https://github.com/deepmind/strict/blob/master/strict.lua](https://github.com/deepmind/strict/blob/master/strict.lua)),
but when you try to expand that for field accesses you then want to make sure
all of those libraries with different class systems or methodologies are also
compatible with it (which a lot of the libraries do not).

The underlying problem with Lua is that it went too wild with the philosophy
of "being the most expressive using the least amount of features" (so you can
implement everything using only metatables). Although many would say that this
is a good thing, for me it seems better for a language to have some kind of
subset for which people can conform and rely on.

~~~
samatman
Lua provides only a meta-object protocol, without blessing a single class
system.

I prefer this. Its more Scheme-like, philosophically. I've seen your criticism
from many quarters and here's my guess at what happens: people come to Lua
from other languages, find missing abstractions, recreate them, and in the
process don't thoroughly learn the metamethod system.

Pure prototyping is a joy once you realize what all the moving parts are and
how many ways they can be usefully combined. This is my experience anyway.

------
th3iedkid
anyone using this can illustrate , how they use this ?

~~~
cmjqol
It's used for their tech called Creo [1] .

It looks a bit like Fuse Tools [2] , a tech designed for mobile designer that
bypass OS Specific UI API to directly draw on the phone using the GPU , sort
of similar to Flutter in core architecture.

[1]- [https://creolabs.com/](https://creolabs.com/) [2]-
[https://www.fusetools.com/](https://www.fusetools.com/)

------
amelius
Sounds not so light-weight.

------
caspervonb
Not to rain on your parade here but, in what world is a interpreter "fast and
efficient"? Embeddable, minimal footprint and zero external dependencies etc
are all excellent real selling points here.

~~~
uryga
IIRC, the K language's interpreter is/was really fast because it's tiny and
fits in the processor's cache.

~~~
willtim
A consequence of this is that the language has many severe limits. For
example, number of function parameters, number of local variables, amount of
code inside a conditional branch etc. Working around these limits can often
feel like being a human-compiler.

~~~
uryga
To be honest I just repeated back stuff I read about K, as I haven't gotten
into K enough to hit these limits. Commentary from someone with actual
experience is great, thanks!

------
carapace
Blank page with JS disabled.

------
PezzaDev
I don't see how a new language can claim to fast and efficient when it does
nothing to encourage data-oriented programming.

------
3rdAccount
So a language that transpiles to C similar to Nim I guess?

Could I use this on Windows and create small binary executables? Any examples
of this?

~~~
loa-in-backup
It's a virtual machine running some intermediate representation.

From github: "Gravity has been developed from scratch for the Creo project in
order to offer an easy way to write portable code for the iOS and Android
platforms. It is written in portable C code that can be compiled on any
platform using a C99 compiler. The VM code is about 2K lines long, the
multipass compiler code is about 3K lines and the shared code is about 2K
lines long. The compiler and virtual machine combined add less than 200KB to
the executable on a 64 bit system."

~~~
SlowRobotAhead
I find in annoying as an embedded engineer that “embedded” now mean phones
which are more powerful than the PCs most of used relatively recently.

Embedded to me means 8-32bit micros for real devices. Not PCs that happen to
fit in your pocket.

200kB is out for even a fairly serious cortex M4.

~~~
wtetzner
Embedded here means "embedded in another program".

~~~
SlowRobotAhead
Here I am looking for both!

