This project implements a port of Lua 5.4 to MoonBit using spec-driven development methodology.
lua.mbt/
├── moon.mod.json # Module configuration
├── README.md # This file
│
├── value/ # Core Value System
│ ├── moon.pkg.json
│ ├── value_spec.mbt # TValue tagged value types
│ └── value_basic_test.mbt
│
├── opcodes/ # VM Instruction Format
│ ├── moon.pkg.json
│ ├── opcodes_spec.mbt # 32-bit instruction encoding
│ └── opcodes_basic_test.mbt
│
├── lex/ # Lexical Analysis
│ ├── moon.pkg.json
│ ├── lex_spec.mbt # Tokenizer
│ └── lex_basic_test.mbt
│
├── parse/ # Syntax Analysis
│ ├── moon.pkg.json
│ ├── parse_spec.mbt # Parser (tokens → AST)
│ └── parse_basic_test.mbt
│
├── compile/ # Code Generation
│ ├── moon.pkg.json
│ ├── compile_spec.mbt # Compiler (AST → bytecode)
│ └── compile_basic_test.mbt
│
├── state/ # VM State Management
│ ├── moon.pkg.json
│ ├── state_spec.mbt # Stack, globals, call frames
│ └── state_basic_test.mbt
│
├── vm/ # Virtual Machine
│ ├── moon.pkg.json
│ ├── vm_spec.mbt # Bytecode executor
│ └── vm_basic_test.mbt
│
├── gc/ # Garbage Collector
│ ├── moon.pkg.json
│ ├── gc_spec.mbt # Tri-color marking GC
│ └── gc_basic_test.mbt
│
├── stdlib/ # Standard Library
│ ├── moon.pkg.json
│ ├── stdlib_spec.mbt # print, type, math.*, string.*
│ └── stdlib_basic_test.mbt
│
└── api/ # C API Compatibility
├── moon.pkg.json
├── api_spec.mbt # Embedding interface
└── api_basic_test.mbt
Lua Source Code
↓
[lex] → Tokens
↓
[parse] → AST
↓
[compile] → Bytecode (Proto)
↓
[vm] ← → [state] ← → [value]
↓ ↓ ↓
[stdlib] [gc] [api]
value (no dependencies - foundation)
↓
opcodes (no dependencies)
↓
lex (no dependencies)
↓
parse (depends on: lex, value)
↓
state (depends on: value)
↓
vm (depends on: value, opcodes, state)
↓
compile (depends on: parse, opcodes, value, vm)
↓
stdlib (depends on: value, state)
gc (depends on: value)
api (depends on: all above)
Each package follows the spec-driven development pattern:
- Specification files (
*_spec.mbt) - Define the public API contract using#declaration_only - Test files (
*_test.mbt) - Type-checked tests that validate the spec (before implementation) - Implementation files - To be created in separate files within the same package
✅ All specification files created (10 packages)
✅ Basic test suites written for each package
✅ moon check passes - all specs type-check correctly
✅ 29 source files created
⏳ Implementation pending
- Error Handling - Uses MoonBit's
raisesystem with typed errors instead of C's error codes - Type System - Leverages MoonBit's enum and struct with derivation (Eq, Show, ToJson)
- Memory Management - MoonBit's GC instead of Lua's manual memory management
- Package Organization - Logical separation following Lua's architecture but adapted to MoonBit's module system
- Maintains Lua 5.4 semantics for values, operators, and control flow
- Register-based VM with 32-bit instruction format (compatible with Lua 5.x)
- Standard library functions match Lua's behavior
- C API layer provides embedding compatibility
LuaTypeenum: Nil, Boolean, Number, String, Table, Function, Userdata, ThreadTValuetype: Tagged value with type-safe operations- Operations: type checking, conversion, comparison, equality
OpCodeenum: 40+ VM opcodes (Move, LoadK, Add, Sub, Call, etc.)OpModeenum: Instruction formats (ABC, ABx, AsBx, Ax, SJ)Instructiontype: 32-bit instruction encoding/decoding
TokenTypeenum: 70+ token types (keywords, operators, literals)Tokenstruct: Token with position informationLexertype: Stateful tokenizer
Exprenum: Expression AST nodes (literals, operators, calls, tables)Stmtenum: Statement AST nodes (blocks, loops, conditions, functions)Parsertype: Recursive descent parser
Compilertype: Stateful code generatorcompile()function: One-shot compilation
LuaStatetype: VM state with stack and globals- Operations: push/pop, stack indexing, global variables
Prototype: Function prototype (bytecode + constants)execute()function: Bytecode executionexecute_instruction()function: Single instruction execution
GCtype: Garbage collector stateGCColorenum: White, Gray, Black (tri-color marking)- Operations: allocate, mark, collect
- Basic: print, type, tonumber, tostring, assert
- Math: abs, floor, ceil, sqrt
- String: len, sub, upper, lower
LuaAPItype: C-compatible embedding interface- Stack operations: push/pop values
- Execution: load_string, pcall
- Globals: get_global, set_global
-
value/ - Foundation for everything else
- Implement TValue as a tagged union
- Implement type checking and conversion
-
opcodes/ - Instruction encoding
- Implement instruction bit manipulation
- Implement opcode mode lookup
-
lex/ - Front-end (part 1)
- Implement tokenizer state machine
- Handle keywords, operators, literals
-
parse/ - Front-end (part 2)
- Implement recursive descent parser
- Build AST from tokens
-
state/ - Runtime foundation
- Implement stack-based register file
- Implement global variable storage
-
compile/ - Code generation
- Implement AST → bytecode translation
- Generate function prototypes
-
vm/ - Execution engine
- Implement instruction dispatch loop
- Implement arithmetic, control flow, etc.
-
gc/ - Memory management
- Implement tri-color marking
- Implement sweep phase
-
stdlib/ - Core functions
- Implement basic library functions
- Register into global environment
-
api/ - Embedding interface
- Wrap state/vm in C-compatible API
- Implement error handling
# Type-check all specs and tests
moon check
# Run tests (after implementation)
moon test
# Run specific package tests
moon test value/
moon test vm/
# Update test snapshots
moon test --update- Choose a package to implement (start with
value/) - Read the spec file to understand the API contract
- Create implementation files in the same package directory (e.g.,
value_impl.mbt) - Implement the
#declaration_onlyfunctions and types - Run
moon testto validate against the spec tests - Add more comprehensive tests as needed
- Run
moon checkto ensure no type errors
- Original Lua 5.4 source:
refs/lua/ - Lua 5.4 manual: https://www.lua.org/manual/5.4/
- MoonBit documentation: https://www.moonbitlang.com/docs/
- MoonBit tour: https://tour.moonbitlang.com/
When implementing a package:
- Follow the spec exactly - don't change the API
- Add implementation files alongside spec files
- Write additional tests for edge cases
- Document complex algorithms with comments
- Use
///|to delimit top-level items - Prefer functional style (immutable by default)
- Use
derive(Eq, Show, ToJson)for debugging support