Generate MiniMoonBit Programs randomly.
# 更新依赖
moon update
# 添加mbtsmith包
moon add Kaida-Amethyst/mbtsmith{
"import" : ["Kaida-Amethyst/mbtsmith"]
}fn main {
let generator = @mbtsmith.RandProgGenerator::new()
let prog = generator.gen_program()
println(prog)
}pub fn RandProgGenerator::new(seed~:Int? = None) -> RandProgGeneratorpub fn RandProgGenerator::gen_program(self: Self) -> Programpub fn RandProgGenerator::gen_top_decl(self: Self) -> TopDecl
pub fn RandProgGenerator::gen_top_let(self: Self) -> TopLet
pub fn RandProgGenerator::gen_top_func_def(self: Self) -> TopFuncDef
pub fn RandProgGenerator::gen_struct_def(self: Self) -> StructDef
pub fn RandProgGenerator::gen_enum_def(self: Self) -> EnumDef
pub fn RandProgGenerator::gen_main_func(self: Self) -> TopFuncDeffn main {
// 创建生成器
let generator = @mbtsmith.RandProgGenerator::new()
// 生成完整程序
let program = generator.gen_program()
// 输出程序代码
println(program)
}fn main {
// 使用种子42创建生成器,相同的种子生成相同的程序,如果不给seed参数,默认为0。
let generator = @mbtsmith.RandProgGenerator::new(seed=Some(42))
let program = generator.gen_program()
println(program)
}fn main {
let generator = @mbtsmith.RandProgGenerator::new()
// 生成单个结构体定义
let struct_def = generator.gen_struct_def()
println("Struct: \{struct_def}")
// 生成单个函数定义
let func_def = generator.gen_top_func_def()
println("Function: \{func_def}")
}# 生成测试程序
moon run main > test_program.mbt
# 使用MoonBit检查语法正确性,--warn-list -A消除所有警告
moon check --warn-list -A test_program.mbt
# 使用你的MiniMoonbit编译器进行测试
your_compiler test_program.mbtgrammar MiniMoonBit;
prog: top_level* EOF;
// Top-level
//
// Top level declarations should start at the beginning of the line, i.e.
// token.column == 0. Since this is non-context-free, it is not included in this
// backend-agnostic ANTLR grammar.
top_level: top_let_decl | toplevel_fn_decl | struct_decl | enum_decl;
top_let_decl:
'let' IDENTIFIER (':' type)? '=' expr ';';
toplevel_fn_decl: (main_fn_decl | top_fn_decl);
// Function declarations
//
// `fn main` does not accept parameters and return type
main_fn_decl: 'fn' 'main' fn_body;
top_fn_decl:
'fn' ('[' UPPER_IDENTIFIER ']')? IDENTIFIER '(' param_list? ')' '->' type fn_body;
param_list: param (',' param)*;
param: IDENTIFIER type_annotation;
fn_body: '{' stmt* expr? '}';
struct_decl:
'struct' UPPER_IDENTIFIER ('[' UPPER_IDENTIFIER ']')? '{' struct_field_list? '}';
struct_field_list:
struct_field (';' struct_field)* ';'?;
struct_field:
IDENTIFIER type_annotation;
enum_decl:
'enum' UPPER_IDENTIFIER ('[' UPPER_IDENTIFIER ']')? '{' enum_variant_list? '}';
enum_variant_list:
enum_variant (';' enum_variant)* ';'?;
enum_variant:
UPPER_IDENTIFIER ('(' enum_variant_field_list? ')')?;
enum_variant_field_list:
type (',' type)*;
nontop_fn_decl:
'fn' IDENTIFIER '(' nontop_param_list? ')' (
'->' type
)? fn_body;
nontop_param_list:
nontop_param (',' nontop_param)*;
nontop_param: IDENTIFIER type_annotation?;
// Statements
stmt:
let_tuple_stmt
| let_mut_stmt
| let_stmt
| fn_decl_stmt
| assign_stmt
| while_stmt
| return_stmt
| expr_stmt;
binding: IDENTIFIER | WILDCARD ;
let_tuple_stmt:
'let' '(' binding (',' binding)* ')' type_annotation? '=' expr ';' ;
let_mut_stmt:
'let' 'mut' IDENTIFIER type_annotation? '=' expr ';';
let_stmt:
'let' binding type_annotation? '=' expr ';';
type_annotation: COLON type;
fn_decl_stmt: nontop_fn_decl;
// x[y] = z;
assign_stmt: left_value '=' expr ';';
// while x { ... }
while_stmt: 'while' expr '{' stmt* '}';
return_stmt:
'return' expr? ';' ;
expr_stmt: expr ';';
left_value:
IDENTIFIER
| left_value '.' IDENTIFIER
| left_value '[' expr ']';
// Expressions, in order of precedence.
expr: // not associative
or_level_expr;
or_level_expr: // left associative
or_level_expr OR and_level_expr
| and_level_expr;
and_level_expr: // left associative
and_level_expr AND cmp_level_expr
| cmp_level_expr;
cmp_level_expr: // not associative
add_sub_level_expr CMP_OPERATOR add_sub_level_expr
| add_sub_level_expr;
add_sub_level_expr: // left associative
add_sub_level_expr '+' mul_div_level_expr
| add_sub_level_expr '-' mul_div_level_expr
| mul_div_level_expr;
mul_div_level_expr: // left associative
mul_div_level_expr '*' if_level_expr
| mul_div_level_expr '/' if_level_expr
| mul_div_level_expr '%' if_level_expr
| if_level_expr;
if_level_expr: get_or_apply_level_expr | if_expr | match_expr;
if_expr: 'if' expr block_expr ('else' (if_expr | block_expr))?;
match_expr: 'match' expr '{' match_arm_list '}';
match_arm_list:
match_arm (';' match_arm)* ';'?;
match_arm:
pattern '=>' expr;
pattern:
NUMBER
| 'true'
| 'false'
| '(' pattern (',' pattern)* ')' // Tuple pattern
| WILDCARD // Wildcard pattern
| IDENTIFIER // Variable pattern
| (UPPER_IDENTIFIER '::')? UPPER_IDENTIFIER ('(' pattern ( ',' pattern )* ')')?; // Enum variant pattern
get_or_apply_level_expr:
value_expr (
'[' expr ']'
| '(' (expr (',' expr)*)? ')'
| '.' IDENTIFIER
)*;
// Value expressions
value_expr:
array_make_expr
| struct_construct_expr // eg: Point::{ x: 1, y: 2 }
| enum_construct_expr // eg: Point(1, 2)
| unit_expr
| group_expr
| tuple_expr
| array_expr
| bool_expr
| identifier_expr
| block_expr
| neg_expr
| floating_point_expr
| int_expr
| not_expr;
unit_expr: '(' ')'; // ()
group_expr: '(' expr ')'; // (x)
tuple_expr:
'(' expr (',' expr)+ ')'; // (x, y); 1-tuple is not allowed
array_expr:
'[' expr (',' expr)* ']'; // [x, y, z]
block_expr: '{' stmt* expr? '}'; // { blah; blah; }
bool_expr: 'true' | 'false';
neg_expr: '-' value_expr;
floating_point_expr: NUMBER '.' NUMBER?; // 1.0 | 1.
int_expr: NUMBER; // 1
not_expr: '!' expr ; // !x
array_make_expr:
ARRAY '::' 'make' '(' expr ',' expr ')'; // Array::make(x, y)
struct_construct_expr:
UPPER_IDENTIFIER '::' '{' struct_field_expr_list? '}'; // Point::{ x: 1, y: 2 }
struct_field_expr_list:
struct_field_expr (',' struct_field_expr)*;
struct_field_expr:
IDENTIFIER ':' expr; // x: 1
enum_construct_expr:
(UPPER_IDENTIFIER '::')? UPPER_IDENTIFIER ('(' enum_construct_field_list? ')')?;
enum_construct_field_list:
expr (',' expr)*; // Point(1, 2)
identifier_expr: IDENTIFIER;
// Types
type:
'Unit'
| 'Bool'
| 'Int'
| 'Double'
| array_type
| tuple_type
| function_type
| user_defined_type // User-defined type
| generic_type; // Generic type, e.g. [T]
array_type: 'Array' '[' type ']';
tuple_type: '(' type (',' type)* ')'; // (Int, Bool)
function_type:
'(' type (',' type)* ')' '->' type; // (Int, Bool) -> Int
generic_type: UPPER_IDENTIFIER '[' type ']'; // [T]
user_defined_type: UPPER_IDENTIFIER;
// Tokens
TRUE: 'true';
FALSE: 'false';
UNIT: 'Unit';
BOOL: 'Bool';
INT: 'Int';
DOUBLE: 'Double';
ARRAY: 'Array';
NOT: 'not';
IF: 'if';
ELSE: 'else';
FN: 'fn';
LET: 'let';
NUMBER: [0-9]+;
UPPER_IDENTIFIER: [A-Z][a-zA-Z0-9_]*;
WILDCARD: '_';
IDENTIFIER: [a-zA-Z_][a-zA-Z0-9_]*;
CMP_OPERATOR: '==' | '!=' | '>=' | '<=' | '<' | '>';
AND: '&&';
OR: '||';
DOT: '.';
ADD: '+';
SUB: '-';
MUL: '*';
DIV: '/';
ASSIGN: '=';
LPAREN: '(';
RPAREN: ')';
LBRACKET: '[';
RBRACKET: ']';
LCURLYBRACKET: '{';
RCURLYBRACKET: '}';
ARROW: '->';
COLON: ':';
SEMICOLON: ';';
COMMA: ',';
WS: [ \t\r\n]+ -> skip;
COMMENT: '//' ~[\r\n]* -> skip;let complex = ValueExpr::IdentExpr(Ident("complex"));
let complex = ApplyExpr::ValueExpr(complex);
inspect(complex, content="complex")
let arr = ValueExpr::IdentExpr(Ident("arr"));
let arr = ApplyExpr::ValueExpr(arr);
inspect(arr, content="arr")
let add = ValueExpr::IdentExpr(Ident("add"));
let add = ApplyExpr::ValueExpr(add);
inspect(add, content="add")
let i1 = ValueExpr::IntExpr(1);
let i1 = ApplyExpr::ValueExpr(i1);
inspect(i1, content="1");
let i1 = IfLevelExpr::ApplyExpr(i1);
let i1 = Expr::IfLevelExpr(i1);
let i42 = ValueExpr::IntExpr(42);
let i42 = ApplyExpr::ValueExpr(i42);
inspect(i42, content="42");
let i42 = IfLevelExpr::ApplyExpr(i42);
let i42 = Expr::IfLevelExpr(i42);
inspect(ApplyExpr::ArrAcc(arr, i1), content="arr[1]")
inspect(ApplyExpr::DotAcc(complex, Ident("y")), content="complex.y")
inspect(ApplyExpr::Call(add, [i1, i42]), content="add(1, 42)")// Simple block with just statements
let i42 = ValueExpr::IntExpr(42);
let i42 = ApplyExpr::ValueExpr(i42);
let i42 = IfLevelExpr::ApplyExpr(i42);
let i42 = Expr::IfLevelExpr(i42);
let stmt = Stmt::Let(Ident("x"), None, i42);
let block1 = BlockExpr::new()
block1.push(stmt);
let expect1 =
#|{
#| let x = 42;
#|}
inspect(block1, content=expect1)
// Block with statements and final expression
let y_val = ValueExpr::IntExpr(100);
let y_val = ApplyExpr::ValueExpr(y_val);
let y_val = IfLevelExpr::ApplyExpr(y_val);
let y_val = Expr::IfLevelExpr(y_val);
let stmt2 = Stmt::Let(Ident("y"), None, y_val);
let final_expr = ValueExpr::IdentExpr(Ident("y"));
let final_expr = ApplyExpr::ValueExpr(final_expr);
let final_expr = IfLevelExpr::ApplyExpr(final_expr);
let final_expr = Expr::IfLevelExpr(final_expr);
let block2 = BlockExpr::new(last_expr = Some(final_expr));
block2.push(stmt2);
let expect2 =
#|{
#| let y = 100;
#| y
#|}
inspect(block2, content=expect2)
// Empty block
let empty_block = BlockExpr::new()
inspect(empty_block, content="{\n}")pub(all) enum CmpOp {
Eq
Ne
Lt
Le
Gt
Ge
}pub(all) enum Either[L, R] {
Left(L)
Right(R)
}// Simple enum without generic parameters and with various variant types
let variants1 : Array[(Upper, Array[Type])] = [
("Red", []),
("Green", []),
("Blue", []),
("RGB", [Int, Int, Int])
];
let enum1 = EnumDef::{
generic_param: None,
name: Upper("Color"),
variants: variants1
};
let expect1 =
#|enum Color {
#| Red
#| Green
#| Blue
#| RGB(Int, Int, Int)
#|}
inspect(enum1, content=expect1)
// Generic enum with type parameter
let variants2 : Array[(Upper, Array[Type])] = [
("None", []),
("Some", [GenericDef("T")])
];
let enum2 = EnumDef::{
generic_param: Some(Upper("T")),
name: Upper("Option"),
variants: variants2
};
let expect2 =
#|enum Option[T] {
#| None
#| Some(T)
#|}
inspect(enum2, content=expect2)
// Empty enum
let enum3 = EnumDef::{
generic_param: None,
name: Upper("Never"),
variants: []
};
inspect(enum3, content="enum Never {}\n")let x = ValueExpr::IdentExpr(Ident("x"));
let y = ValueExpr::IdentExpr(Ident("y"));
let i42 = ValueExpr::IntExpr(42);
let i73 = ValueExpr::IntExpr(73);
let f22 = ValueExpr::FloatExpr(22.0);
let f89 = ValueExpr::FloatExpr(89.0);
let bool_true = ValueExpr::BoolExpr(true);
let bool_false = ValueExpr::BoolExpr(false);
let x = ApplyExpr::ValueExpr(x);
let x = IfLevelExpr::ApplyExpr(x);
let x = Expr::IfLevelExpr(x);
let y = ApplyExpr::ValueExpr(y);
let y = IfLevelExpr::ApplyExpr(y);
let y = Expr::IfLevelExpr(y);
let i42 = ApplyExpr::ValueExpr(i42);
let i42 = IfLevelExpr::ApplyExpr(i42);
let i42 = Expr::IfLevelExpr(i42);
let i73 = ApplyExpr::ValueExpr(i73);
let i73 = IfLevelExpr::ApplyExpr(i73);
let i73 = Expr::IfLevelExpr(i73);
let f22 = ApplyExpr::ValueExpr(f22);
let f22 = IfLevelExpr::ApplyExpr(f22);
let f22 = Expr::IfLevelExpr(f22);
let f89 = ApplyExpr::ValueExpr(f89);
let f89 = IfLevelExpr::ApplyExpr(f89);
let f89 = Expr::IfLevelExpr(f89);
let bool_true = ApplyExpr::ValueExpr(bool_true);
let bool_true = IfLevelExpr::ApplyExpr(bool_true);
let bool_true = Expr::IfLevelExpr(bool_true);
let bool_false = ApplyExpr::ValueExpr(bool_false);
let bool_false = IfLevelExpr::ApplyExpr(bool_false);
let bool_false = Expr::IfLevelExpr(bool_false);
inspect(Expr::AndExpr(bool_false, y), content="false && y")
inspect(Expr::OrExpr(x, bool_true), content="x || true")
inspect(Expr::CmpExpr(Eq, x, y), content="x == y")
inspect(Expr::CmpExpr(Ne, x, y), content="x != y")
inspect(Expr::CmpExpr(Lt, i42, i73), content="42 < 73")
inspect(Expr::CmpExpr(Le, i42, i73), content="42 <= 73")
inspect(Expr::CmpExpr(Gt, i73, i42), content="73 > 42")
inspect(Expr::CmpExpr(Ge, i73, i42), content="73 >= 42")
inspect(Expr::AddExpr(i42, i73), content="42 + 73")
inspect(Expr::SubExpr(i73, i42), content="73 - 42")
inspect(Expr::MulExpr(i42, i73), content="42 * 73")
inspect(Expr::DivExpr(i73, i42), content="73 / 42")
inspect(Expr::ModExpr(i73, i42), content="73 % 42")pub(all) type Ident Stringlet cond = ValueExpr::BoolExpr(true);
let cond = ApplyExpr::ValueExpr(cond);
let cond = IfLevelExpr::ApplyExpr(cond);
let cond = Expr::IfLevelExpr(cond);
let x_val = ValueExpr::IntExpr(42);
let x_val = ApplyExpr::ValueExpr(x_val);
let x_val = IfLevelExpr::ApplyExpr(x_val);
let x_val = Expr::IfLevelExpr(x_val);
let y_val = ValueExpr::IntExpr(24);
let y_val = ApplyExpr::ValueExpr(y_val);
let y_val = IfLevelExpr::ApplyExpr(y_val);
let y_val = Expr::IfLevelExpr(y_val);
let then_block = BlockExpr::new(last_expr=Some(x_val));
let else_block = BlockExpr::new(last_expr=Some(y_val));
let if_expr = IfExpr::{ cond, then_: then_block, else_: Right(else_block) };
let expect =
#|if true {
#| 42
#|} else {
#| 24
#|}
inspect(if_expr, content=expect)let x = ValueExpr::IdentExpr(Ident("x"));
let x = ApplyExpr::ValueExpr(x);
inspect(IfLevelExpr::ApplyExpr(x), content="x")
let cond = ValueExpr::BoolExpr(true);
let cond = ApplyExpr::ValueExpr(cond);
let cond = IfLevelExpr::ApplyExpr(cond);
let cond = Expr::IfLevelExpr(cond);
let then_block = BlockExpr::new()
let else_block = BlockExpr::new()
let if_expr = IfExpr::{ cond, then_: then_block, else_: Right(else_block) };
inspect(IfLevelExpr::IfExpr(if_expr), content="if true {\n} else {\n}")
let match_expr = MatchExpr::{ nested_level: 0, expr: cond, arms: [] };
inspect(IfLevelExpr::MatchExpr(match_expr), content="match true {\n}")impl Show for IfLevelExprinspect(LeftValue::Ident("x"), content="x")
inspect(LeftValue::DotAcc(Ident("x"), "y"), content="x.y")
let int_expr = ValueExpr::IntExpr(1);
let int_expr = ApplyExpr::ValueExpr(int_expr);
let int_expr = IfLevelExpr::ApplyExpr(int_expr);
let int_expr = Expr::IfLevelExpr(int_expr);
inspect(LeftValue::ArrAcc(Ident("arr"), int_expr), content="arr[1]")let x = ValueExpr::IdentExpr(Ident("x"));
let x = ApplyExpr::ValueExpr(x);
let x = IfLevelExpr::ApplyExpr(x);
let x = Expr::IfLevelExpr(x);
let val1 = ValueExpr::IntExpr(1);
let val1 = ApplyExpr::ValueExpr(val1);
let val1 = IfLevelExpr::ApplyExpr(val1);
let val1 = Expr::IfLevelExpr(val1);
let val2 = ValueExpr::IntExpr(2);
let val2 = ApplyExpr::ValueExpr(val2);
let val2 = IfLevelExpr::ApplyExpr(val2);
let val2 = Expr::IfLevelExpr(val2);
let arms = [
(Pattern::Number(1), val1),
(Pattern::WildCard, val2)
];
let match_expr = MatchExpr::{ nested_level: 0, expr: x, arms };
let expect =
#|match x {
#| 1 => 1,
#| _ => 2,
#|}
inspect(match_expr, content=expect)inspect(Pattern::Number(1), content="1")
inspect(Pattern::Bool(true), content="true")
inspect(Pattern::WildCard, content="_")
inspect(Pattern::Ident("x"), content="x")
inspect(Pattern::Tuple([Ident("x"), Ident("y")]), content="(x, y)")
inspect(Pattern::EnumPattern(None, "Point", [Ident("x"), Ident("y")]), content="Point(x, y)")
inspect(Pattern::EnumPattern(None, "Red", []), content="Red")
inspect(Pattern::EnumPattern(Some("Color"), "Red", []), content="Color::Red")pub struct RandProgGenerator {
rand : Rand
max_depth : Int
max_stmt_count : Int
max_array_size : Int
max_tuple_size : Int
max_func_params : Int
max_nested_level : Int
total_lines_target : Int
var_env : Env[Ident, Type]
mutable_vars : Env[Ident, Type]
type_env : Env[Upper, Type]
all_defined_vars : Map[Ident, Type]
used_vars : Map[Ident, Bool]
struct_defs : Map[Upper, StructDef]
enum_defs : Map[Upper, EnumDef]
func_defs : Map[Ident, TopFuncDef]
name_counter : Int
current_return_type : Type
current_depth : Int
current_nested_level : Int
current_lines : Int
}// Let statement with type annotation
let val42 = ValueExpr::IntExpr(42);
let val42 = ApplyExpr::ValueExpr(val42);
let val42 = IfLevelExpr::ApplyExpr(val42);
let val42 = Expr::IfLevelExpr(val42);
let let_stmt = Stmt::Let(Ident("x"), Some(Type::Int), val42);
inspect(let_stmt, content="let x: Int = 42;")
// Mutable let statement
let mut_stmt = Stmt::LetMut(Ident("counter"), None, val42);
inspect(mut_stmt, content="let mut counter = 42;")
// Tuple destructuring let
let bindings = [Binding::Ident(Ident("a")), Binding::Ident(Ident("b"))];
let tuple_val = ValueExpr::TupleExpr([val42, val42]);
let tuple_val = ApplyExpr::ValueExpr(tuple_val);
let tuple_val = IfLevelExpr::ApplyExpr(tuple_val);
let tuple_val = Expr::IfLevelExpr(tuple_val);
let tuple_stmt = Stmt::LetTuple(bindings, None, tuple_val);
inspect(tuple_stmt, content="let (a, b) = (42, 42);")
// Assignment statement
let left_val = LeftValue::Ident(Ident("x"));
let assign_stmt = Stmt::Assign(left_val, val42);
inspect(assign_stmt, content="x = 42;")
// While loop
let cond = ValueExpr::BoolExpr(true);
let cond = ApplyExpr::ValueExpr(cond);
let cond = IfLevelExpr::ApplyExpr(cond);
let cond = Expr::IfLevelExpr(cond);
let body = BlockExpr::new()
let while_stmt = Stmt::While(cond, body);
inspect(while_stmt, content="while true {\n}")
// Return statement
let return_stmt = Stmt::Return(val42);
inspect(return_stmt, content="return 42;")
// Expression statement
let expr_stmt = Stmt::ExprStmt(val42);
inspect(expr_stmt, content="42;")// Simple struct without generic parameters
let fields1 : Array[(Ident, Type)] = [("x", Int), ("y", Int)];
let struct1 = StructDef::{
generic_param: None,
name: Upper("Point"),
fields: fields1
};
let expect1 =
#|struct Point {
#| x: Int
#| y: Int
#|}
inspect(struct1, content=expect1)
// Generic struct with type parameter
let fields2: Array[(Ident, Type)] = [("value", GenericDef("T"))];
let struct2 = StructDef::{
generic_param: Some(Upper("T")),
name: Upper("Container"),
fields: fields2
};
let expect2 =
#|struct Container[T] {
#| value: T
#|}
inspect(struct2, content=expect2)
// Empty struct
let struct3 = StructDef::{
generic_param: None,
name: Upper("Empty"),
fields: []
};
inspect(struct3, content="struct Empty {}\n")let val42 = ValueExpr::IntExpr(42);
let val42 = ApplyExpr::ValueExpr(val42);
let val42 = IfLevelExpr::ApplyExpr(val42);
let val42 = Expr::IfLevelExpr(val42);
let body = BlockExpr::new(last_expr=Some(val42));
// Simple function without generic parameters
let params1 : Array[(Ident, Type)] = [("x", Int), ("y", Int)];
let func1 = TopFuncDef::{
generic_param: None,
name: "add",
params: params1,
ret_ty: Type::Int,
body
};
inspect(func1, content="fn add(x: Int, y: Int) -> Int {\n 42\n}")
// Generic function with type parameter
let params2: Array[(Ident, Type)] = [("x", GenericDef("T"))];
let func2 = TopFuncDef::{
generic_param: Some(Upper("T")),
name: "identity",
params: params2,
ret_ty: Type::GenericDef(Upper("T")),
body
};
inspect(func2, content="fn[T] identity(x: T) -> T {\n 42\n}")
// Function with no parameters
let func3 = TopFuncDef::{
generic_param: None,
name: "get_answer",
params: [],
ret_ty: Type::Int,
body
};
inspect(func3, content="fn get_answer() -> Int {\n 42\n}")impl Show for TopFuncDeflet val42 = ValueExpr::IntExpr(42);
let val42 = ApplyExpr::ValueExpr(val42);
let val42 = IfLevelExpr::ApplyExpr(val42);
let val42 = Expr::IfLevelExpr(val42);
// Top-level let without type annotation
let top_let1 = TopLet::{ name: "global_var", ty: None, value: val42 };
inspect(top_let1, content="let global_var = 42;")
// Top-level let with type annotation
let top_let2 = TopLet::{ name: "typed_var", ty: Some(Type::Int), value: val42 };
inspect(top_let2, content="let typed_var: Int = 42;")
// Top-level let with complex expression
let array_val = ValueExpr::ArrayExpr([val42, val42]);
let array_val = ApplyExpr::ValueExpr(array_val);
let array_val = IfLevelExpr::ApplyExpr(array_val);
let array_val = Expr::IfLevelExpr(array_val);
let top_let3 = TopLet::{ name:"array_var", ty: Some(Type::Array(Type::Int)), value: array_val };
inspect(top_let3, content="let array_var: Array[Int] = [42, 42];")inspect(Type::Unit, content="Unit")
inspect(Type::Bool, content="Bool")
inspect(Type::Int, content="Int")
inspect(Type::Double, content="Double")
inspect(Type::Array(Int), content="Array[Int]")
inspect(Type::Tuple([Int, Bool]), content="(Int, Bool)")
inspect(Type::Func([Int, Bool], Int), content="(Int, Bool) -> Int")
inspect(Type::GenericDef("T"), content="T")
inspect(Type::Struct("Point", []), content="Point")
inspect(Type::GenericSub("Complex", Int), content="Complex[Int]")pub(all) type Upper Stringpub(all) enum ValueExpr {
ArrayMake(Expr, Expr)
StructConstruct(Upper, Array[(Ident, Expr)])
EnumConstruct(Upper?, Upper, Array[Expr])
UnitExpr
GroupExpr(Expr)
TupleExpr(Array[Expr])
ArrayExpr(Array[Expr])
BoolExpr(Bool)
IdentExpr(Ident)
BlockExpr(BlockExpr)
NegExpr(Expr)
FloatExpr(Double)
IntExpr(Int)
NotExpr(Expr)
}inspect(ValueExpr::UnitExpr, content="()")
inspect(ValueExpr::BoolExpr(true), content="true")
inspect(ValueExpr::BoolExpr(false), content="false")
inspect(ValueExpr::IntExpr(1), content="1")
inspect(ValueExpr::IntExpr(65536), content="65536")
inspect(ValueExpr::FloatExpr(1.0), content="1.0")
inspect(ValueExpr::FloatExpr(2.0), content="2.0")
inspect(ValueExpr::IdentExpr(Ident("x")), content="x")Generate MiniMoonBit Programs randomly.