mbtsmith

Generate MiniMoonBit Programs randomly.

MiniMoonbit2025
Program Generator
moon add Kaida-Amethyst/mbtsmith@0.1.4
Download zip
Version
0.1.4
License
Apache-2.0
Last updated
last year
Downloads
29
README

#MiniMbt-Smith

MiniMbt-Smith是一个检测MiniMoonbit编译器实现稳健性的工具,它可以根据MiniMoonbit2025标准的语法,随机生成符合语法的MiniMoonbit代码。

本工具基于csmith的思路设计,专注于生成具有一定长度和复杂度的MiniMoonbit程序,用于测试MiniMoonbit编译器的稳健性。

#安装与导入

在你的MoonBit项目目录中运行:

# 更新依赖 moon update # 添加mbtsmith包 moon add Kaida-Amethyst/mbtsmith

之后,在你需要使用mbtsmith的包下的moon.pkg.json下,添加import:

{ "import" : ["Kaida-Amethyst/mbtsmith"] }

然后在代码中使用:

fn main {
let generator = @mbtsmith.RandProgGenerator::new()
let prog = generator.gen_program()
println(prog)
}

#API接口说明

#RandProgGenerator类

RandProgGenerator是核心的随机程序生成器类,提供了完整的程序生成功能。

#构造函数

pub fn RandProgGenerator::new(seed~:Int? = None) -> RandProgGenerator

  • seed:可选的随机种子,用于生成可重复的随机程序。默认为0。

#主要生成方法

#1. 生成完整程序

pub fn RandProgGenerator::gen_program(self: Self) -> Program

生成一个完整的MiniMoonbit程序,包含:
  • 多个结构体定义(3-7个)
  • 多个枚举定义(2-5个)
  • 多个顶层函数和变量声明(40-79个)
  • 一个必需的main函数

#2. 生成顶层声明

pub 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) -> TopFuncDef

#AST语法树

项目提供了完整的AST语法树定义,所有Ast都实现了Show trait,可以直接转换为字符串输出:

#核心AST类型

  • Program:完整程序
  • TopDecl:顶层声明(函数、结构体、枚举、变量)
  • Expr:表达式
  • Stmt:语句
  • Type:类型系统
  • Pattern:模式匹配

#标识符类型

  • Ident:普通标识符(变量名、函数名等)
  • Upper:大写标识符(类型名、枚举变体名等)

#使用示例

#基本用法

fn 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}")
}

#测试编译器

生成的程序可以用于测试MiniMoonbit编译器:

# 生成测试程序 moon run main > test_program.mbt # 使用MoonBit检查语法正确性,--warn-list -A消除所有警告 moon check --warn-list -A test_program.mbt # 使用你的MiniMoonbit编译器进行测试 your_compiler test_program.mbt

#注意

mbtsmith当前只能生成满足语法和类型定义的minimoonbit程序,但在运行阶段可能会出现问题。

#MiniMoonbit2025标准语法

grammar 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;

#许可证

Apache-2.0

#
ApplyExpr

pub(all) enum ApplyExpr {
ValueExpr(ValueExpr)
ArrAcc(ApplyExpr, Expr)
DotAcc(ApplyExpr, Ident)
Call(ApplyExpr, Array[Expr])
}
ApplyExpr is used to represent function application, array access, and dot access.

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)")
impl Show for ApplyExpr

#
Binding

pub(all) enum Binding {
Ident(Ident)
WhileCard
}
Binding is used in the left-hand side of a let statement.

inspect(Binding::Ident("x"), content="x")
inspect(Binding::WhileCard, content="_")
impl Show for Binding

#
BlockExpr

pub struct BlockExpr {
nested_level : Int
stmts : Array[Stmt]
last_expr : Expr?
parent : BlockExpr?
}
BlockExpr represents a block of code wrapped in {} containing statements and an optional final expression. A block can contain multiple statements followed by an optional expression that serves as the block's value. The nested_level field controls indentation for pretty printing.

// 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}")
impl Show for BlockExpr

#
BlockExpr::new

fn BlockExpr::new(nested_level? : Int, parent? : BlockExpr?, last_expr? : Expr?) -> BlockExpr

#
BlockExpr::push

fn BlockExpr::push(self : BlockExpr, stmt : Stmt) -> Unit

#
BlockExpr::set_last_expr

fn BlockExpr::set_last_expr(self : BlockExpr, expr : Expr) -> Unit

#
CmpOp

pub(all) enum CmpOp {
Eq
Ne
Lt
Le
Gt
Ge
}

impl Show for CmpOp

#
Either

pub(all) enum Either[L, R] {
Left(L)
Right(R)
}

impl Eq for Either[L, R]

#
Either::expect_left

fn[L, R] Either::expect_left(self : Either[L, R], msg : String) -> L

