{"id":20222374,"url":"https://github.com/capr/miniterra","last_synced_at":"2026-03-05T09:04:06.780Z","repository":{"id":190380572,"uuid":"580791127","full_name":"capr/miniterra","owner":"capr","description":":last_quarter_moon: A programming language derived from Terra that compiles to C","archived":false,"fork":false,"pushed_at":"2023-08-25T13:38:48.000Z","size":422,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-03T12:23:54.184Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Terra","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/capr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-12-21T13:09:48.000Z","updated_at":"2024-01-24T23:35:03.000Z","dependencies_parsed_at":"2023-08-24T11:53:11.258Z","dependency_job_id":null,"html_url":"https://github.com/capr/miniterra","commit_stats":null,"previous_names":["capr/miniterra"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/capr/miniterra","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capr%2Fminiterra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capr%2Fminiterra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capr%2Fminiterra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capr%2Fminiterra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/capr","download_url":"https://codeload.github.com/capr/miniterra/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capr%2Fminiterra/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30117498,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T08:19:04.902Z","status":"ssl_error","status_checked_at":"2026-03-05T08:17:37.148Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T06:56:19.682Z","updated_at":"2026-03-05T09:04:06.416Z","avatar_url":"https://github.com/capr.png","language":"Terra","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cb\u003eNOTE: Work-in-progress. Do not use yet!\u003c/b\u003e\n\n# Miniterra\n\nMiniterra is programming language derived from [Terra](https://terralang.org/)\nthat compiles to C. It works on Windows, Linux and Mac with LuaJIT 2.1 and GCC.\n\nIt differs from Terra in the following ways:\n\n### Language differences\n\n* reintroducing lazy typechecking, which unlocks some meta-programming use cases.\n* using Lua's scoping rules, which allows variable shadowing.\n* reintroducing automatic function overloading.\n* operator precedence is the same as in Lua.\n* operator `^` does `pow()` like in Lua.\n* operator `xor` was added.\n* different semantics for `__for`.\n* struct, field and function annotations.\n* nested functions with lexical scoping.\n* ++, +=, -=, *= /=, ^=, \u003e\u003e=, \u003c\u003c= assignment operators.\n\n### Runtime differences\n\n* can't import unsanitized C headers directly as there's no full-spec C parser.\n  * but you can use `ffi.cdef` headers and get a 10x speed-up over clang as a bonus.\n* can't call Terra code from Lua as there's no JIT compiler.\n  * but LuaJIT ffi bindings (cdefs and metatypes) can be auto-generated for\n    Terra functions so you can call into your Terra binaries from Lua directly.\n  * on the flip side, you don't have to ship the clang+LLVM 50 MB binary,\n    in fact you don't even have to ship lx and miniterra, just your compiled\n    Terra code, either as a shared library or as a static library to be\n    linked with your executable.\n\n# Building\n\nBinaries are included in the repo for Windows and Linux so you can skip this\nstep unless you're on a Mac, an old Linux or you don't trust the binaries.\n\nThe build script is for GCC. Use MSYS2 on Windows.\nFor OSX you can build on OSX or cross-compile from Linux.\n\nThe build command is:\n\n```\nsh c/build.sh\n```\n\nThe result is static and dynamic libraries in `bin/OS`.\n\n# Installation\n\nPut the Lua code from the `lua` dir in your Lua path.\n\nPut the dynamic libs from `bin/OS` where your LuaJIT exe is.\n\n# Using\n\n`foo_mt.mt` contains Terra code in Miniterra dialect:\n\n```Lua\nlocal foo = {}\n\nstruct Foo {\n   ...\n}\n\nterra new()\n   return malloc(sizeof(Foo))\nend\n\nterra Foo:free()\n   free(self)\nend\n\nterra Foo:bar()\n   ...\nend\n\nfunction foo:build()\n   local lib = miniterra.lib'foo'\n   lib:add(new)\n   lib:add(Foo)\n   lib:build()\nend\n\nreturn foo\n```\n\n`foo_build.lua` loads Miniterra and builds `foo_mt`:\n\n```Lua\nrequire'miniterra'\nlocal foo = require'foo_mt' --load `foo_mt.mt`\nfoo:build()\n```\n\nThis creates either `bin/windows/foo.dll`, `bin/linux/libfoo.so` or `bin/osx/libfoo.dylib`\ndepending on your OS and generates Lua bindings for it in `foo_h.lua`.\nFrom there you can use `foo_h` directly or create `foo.lua` manually\nand further Luaize the auto-generated binding, and use that:\n\n```Lua\nlocal foo = require'foo'\n\nlocal foo1 = foo.new()\nfoo1:bar()\nfoo1:free()\n```\n\n# Standard library\n\nMiniterra comes with a set of basic libraries to get you started:\n\n| Module | Description |\n|--------|-------------|\n| [miniterra.low           ](lua/miniterra/low.mt           ) | Lua+Terra standard library and low level tools |\n| [miniterra.arrayview     ](lua/miniterra/arrayview.mt     ) | Array view type |\n| [miniterra.dynarray      ](lua/miniterra/dynarray.mt      ) | Dynamic array type |\n| [miniterra.hashmap       ](lua/miniterra/hashmap.mt       ) | Hashmap type |\n| [miniterra.rawstringview ](lua/miniterra/rawstringview.mt ) | Raw string arrayview and dynarray type |\n| [miniterra.phf           ](lua/miniterra/phf.mt           ) | Perfect hash function generator |\n| [miniterra.linkedlist    ](lua/miniterra/linkedlist.mt    ) | self-allocated doubly-linked list |\n| [miniterra.fixedfreelist ](lua/miniterra/fixedfreelist.mt ) | Fixed-capacity freelist |\n| [miniterra.arrayfreelist ](lua/miniterra/arrayfreelist.mt ) | Freelist based on a dynamic array |\n| [miniterra.lrucache      ](lua/miniterra/lrucache.mt      ) | LRU cache, size-limited and count-limited |\n| [miniterra.bitarray      ](lua/miniterra/bitarray.mt      ) | 1-D and 2-D bit array type |\n| [miniterra.utf8          ](lua/miniterra/utf8.mt          ) | UTF-8 encoding and decoding |\n| [miniterra.random        ](lua/miniterra/random.mt        ) | Tausworthe PRNG |\n| [miniterra.memcheck      ](lua/miniterra/memcheck.mt      ) | Leak-checking allocator |\n\n# Implementation\n\nUnlike Terra which uses the LLVM C++ API to generate LLVM IR, miniterra\ngenerates C code which is then compiled with your favorite C compiler (gcc).\nWhile Terra is around 4 KLOC of C++ that leverages LLVM and STL, miniterra\nis written in Lua, based on a Lua lexer and parser library called `lx`.\n\n## Miniterra as an embedded language\n\n`lx` is a standalone library which allows embedding other languages inside\nLua, another [idea from Terra](https://terralang.org/api.html#embedding-new-languages-inside-lua).\nMiniterra is implemented as an embedded language based on this library.\nYou can use `lx` to implement your own embedded language that has nothing\nto do with Terra as long as its syntax is made only of Lua/Terra lexical\nunits and there's a clear set of keywords or tokens that mark the beginning\nof a statement or expression in the language.\n\n`lx` is made of two parts: a tokenizer which was taken from LuaJIT and\namounts to 1 KLOC of straightforward C, and a Lua parser written in Lua\nthat is more/less a translation of Lua's own parser which is a very hackable\nrecursive-descent parser with a simple way to handle operator precedence.\n\n`lx` adds a `require` loader that loads `.luax` files. Those are like normal\nLua modules except for the syntax `import'foo'` which you can use anywhere\nin the Lua code, in any scope, to load the embedded language `foo` in that\nscope. You can import multiple languages in the same Lua scope as long as\neach one uses different starting tokens.\n\nA language must be implemented in a Lua module with the same name. A language\nmodule must contain a function called `lang` that returns the keywords that\nthe language defines, the entrypoints for statements and for expressions,\nand a parser constructor that must return a parse function that will be called\nwhenever a statement or expression of the language is encountered.\n\nTake miniterra as an example:\n\n```Lua\nlocal mt = {} --miniterra module\n\nlocal function expression_function(lx) --parser constructor\n   local function bind()\n      -- call the bind functions returned by lx.luaexpr() here.\n      return val_of_name1, ...\n   end\n   return function(self, token, is_statement) --parse function\n      --in here, use lx to:\n      -- * consume the tokens of this statement or expression:\n      --    * use lx.next(), lx.lookahead(), etc.\n      -- * create lexical scopes and declare local symbols inside them:\n      --    * use lx.begin_scope(), lx.symbol(), lx.end_scope()\n      -- * parse embedded Lua expressions to be eval'ed later at bind time:\n      --    * use lx.luaexpr() which returns a bind function.\n      --    * Lua expressions will see your language's local symbols.\n      -- finally, return a bind function and the names of the locals that\n      -- this expression or statement defines. the bind function will be\n      -- called later and must return the values to assign to those names.\n      return bind, {name1, ...}\n   end\nend\n\nfunction mt.lang(lx)\n   return {\n      keywords = {'terra', 'quote', 'struct', 'var'},\n      entrypoints = {\n         statement = {'terra', 'struct'},\n         expression = {'`'},\n      },\n      expression = expression_function(lx),\n   }\nend\n\nreturn mt\n```\n\nThe parser constructor receives an `lx` object to be used by the parse\nfunction to consume the tokens of a particular statement or expression.\nThe parse function receives the starting token and a bool that tells whether\nthis is a statement or an expression. The parse function must consume all the\ntokens of a particular statement/expression using the `lx` object which\ncontains all the necessary functions for that.\n\n`lx` can also be used to parse and eval embedded Lua expressions that can\nappear inside your embedded language, if it makes sense for your language to\nsupport such a feature. In addition, you can tell `lx` to create nested\nlexical scopes and declare symbols within those scopes. Embedded Lua\nexpressions will then be able to reference those symbols as well as any\nlocals from the outer Lua scope. Miniterra uses this feature of `lx` to\nimplement escapes that can see both Terra vars from the surrounding Terra\nscope as well as Lua vars from the outer Lua scope. You can use this feature\nin your own embedded language if your language is lexically scoped and you\nwant to implement escaping to Lua in it with the ability to access symbols\nfrom the lexical scope of the escape.\n\n`lx` also contains an infix expression parser generator on which you can\nspecify operators (binary and prefix-unary), precedence levels and\nassociativity, so you don't have to roll your own.\n\n## Miniterra compilation stages\n\n1. **Lexing** - breaks text into a stream of tokens. Literals are parsed on demand.\n   Keywords are separated from other names. Comments are skipped.\n2. **Parsing** - consumes tokens and generates AST with binding slots in it.\n   Checks syntax. Parses expressions using operator precedence rules.\n   The input Lua code is patched such that embedded-language code is removed\n   and replaced with Lua code meant to resolve names and embedded Lua expressions.\n3. **Binding** - fills the binding slots in the AST by running the patched Lua\n   code which resolves names and embedded Lua expressions to either Terra\n   symbols or Lua values.\n4. **Typechecking** - typechecks assignments, operations and call args. Infers\n   types, selects overload variants.\n5. **Code gen** - generates C code, headers, and ffi bindings.\n6. **Build** - builds the generated C code.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapr%2Fminiterra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcapr%2Fminiterra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapr%2Fminiterra/lists"}