fix: block ends with expr stmt

This commit is contained in:
2025-11-05 22:12:40 +08:00
parent b312898187
commit cc34f59a4d
4 changed files with 20 additions and 11 deletions

View File

@@ -2,36 +2,38 @@ import os
import asyncio import asyncio
async def check_file(filepath): async def check_file(in_path, out_path):
proc = await asyncio.create_subprocess_exec( proc = await asyncio.create_subprocess_exec(
"moon", "moon",
"run", "run",
"src/bin/main.mbt", "src/bin/main.mbt",
"--", "--",
"--typecheck", in_path,
filepath, "-o",
out_path,
stdout=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
) )
stdout, stderr = await proc.communicate() stdout, stderr = await proc.communicate()
if proc.returncode != 0: if proc.returncode != 0:
print(f""" print(f"""
[{proc.returncode}] Error in file {filepath}: [{proc.returncode}] Error in file {in_path}:
======== STDOUT ======== ======== STDOUT ========
{stdout.decode()} {stdout.decode()}
======== STDERR ======== ======== STDERR ========
{stderr.decode()} {stderr.decode()}
""") """)
else: else:
print(f"File {filepath} compiled successfully.") print(f"File {in_path} compiled successfully.")
async def main(): async def main():
tasks = [] tasks = []
for file in os.listdir("contest-2025-data/test_cases/mbt"): for file in os.listdir("contest-2025-data/test_cases/mbt"):
if file.endswith(".mbt"): if file.endswith(".mbt"):
filepath = os.path.join("contest-2025-data/test_cases/mbt", file) in_path = os.path.join("contest-2025-data/test_cases/mbt", file)
tasks.append(check_file(filepath)) out_path = os.path.join("output/repo", file.replace(".mbt", ".s"))
tasks.append(check_file(in_path, out_path))
await asyncio.gather(*tasks) await asyncio.gather(*tasks)

View File

@@ -485,7 +485,12 @@ pub fn parse_block_expr(
} }
break r break r
} else if r is [RCurlyBracket, .. 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 break r
} }
continue r continue r

View File

@@ -154,7 +154,7 @@ test "parse_block_expr" {
RCurlyBracket, RCurlyBracket,
EOF, 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, RCurlyBracket,
EOF, 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, LCurlyBracket,
IntLiteral(0), IntLiteral(0),
Semicolon, Semicolon,
LParen,
RParen,
RCurlyBracket, RCurlyBracket,
EOF, EOF,
]), ]),

View File

@@ -563,7 +563,7 @@ test "Block Expr TypeCheck Test" {
// TypeCheck first block expr // TypeCheck first block expr
let (block_expr1, tok_view) = @parser.parse_block_expr(tok_view) let (block_expr1, tok_view) = @parser.parse_block_expr(tok_view)
let checked_block1 = ctx.check_block_expr(block_expr1) 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) assert_true(checked_block1.ty is Unit)
// TypeCheck second block expr // TypeCheck second block expr
let (block_expr2, tok_view) = @parser.parse_block_expr(tok_view) let (block_expr2, tok_view) = @parser.parse_block_expr(tok_view)