#
Either::expect_right

fn[L, R] Either::expect_right(self : Either[L, R], msg : String) -> R

#
Either::is_left

fn[L, R] Either::is_left(self : Either[L, R]) -> Bool

#
Either::is_right

fn[L, R] Either::is_right(self : Either[L, R]) -> Bool

#
Either::left

fn[L, R] Either::left(self : Either[L, R]) -> L?

#
Either::left_unwrap

fn[L, R] Either::left_unwrap(self : Either[L, R]) -> L

#
Either::right

fn[L, R] Either::right(self : Either[L, R]) -> R?

#
Either::right_unwrap

fn[L, R] Either::right_unwrap(self : Either[L, R]) -> R

#
EnumDef

pub(all) struct EnumDef {
generic_param : Upper?
name : Upper
variants : Array[(Upper, Array[Type])]
}
EnumDef represents enum type definitions with optional generic parameters. Enums define algebraic data types with multiple variants that can have associated data.

// 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")
impl Show for EnumDef

#
EnumDef::type_of

fn EnumDef::type_of(self : EnumDef) -> Type

#
Env

type Env[K, V]
Environment management - used to track variable and type bindings

#
Expr

pub(all) enum Expr {
AndExpr(Expr, Expr)
OrExpr(Expr, Expr)
CmpExpr(CmpOp, Expr, Expr)
AddExpr(Expr, Expr)
SubExpr(Expr, Expr)
MulExpr(Expr, Expr)
DivExpr(Expr, Expr)
ModExpr(Expr, Expr)
IfLevelExpr(IfLevelExpr)
}
Expr is the main expression type that can be used in the AST.

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")
impl Show for Expr

#
Ident

pub(all) type Ident String

impl Eq for Ident
impl Hash for Ident
impl Show for Ident

#
Ident::inner

fn Ident::inner(self : Ident) -> String
Convert newtype to its underlying type, automatically derived.

#
IfExpr

pub(all) struct IfExpr {
cond : Expr
then_ : BlockExpr
else_ : Either[IfExpr, BlockExpr]
}
IfExpr represents conditional expressions with if-then-else structure.

let 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)
impl Show for IfExpr

#
IfLevelExpr

pub(all) enum IfLevelExpr {
ApplyExpr(ApplyExpr)
IfExpr(IfExpr)
MatchExpr(MatchExpr)
}
IfLevelExpr represents expressions that have the same precedence as if expressions.

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 IfLevelExpr

#
LeftValue

pub(all) enum LeftValue {
Ident(Ident)
DotAcc(LeftValue, Ident)
ArrAcc(LeftValue, Expr)
}
LeftValue is the left-hand side of an assignment.

inspect(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]")
impl Show for LeftValue

#
MatchExpr

pub struct MatchExpr {
nested_level : Int
expr : Expr
arms : Array[(Pattern, Expr)]
}
MatchExpr represents pattern matching expressions with multiple arms.

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)
impl Show for MatchExpr

#
Pattern

pub(all) enum Pattern {
Number(Int)
Bool(Bool)
WildCard
Ident(Ident)
Tuple(Array[Pattern])
EnumPattern(Upper?, Upper, Array[Pattern])
}
Pattern is used in the match arm.

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")
impl Show for Pattern

#
Program

pub struct Program {
top_decls : Array[TopDecl]
}

impl Show for Program

#
RandProgGenerator

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
}
Generator state and configuration

#
RandProgGenerator::gen_assign_stmt

fn RandProgGenerator::gen_assign_stmt(self : RandProgGenerator) -> Stmt
Generate assignment statement

#
RandProgGenerator::gen_block_expr

fn RandProgGenerator::gen_block_expr(self : RandProgGenerator, return_type : Type) -> BlockExpr
Enhanced code block generator supporting more complex code structures

#
RandProgGenerator::gen_enum_def

fn RandProgGenerator::gen_enum_def(self : RandProgGenerator) -> EnumDef
Generate enum definition

#
RandProgGenerator::gen_expr

fn RandProgGenerator::gen_expr(self : RandProgGenerator, ty : Type, simple : Bool) -> Expr
Enhanced expression generator supporting more complex expression structures

#
RandProgGenerator::gen_expr_stmt

fn RandProgGenerator::gen_expr_stmt(self : RandProgGenerator) -> Stmt
Generate expression statement

#
RandProgGenerator::gen_if_expr

fn RandProgGenerator::gen_if_expr(self : RandProgGenerator, expected_type : Type) -> Expr?
Generate if expressions

#
RandProgGenerator::gen_let_mut_stmt

fn RandProgGenerator::gen_let_mut_stmt(self : RandProgGenerator) -> Stmt
Generate let mut statement with immediate assignment to ensure mutability is used

#
RandProgGenerator::gen_let_stmt

