Terra: Low-level system programming language meta-programmed from Lua
terralang.org
terralang.org
I help maintain Terra, and also use it to build Regent, my distributed programming language[1].
A bit busy at the moment, but if you leave questions here I'll try to answer them (possibly in some hours).
[1]: regent-lang.org
I'll also add that we're always looking for new contributors. We're an 100% community run project, so everything is driven by people who care about things stepping in to do them. If you're interested in compiler technology, there's a wide variety of things to work on.
I've definitely got a long list of gripes with Lua... but they're not really enough to take on the additional maintenance burden.
Lua tying it all together means you have a tiny, dynamically typed language that can be embedded in lots of popular C based software, which can now be accelerated to (even more) incredible speed. I predict big things and wish them well.
Unfortunately, we have since discovered even more insane behavior: https://github.com/terralang/terra/issues/460
The language itself is performant and pleasant, but there are not enough people using it, so troubleshooting is really painful.
(I also help maintain Terra, but this answer is more focused on my capacity as a user.)
Terra is a workhorse and it gets the job done. Overall, compared to a previous iteration of Regent (that was built entirely from the ground up in Python), it's been a good experience. Having first-class code generation capabilities has been really nice, especially with built-in support for things like parsing C header files, vectorization, and CUDA code generation. The language is stable and generally doesn't have many surprises. Unlike, say, C++ or Rust, there aren't as any corners to hide odd behaviors. (Obviously, there still is some room for such things, as you can see in the sibling comments. But I still think it's better than most languages.)
The main issue is, as siblings have noted, the size of the community. While most stuff works, if you find something broken you're likely going to have to fix it yourself. This is an area where we're always looking to grow.
Appears to be going 1.0[1]!
[1] https://github.com/terralang/terra/commit/1ea278278c104580a0...
Output:
I hope this works out. C++ has been deliberately evolving in the same direction, e.g. using `if constexpr` for conditional compilation. Plus, since the C++ compiler is aware of both levels of the language, it can catch some errors even for compilation paths not taken.
But the C++ syntax for metaprogramming still leaves a fair bit to be desired. So I like that folks are still experimenting in this area.
local add1 = macro(function()
return `x+1
end)
terra()
var x = 12
add1()
end
Then this will give you an error because x is not in scope in the add1 macro.Instead you'd have to write:
local add1 = macro(function(y)
return `y+1
end)
terra()
var x = 12
add1(x)
end
Note that I changed the variable name to clarify that only the lexical scope matters (i.e., "x" is a symbol passed to the function as argument y).You should be able to create towers of languages in Terra. I'm not sure if anyone really does more than 2 levels in practice, but most of the common Terra DSLs are basically written as code generators on top of Terra language expressions.
See e.g. the Regent code generator. Here's an example of some nested metaprogramming---not with a nested language or macros, but with an escape that calls a Lua function to generate more code based on the type of the argument:
https://github.com/StanfordLegion/legion/blob/0cf9ddd60c227c...
Code inside a `terra` function is statically-typed and executed at runtime, while the rest of the code is just plain Lua and is executed at compiled time.
It's a really interesting idea and I'd be interested to try it for something like an X11 application.
Many years ago, someone wrote a Haskell library along the same lines that lets the library's user mimic assembly language with Haskell code. One thing I particularly liked about this library is that (by deviating a little from the standard way of indenting Haskell code) the user could mimic the 2 columns of assembly language. E.g., in
foo <- statement
statement2
bar <- statement3
"foo" and "bar" would be a labels, and that mimics the look of assembly language in that the leftmost 15 or so characters (columns) in an assembly-language file are usually reserved for labels. (I.e., if a line has no label, those 15 characters are blank.)Of course Terra functions can also be saved out to a file too, and if you do that they're free of any dependency on Lua (i.e., no need to like liblua*.so).
Code generation is already popular with popular C++ libraries like protobuf and in game dev.
How do you parse C/C++ header files so you can introspect their types or functions and take actions based on the results?
How do you write clean abstractions for code generation? Do you build your own C++ AST abstraction entirely from scratch? If not what do you use, and how much power does it expose (and what tradeoffs come with the level of power that you get)?
Terra lets you do all of these things in a clean way with well-defined, predictable semantics that don't leave you scratching your head when you get to 4 nested levels of macros and complex dynamic behavior that depends on program inputs.
You want the generated code to be low-level, because you want it to be fast, free of dependencies (interpreter, JIT, GC, etc.), and you care less about abstractions. You want the metaprogram to be high-level because you want nice abstractions, and it runs at compile-time anyway so you care less about performance.
Sure, people are working on languages that can do both, but it's easier to make it work with two different languages that can be tuned specifically to their niches.
You can also call back into Lua from the native code, and use it to generate more native code. You get back some of the cool self-modifying executable techniques of the days gone by, without having to completely YOLO it.
Dumb question: It was not clearly instruction-set specific; could Terra compile to webassembly? Would one want to?