Skip to content

Repository files navigation

MoonBit Eval

VersionGitHub Workflow Status (with event)License

Demo

🚀 REPL Demo

🚀 Notebook Demo https://moonbit-notebook.oboard.fun/

Introduction

MoonBit Eval is an interpreter for the MoonBit language.

Built on top of the @moonbitlang/parser library, it provides comprehensive and accurate MoonBit syntax support, capable of correctly parsing and executing complex MoonBit code structures including functions, structs, lambdas, loops, and more.

Quick Start

let vm =MoonBitVM()
// Basic expressions
inspect(vm.eval("1 + 2 * 3"), content="7")
inspect(vm.eval("\"hello\" + \" world\""), content="hello world")
// Variables and functions
inspect(vm.eval("let x = 42"), content="()")
inspect(vm.eval("fn double(n: Int) -> Int { n * 2 }"), content="(n: Int) -> Int")
inspect(vm.eval("double(x)"), content="84")
// Control flow
inspect(vm.eval("if x > 40 { \"big\" } else { \"small\" }"), content="big")
// Pattern matching
inspect(vm.eval("match (1, 2) { (a, b) => a + b }"), content="3")
// Using aliases (new parser style)
inspect(vm.eval("using @int {abs}"), content="()")
inspect(vm.eval("abs(-5)"), content="5")

Compile and Run

Use compile when the same code needs to run repeatedly. Parsing happens once, and each run executes the compiled code against the VM you pass in.

let vm =MoonBitVM()
let expr = vm.compile("x + y * 2", params=["x", "y"])
inspect(
expr.run(vm, args=[3, 4]),
content="11",
)
inspect(
expr.run(vm, args=[10, 1]),
content="12",
)

Compiled parameters are bound in a temporary scope, so they do not leak into the VM global environment after execution.

Imports and Package Loading

eval accepts top-level expressions directly, with or without fn main. Import declarations can appear before either form.

let vm =MoonBitVM()
inspect(
vm.eval(
(
#|import {
#| "moonbitlang/core/list"
#|}
#|@list.from_array([1, 2, 3])
),
),
content="More(1, tail=More(2, tail=More(3, tail=Empty)))",
)

Core packages are loaded on demand. moonbitlang/core/builtin is always available, but other core packages such as moonbitlang/core/list must be imported explicitly before using their package aliases.

Runtime Modules

Optional runtime modules can be injected when constructing a VM. They register packages and embedded runtime functions without loading every package into the current eval scope.

let vm =MoonBitVM(modules=[@eval/async.module()])

The async module makes the root @async package available. Subpackages are lazy-loaded and must be imported explicitly:

inspect(
vm.test_all(
(
#|import { "moonbitlang/async/http" }
#|async test "https request" {
#| let (response, body) = @async.retry(FixedDelay(250), max_retry=3, () => {
#| @async.with_timeout(3000, () => @http.get("https://www.moonbitlang.com"))
#| })
#| assert_true(response.code is (200..<300), msg=response.code.to_string())
#| assert_true(body.text().to_lower().has_prefix("<!doctype html>"), msg=body.text())
#|}
),
),
content="TestResult(total=1, passed=1, failed=0)",
)

vm.test_all(code) runs top-level test and async test blocks and returns a TestResult summary instead of swallowing assertion failures.

Parser Notes

  • eval parses code through a compatibility wrapper around moonbitlang/parser.
  • Top-level expressions are supported directly, so users do not need to wrap snippets in fn main.
  • Full top-level code with declarations and fn main remains supported.
  • Diagnostics from parser reports are preserved and returned in Err(...) when parse fails.

✨ Features

  • 🥮 Mooncakes Loader: Load Mooncakes packages at runtime
  • Builtin FileSystem Library: Provides basic file system operations.
  • Eval Function: Allows dynamic evaluation of MoonBit code strings.

MoonBit Language Support

