diff --git a/batch_run.py b/batch_run.py index 2f9380b..9f32079 100644 --- a/batch_run.py +++ b/batch_run.py @@ -2,36 +2,38 @@ import os import asyncio -async def check_file(filepath): +async def check_file(in_path, out_path): proc = await asyncio.create_subprocess_exec( "moon", "run", "src/bin/main.mbt", "--", - "--typecheck", - filepath, + in_path, + "-o", + out_path, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) stdout, stderr = await proc.communicate() if proc.returncode != 0: print(f""" -[{proc.returncode}] Error in file {filepath}: +[{proc.returncode}] Error in file {in_path}: ======== STDOUT ======== {stdout.decode()} ======== STDERR ======== {stderr.decode()} """) else: - print(f"File {filepath} compiled successfully.") + print(f"File {in_path} compiled successfully.") async def main(): tasks = [] for file in os.listdir("contest-2025-data/test_cases/mbt"): if file.endswith(".mbt"): - filepath = os.path.join("contest-2025-data/test_cases/mbt", file) - tasks.append(check_file(filepath)) + in_path = os.path.join("contest-2025-data/test_cases/mbt", file) + out_path = os.path.join("output/repo", file.replace(".mbt", ".s")) + tasks.append(check_file(in_path, out_path)) await asyncio.gather(*tasks) diff --git a/src/parser/ast.mbt b/src/parser/ast.mbt index e0ffba5..1d8b96b 100644 --- a/src/parser/ast.mbt +++ b/src/parser/ast.mbt @@ -485,7 +485,12 @@ pub fn parse_block_expr( } break r } else if r is [RCurlyBracket, .. r] { - stmts.push(Expr(Literal(Unit))) + // Ref: syntax.typ:123-125 + // - 一个Block 块可以有返回值,块内的最后一条语句可以是一个expr,也可以是一个`stmt`,如果块的最后一个语句是一个`expr`,则该块的值就是这个 `expr` 的值。如果块的最后一个语句是一个 `stmt`,且这个块是一个`expr_stmt`,则该块的值就是这个 `stmt` 的值。 + // 例如, ```rust let a = 1; { let b = 2; a + b }``` 的值是 `3`,```rust let a = 1; { let b = 2; a + b; }``` 的值是 `3`,而```rust let a = 1; { let b = 2; let _ = a + b; }``` 的值是 `()`。 + if !(stmts is [.., Expr(_)]) { + stmts.push(Expr(Literal(Unit))) + } break r } continue r diff --git a/src/parser/ast_wbtest.mbt b/src/parser/ast_wbtest.mbt index f5c61aa..ef95f03 100644 --- a/src/parser/ast_wbtest.mbt +++ b/src/parser/ast_wbtest.mbt @@ -154,7 +154,7 @@ test "parse_block_expr" { RCurlyBracket, EOF, ]), - content="(Block([Expr(Literal(Int(1))), Expr(Literal(Unit))]), [EOF])", + content="(Block([Expr(Literal(Int(1)))]), [EOF])", ) } @@ -226,7 +226,7 @@ test "parse_if_level_expr" { RCurlyBracket, EOF, ]), - content="(If(Literal(Int(0)), Block([Expr(Literal(Int(1))), Expr(Literal(Unit))]), None), [EOF])", + content="(If(Literal(Int(0)), Block([Expr(Literal(Int(1)))]), None), [EOF])", ) } @@ -333,6 +333,8 @@ test "parse_program" { LCurlyBracket, IntLiteral(0), Semicolon, + LParen, + RParen, RCurlyBracket, EOF, ]), diff --git a/src/typecheck/typecheck_test.mbt b/src/typecheck/typecheck_test.mbt index 3f81b48..15c2bf3 100644 --- a/src/typecheck/typecheck_test.mbt +++ b/src/typecheck/typecheck_test.mbt @@ -563,7 +563,7 @@ test "Block Expr TypeCheck Test" { // TypeCheck first block expr let (block_expr1, tok_view) = @parser.parse_block_expr(tok_view) let checked_block1 = ctx.check_block_expr(block_expr1) - assert_true(checked_block1.stmts.length() is 5) // Lilunar adds an implicit Expr(Unit) at the end + assert_true(checked_block1.stmts.length() is 4) assert_true(checked_block1.ty is Unit) // TypeCheck second block expr let (block_expr2, tok_view) = @parser.parse_block_expr(tok_view)