fix: block ends with expr stmt
This commit is contained in:
16
batch_run.py
16
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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
]),
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user