FeatureStatusDescription
Core Language
Basic Types (Int, Bool, String, Double, Char)Full support for primitive types
Expressions (arithmetic, logical, comparison)Complete expression evaluation
Variables (let, let mut)Immutable and mutable variables
AssignmentVariable reassignment and shadowing
Multiline strings#|syntax for multiline string literals
String interpolation{variable} syntax in string literals
Type constraints(value : Type) syntax for explicit typing
Control Flow
If-elseConditional expressions
For loopsC-style for loops with continue/break
While loopsWhile loop constructs with else clause
Loop controlContinue and break statements
Guard expressionsguard condition else { action } syntax
Is expressionsPattern matching with 'is' operator
Defer expressionsdefer statement for cleanup code
Return expressionsEarly return from functions
Raise expressionsException throwing with raise
Try-catch expressionsException handling with try-catch
Loop expressionsloop pattern matching with break/continue
Functions
Function definitionsNamed functions with parameters
Named parametersNamed and optional parameters
Lambda expressionsAnonymous functions (x => x * 2)
ClosuresProper closure environment capture
Recursive functionsSelf-referencing function calls
CurryingHigher-order function composition
External functionsIntegration with external calls
Embedded functionsNative function integration
Data Structures
ArraysArray creation, indexing, assignment
Array methodslength, get, push, pop, contains, slice, concat, join
Array boolean methodsany, all operations
Array spread syntax[..array1, ..array2] syntax
Array slice operationsarr[start:end], arr[start:], arr[:end] syntax
Array augmented assignmentarr[i] += value, arr[i] *= value syntax
TuplesTuple creation, access, destructuring
StructsCustom data types with methods
Mutable struct fieldsField mutation support
Nested struct referencesReference semantics for nested structures
Record update syntax{ ..record, field: new_value } syntax
Map literals{ "key": value } syntax for map creation
Pattern Matching
Basic patternsConstants, variables, wildcards
Tuple patternsDestructuring tuples
Array patternsArray destructuring
Record patternsStruct field matching
Range patternsRange expressions (_..<x, 'a'..='z')
Constructor patternsConstant constructor matching
Or patternsMultiple pattern alternatives
Nested patternsComplex nested pattern matching
Enums and Generics
Basic enumsSimple enumeration types
Enums with dataAlgebraic data types
Enum pattern matchingPattern matching on enum variants
Generic typesGeneric enums and functions
Generic functionsPolymorphic function definitions
Option Type
Option basicsSome/None construction
Option pattern matchingPattern matching on Option
Option methodsunwrap, unwrap_or, is_empty, map, filter
Built-in Methods
Bool methodscompare, default
Int methodsBitwise ops, comparisons, bit manipulation
String methodslength, get, unsafe_get, to_string
Double methodscompare, to_int64
Char methodscompare, to_int
Advanced Features
Type systemBasic type checking and inference
Static method callsClass::method() syntax
Pipe operator|> operator for function chaining
Function aliasesusing @pkg {name} alias support
Cross-package method callsMethod calls across different packages
Error handlingResult type error handling
Group expressionsParenthesized expressions for precedence
For-in loopsIterator-based loops
Iterator methodsiter, map, filter, reduce, for_each
Nested iterationComplex nested loop structures
Iterator control flowbreak/continue in iterator contexts
Package System
Module importsExplicit import { "package/path" } declarations and @package.function syntax
Cross-package typesUsing types from other packages
Built-in packagesBuiltin package is always loaded; other core packages load through explicit imports
Package method callingMethod calls across package boundaries
Runtime modulesOptional injected modules such as @eval/async.module()
IO and FFI
Print functionsprintln and print support
Embedded functionsNative function integration via FFI
External function bindingCustom function registration
Sorting and Collections
List sortingBuilt-in sort methods for collections
Array sortingSorting operations on arrays
Collection methodsComprehensive collection manipulation
Comparison Operations
Equality operators== and != operators
Relational operators<, >, <=, >= operators
Type-aware comparisonProper type checking in comparisons
Constructor Patterns
Single argument matchingConstructor pattern with single args
Named field matchingConstructor patterns with named fields
Wildcard patterns_ patterns in constructor matching
Functional Programming
Higher-order functionsFunctions as first-class values
Function compositionCombining functions effectively
Closure environmentsProper variable capture in closures
Literal Overloading
Numeric literal overloadingAutomatic conversion between numeric types
Character literal overloadingChar to Int conversion in pattern matching
String literal overloadingString to Bytes conversion
Array literal overloadingArray to various types (Bytes, String) conversion
Double literal overloadingDouble to Float precision conversion
Map literal overloadingMap to Json object conversion
Complex overloading scenariosMulti-step type conversions
Traits🟡Interface definitions
Trait as expressions🟡(value as Trait) syntax for trait casting
Packages🟡Module system with @package.function syntax (no trait, trait derive, operator overloading)
Attribute
#aliasFunction alias
#externalExternal function binding
#callsiteCall site information
#skipSkipping compilation of a function
#cfgConditional compilation based on configuration
Not Yet Supported
Async/await🟡Async tests and selected moonbitlang/async APIs through explicit runtime module injection

Contributing

We welcome contributions to the MoonBit Eval project! Whether it's bug fixes, feature additions, or documentation improvements, your contributions are valuable.

Community

Join our community for discussions and support:

  • QQ Group: 949886784

QQ 群

About

MoonBit language interpreter

Topics

Resources

Stars

19 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages