Ember is a Go-native Luau-compatible scripting runtime for Hearth.
The long-term goal is not to mechanically translate Luau's C++ source into Go. The goal is to grow a small, testable Go implementation piece by piece, using upstream Luau as the behavioral reference and Hearth as the first host that proves the embedding API.
Ember currently has a tiny root-package vertical slice:
- a value model for nil, booleans, numbers, strings, host-visible tables, and opaque host userdata;
- internal bytecode for constants, globals, register moves, table fields and indexes, arithmetic, calls, and return;
- a minimal interpreter loop;
- a narrow
Compilepath for scalar local bindings, assignments to existing locals and chained table selectors, erased Luau type annotations, generic function type parameters,typeoftype queries, aliases, and casts, array, named-field, and computed-key table literals, chained dot-field and bracket reads,do/endlexical blocks,if/then/elseif/else/endcontrol flow with Luau truthiness,while/do/end,repeat/until, numericfor, and genericforloops over iterator expressions or direct table values with__iter,break, andcontinue, host-visible table mutation, host globals read and assigned as expression values, host callback calls through names or selector expressions as expressions or statements, method calls with receiver self-arguments, minimal local and anonymous closures with upvalues, table field and method function declarations, table metatables with table-valued and function-valued__indexand__newindex, function-valued__iterand__tostring, function-valued__call, arithmetic and concat metamethods including__unm, relational and equality metamethods, plus__metatableprotection, multiple return values and value-list adjustment for returns, local bindings, assignment, and final call arguments, variadic script functions with..., plus expressions joined by+,-,*,/,//,%,^,..,==,~=,<,<=,>,>=,and, oror,if/then/elseif/elseexpressions, unarynot, unary numeric-, unary length#, and parentheses for grouping; - a strict-mode
Checkfoothold that recognizes--!strictfile comments and retains an internal type tree with source ranges for the future typed-analysis path; - a tiny pure base-library foothold with
type,math,setmetatable,tonumber,tostring,getmetatable,next,pairs,ipairs,rawget,rawset, andrawlen, plusselect,unpack, andtable.pack/table.unpack,table.insert,table.remove,table.concat,table.find,table.clear, andtable.sort; - source-to-result tests such as
return 1 + 2, scalar literals, and local references.
This is only a seed. Full Luau grammar, full function syntax, broader standard libraries, and analyzer behavior remain future slices.
import "github.com/besmpl/ember"The root package should remain small. Future packages should exist only after a slice proves that the split makes the public interface smaller or the implementation easier to test.
Ember should be:
- Go-native, with ordinary Go values, errors, tests, and package structure;
- Luau-compatible where compatibility is claimed;
- deterministic enough for headless Hearth simulations;
- embeddable without hidden global runtime ownership;
- explicit about host callbacks, clocks, I/O, randomness, and cancellation;
- built in vertical slices that run real scripts or conformance fixtures.
Start with the small durable documentation set:
- docs/README.md
- docs/principles.md
- docs/design.md
- docs/compatibility.md
- docs/public-surface.md
- docs/hearth-integration.md
- docs/checks.md
The compatibility document is the maintained feature manifest: every claimed Luau slice points to at least one behavior test, and a package test checks that the referenced test names still exist.
Standing future-plan docs are intentionally not kept in the repository. When a slice needs coordination, write the smallest temporary plan that proves useful and retire or delete it when the slice lands or is abandoned.
scripts/check-fast
scripts/checkFor focused Go work, run package-local tests first, then use the scripts before calling a slice done.