fn RandProgGenerator::gen_let_stmt(self : RandProgGenerator) -> Stmt
Generate let statement

#
RandProgGenerator::gen_let_tuple_stmt

fn RandProgGenerator::gen_let_tuple_stmt(self : RandProgGenerator) -> Stmt
Generate tuple destructuring let statement

#
RandProgGenerator::gen_local_func_def_stmt

fn RandProgGenerator::gen_local_func_def_stmt(self : RandProgGenerator) -> Stmt
Generate local function definition statement

#
RandProgGenerator::gen_main_func

fn RandProgGenerator::gen_main_func(self : RandProgGenerator) -> TopFuncDef
Generate main function (without parameters and generic parameters)

#
RandProgGenerator::gen_match_expr

fn RandProgGenerator::gen_match_expr(self : RandProgGenerator, expected_type : Type) -> Expr?
Generate match expressions

#
RandProgGenerator::gen_program

fn RandProgGenerator::gen_program(self : RandProgGenerator) -> Program
Program generator ensuring main function inclusion and reasonable program length

#
RandProgGenerator::gen_return_stmt

fn RandProgGenerator::gen_return_stmt(self : RandProgGenerator) -> Stmt
Generate return statement

#
RandProgGenerator::gen_stmt

fn RandProgGenerator::gen_stmt(self : RandProgGenerator) -> Stmt
Enhanced statement generator supporting more statement types

#
RandProgGenerator::gen_struct_def

fn RandProgGenerator::gen_struct_def(self : RandProgGenerator) -> StructDef
Generate struct definition

#
RandProgGenerator::gen_top_decl

fn RandProgGenerator::gen_top_decl(self : RandProgGenerator) -> TopDecl
Generate top-level declaration

#
RandProgGenerator::gen_top_func_def

fn RandProgGenerator::gen_top_func_def(self : RandProgGenerator) -> TopFuncDef
Generate top-level function definition

#
RandProgGenerator::gen_top_let

fn RandProgGenerator::gen_top_let(self : RandProgGenerator) -> TopLet
Enhanced top-level definition generator

#
RandProgGenerator::gen_while_stmt

fn RandProgGenerator::gen_while_stmt(self : RandProgGenerator) -> Stmt
Generate while statement

#
RandProgGenerator::new

fn RandProgGenerator::new(seed? : Int?) -> RandProgGenerator
Create new random program generator

#
Stmt

pub(all) enum Stmt {
LetTuple(Array[Binding], Type?, Expr)
LetMut(Ident, Type?, Expr)
Let(Ident, Type?, Expr)
LocalFuncDef(Ident, Array[(Ident, Type?)], Type?, BlockExpr)
Assign(LeftValue, Expr)
While(Expr, BlockExpr)
Return(Expr)
ExprStmt(Expr)
}
Stmt represents different types of statements in the language. Statements are instructions that perform actions but do not return values.

// 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;")
impl Show for Stmt

#
StructDef

pub(all) struct StructDef {
generic_param : Upper?
name : Upper
fields : Array[(Ident, Type)]
}
StructDef represents struct type definitions with optional generic parameters. Structs define custom data types with named fields.

// 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")
impl Show for StructDef

#
StructDef::type_of

fn StructDef::type_of(self : StructDef) -> Type

#
TopDecl

pub enum TopDecl {
TopLet(TopLet)
TopFuncDef(TopFuncDef)
StructDef(StructDef)
EnumDef(EnumDef)
}

impl Show for TopDecl

#
TopFuncDef

pub(all) struct TopFuncDef {
generic_param : Upper?
name : Ident
params : Array[(Ident, Type)]
ret_ty : Type
body : BlockExpr
}
TopFuncDef represents top-level function definitions with optional generic parameters. These are function declarations that can be called from anywhere in the program.

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 TopFuncDef

#
TopLet

pub(all) struct TopLet {
name : Ident
ty : Type?
value : Expr
}
TopLet represents top-level let bindings with optional type annotations. These are global variable declarations that can be used throughout the program.

let 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];")
impl Show for TopLet

#
Type

pub(all) enum Type {
Unit
Bool
Int
Double
Array(Type)
Tuple(Array[Type])
Func(Array[Type], Type)
Struct(Upper, Array[(Ident, Type)])
Enum(Upper, Array[(Upper, Array[Type])])
GenericDef(Upper)
GenericSub(Upper, Type)
}
Show for Type

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]")
impl Eq for Type
impl Show for Type

#
Upper

pub(all) type Upper String

impl Eq for Upper
impl Hash for Upper
impl Show for Upper

#
Upper::inner

fn Upper::inner(self : Upper) -> String
Convert newtype to its underlying type, automatically derived.

#
ValueExpr

pub(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)
}
ValueExpr is primary expressions that can be evaluated to a value.

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")
impl Show for ValueExpr