Skip to content

oboard/moonbit-eval

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

343 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

MoonBit Eval

Version GitHub 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

Feature Status Description
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
Assignment โœ… Variable 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-else โœ… Conditional expressions
For loops โœ… C-style for loops with continue/break
While loops โœ… While loop constructs with else clause
Loop control โœ… Continue and break statements
Guard expressions โœ… guard condition else { action } syntax
Is expressions โœ… Pattern matching with 'is' operator
Defer expressions โœ… defer statement for cleanup code
Return expressions โœ… Early return from functions
Raise expressions โœ… Exception throwing with raise
Try-catch expressions โœ… Exception handling with try-catch
Loop expressions โœ… loop pattern matching with break/continue
Functions
Function definitions โœ… Named functions with parameters
Named parameters โœ… Named and optional parameters
Lambda expressions โœ… Anonymous functions (x => x * 2)
Closures โœ… Proper closure environment capture
Recursive functions โœ… Self-referencing function calls
Currying โœ… Higher-order function composition
External functions โœ… Integration with external calls
Embedded functions โœ… Native function integration
Data Structures
Arrays โœ… Array creation, indexing, assignment
Array methods โœ… length, get, push, pop, contains, slice, concat, join
Array boolean methods โœ… any, all operations
Array spread syntax โœ… [..array1, ..array2] syntax
Array slice operations โœ… arr[start:end], arr[start:], arr[:end] syntax
Array augmented assignment โœ… arr[i] += value, arr[i] *= value syntax
Tuples โœ… Tuple creation, access, destructuring
Structs โœ… Custom data types with methods
Mutable struct fields โœ… Field mutation support
Nested struct references โœ… Reference semantics for nested structures
Record update syntax โœ… { ..record, field: new_value } syntax
Map literals โœ… { "key": value } syntax for map creation
Pattern Matching
Basic patterns โœ… Constants, variables, wildcards
Tuple patterns โœ… Destructuring tuples
Array patterns โœ… Array destructuring
Record patterns โœ… Struct field matching
Range patterns โœ… Range expressions (_..<x, 'a'..='z')
Constructor patterns โœ… Constant constructor matching
Or patterns โœ… Multiple pattern alternatives
Nested patterns โœ… Complex nested pattern matching
Enums and Generics
Basic enums โœ… Simple enumeration types
Enums with data โœ… Algebraic data types
Enum pattern matching โœ… Pattern matching on enum variants
Generic types โœ… Generic enums and functions
Generic functions โœ… Polymorphic function definitions
Option Type
Option basics โœ… Some/None construction
Option pattern matching โœ… Pattern matching on Option
Option methods โœ… unwrap, unwrap_or, is_empty, map, filter
Built-in Methods
Bool methods โœ… compare, default
Int methods โœ… Bitwise ops, comparisons, bit manipulation
String methods โœ… length, get, unsafe_get, to_string
Double methods โœ… compare, to_int64
Char methods โœ… compare, to_int
Advanced Features
Type system โœ… Basic type checking and inference
Static method calls โœ… Class::method() syntax
Pipe operator โœ… |> operator for function chaining
Function aliases โœ… using @pkg {name} alias support
Cross-package method calls โœ… Method calls across different packages
Error handling โœ… Result type error handling
Group expressions โœ… Parenthesized expressions for precedence
For-in loops โœ… Iterator-based loops
Iterator methods โœ… iter, map, filter, reduce, for_each
Nested iteration โœ… Complex nested loop structures
Iterator control flow โœ… break/continue in iterator contexts
Package System
Module imports โœ… Explicit import { "package/path" } declarations and @package.function syntax
Cross-package types โœ… Using types from other packages
Built-in packages โœ… Builtin package is always loaded; other core packages load through explicit imports
Package method calling โœ… Method calls across package boundaries
Runtime modules โœ… Optional injected modules such as @eval/async.module()
IO and FFI
Print functions โœ… println and print support
Embedded functions โœ… Native function integration via FFI
External function binding โœ… Custom function registration
Sorting and Collections
List sorting โœ… Built-in sort methods for collections
Array sorting โœ… Sorting operations on arrays
Collection methods โœ… Comprehensive collection manipulation
Comparison Operations
Equality operators โœ… == and != operators
Relational operators โœ… <, >, <=, >= operators
Type-aware comparison โœ… Proper type checking in comparisons
Constructor Patterns
Single argument matching โœ… Constructor pattern with single args
Named field matching โœ… Constructor patterns with named fields
Wildcard patterns โœ… _ patterns in constructor matching
Functional Programming
Higher-order functions โœ… Functions as first-class values
Function composition โœ… Combining functions effectively
Closure environments โœ… Proper variable capture in closures
Literal Overloading
Numeric literal overloading โœ… Automatic conversion between numeric types
Character literal overloading โœ… Char to Int conversion in pattern matching
String literal overloading โœ… String to Bytes conversion
Array literal overloading โœ… Array to various types (Bytes, String) conversion
Double literal overloading โœ… Double to Float precision conversion
Map literal overloading โœ… Map to Json object conversion
Complex overloading scenarios โœ… Multi-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
#alias โœ… Function alias
#external โŒ External function binding
#callsite โŒ Call site information
#skip โŒ Skipping compilation of a function
#cfg โŒ Conditional 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

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors