finally allow bare returns

This commit is contained in:
2026-06-07 13:10:36 +02:00
parent d4fe032a3a
commit 2864548daf
5 changed files with 43 additions and 34 deletions

View File

@@ -415,15 +415,18 @@ _builtin_environ:
.replace_range(prologue_offset..prologue_offset + patch.len(), &patch); .replace_range(prologue_offset..prologue_offset + patch.len(), &patch);
} }
Stmt::Return { keyword: _, exprs } => { Stmt::Return { keyword: _, exprs } => {
if exprs.len() == 2 { match exprs.len() {
2 => {
self.compile_expr(env, &exprs[1])?; self.compile_expr(env, &exprs[1])?;
emit!(&mut self.output, " push rax"); emit!(&mut self.output, " push rax");
self.compile_expr(env, &exprs[0])?; self.compile_expr(env, &exprs[0])?;
emit!(&mut self.output, " pop rdx"); emit!(&mut self.output, " pop rdx");
} else if exprs.len() == 1 { }
1 => {
self.compile_expr(env, &exprs[0])?; self.compile_expr(env, &exprs[0])?;
} else { }
todo!(); 0 => {}
_ => todo!(),
} }
emit!(&mut self.output, " mov rsp, rbp"); emit!(&mut self.output, " mov rsp, rbp");
emit!(&mut self.output, " pop rbp"); emit!(&mut self.output, " pop rbp");

View File

@@ -327,12 +327,14 @@ impl Parser {
} else if self.match_token(&[TokenType::KeywordReturn]) { } else if self.match_token(&[TokenType::KeywordReturn]) {
let keyword = self.previous().clone(); let keyword = self.previous().clone();
let mut exprs = vec![]; let mut exprs = vec![];
if !self.check(&TokenType::Dedent) {
loop { loop {
exprs.push(self.expression()?); exprs.push(self.expression()?);
if !self.match_token(&[TokenType::Comma]) { if !self.match_token(&[TokenType::Comma]) {
break; break;
} }
} }
}
Ok(Stmt::Return { keyword, exprs }) Ok(Stmt::Return { keyword, exprs })
} else if self.match_token(&[TokenType::KeywordBreak]) { } else if self.match_token(&[TokenType::KeywordBreak]) {
Ok(Stmt::Break) Ok(Stmt::Break)

View File

@@ -81,11 +81,11 @@ func mem.free[x: any] : void
func ptr.free[x: ptr] : void func ptr.free[x: ptr] : void
if x == 0 if x == 0
return 0 return
blk := (x - MEM_BLOCK_SIZE) as mem.Block blk := (x - MEM_BLOCK_SIZE) as mem.Block
if blk->free if blk->free
return 0 return
blk->free = true blk->free = true
@@ -733,7 +733,7 @@ func i64.to_str_buf[n: i64, buf: ptr] : void
if n == 0 if n == 0
buf[0] = '0' buf[0] = '0'
buf[1] = 0 buf[1] = 0
return 0 return
neg : bool = n < 0 neg : bool = n < 0
if neg if neg
@@ -768,7 +768,7 @@ func i64.to_hex_str_buf[n: i64, buf: ptr] : void
if n == 0 if n == 0
buf[0] = '0' buf[0] = '0'
buf[1] = 0 buf[1] = 0
return 0 return
mask := (1 << 60) - 1 mask := (1 << 60) - 1
tmp := _stackalloc(17) tmp := _stackalloc(17)
@@ -849,7 +849,7 @@ func Array.new_preallocated_and_zeroed[size: i64] : Array
func Array.nth[xs: Array, n: i64] : any func Array.nth[xs: Array, n: i64] : any
if n < 0 || n >= xs->size if n < 0 || n >= xs->size
panic("array.nth out of bounds") panic("Array.nth out of bounds")
return mem.read64(xs->data + n * 8) return mem.read64(xs->data + n * 8)
func Array.set[xs: Array, n: i64, x: any] : void func Array.set[xs: Array, n: i64, x: any] : void
@@ -882,14 +882,19 @@ func Array.free_with_items[xs: Array] : void
func Array.pop[xs: Array] : any func Array.pop[xs: Array] : any
if xs->size == 0 if xs->size == 0
panic("array.pop on empty array") panic("Array.pop on empty array")
x : any = xs->nth(xs->size - 1) x : any = Array.last(xs)
xs->size = xs->size - 1 xs->size = xs->size - 1
return x return x
func Array.last[xs: Array] : any
if xs->size == 0
panic("Array.last on empty array")
return xs->nth(xs->size - 1)
func Array.slice[xs: Array, start: i64, length: i64] : Array func Array.slice[xs: Array, start: i64, length: i64] : Array
if start < 0 || length < 0 || start + length > xs->size if start < 0 || length < 0 || start + length > xs->size
panic("array.slice out of bounds") panic("Array.slice out of bounds")
new_array := Array.new_preallocated_and_zeroed(length) new_array := Array.new_preallocated_and_zeroed(length)
mem.copy(xs->data + start * 8, new_array->data, length * 8) mem.copy(xs->data + start * 8, new_array->data, length * 8)
@@ -971,7 +976,7 @@ func HashMap.insert[map: HashMap, key: str, value: any] : void
while current as ptr while current as ptr
if current->key->equal(key) if current->key->equal(key)
current->value = value current->value = value
return 0 return
current = current->next current = current->next
new_node := new* HashMap._Node new_node := new* HashMap._Node
@@ -1005,7 +1010,7 @@ func HashMap.delete[map: HashMap, key: str] : void
current->key->free() current->key->free()
mem.free(current) mem.free(current)
return 0 return
prev = current prev = current
current = current->next current = current->next

View File

@@ -329,17 +329,16 @@ impl<'a> TypeChecker<'a> {
env.pop_scope(); env.pop_scope();
} }
Stmt::Return { keyword, exprs } => { Stmt::Return { keyword, exprs } => {
let expected = if self.current_function_return_type == "void" { let joined_type = if exprs.is_empty() {
"i64".into() "void".into()
} else { } else {
self.current_function_return_type.clone() exprs
};
let joined_type = exprs
.iter() .iter()
.map(|e| self.typecheck_expr(env, e)) .map(|e| self.typecheck_expr(env, e))
.collect::<Result<Vec<String>, _>>()? .collect::<Result<Vec<String>, _>>()?
.join(","); .join(",")
expect_type!(joined_type, expected, keyword.loc); };
expect_type!(joined_type, self.current_function_return_type, keyword.loc);
} }
Stmt::Break => {} Stmt::Break => {}
Stmt::Continue => {} Stmt::Continue => {}

View File

@@ -5,7 +5,7 @@ func run_test[x: str] : void
for i in 0..build_blacklist->size for i in 0..build_blacklist->size
if x->equal(build_blacklist->nth(i)) if x->equal(build_blacklist->nth(i))
io.printf("Skipping %s...\n", x) io.printf("Skipping %s...\n", x)
return 0 return
io.printf("Building %s...\n", x) io.printf("Building %s...\n", x)
@@ -20,7 +20,7 @@ func run_test[x: str] : void
for i in 0..run_blacklist->size for i in 0..run_blacklist->size
if x->contains(run_blacklist->nth(i)) if x->contains(run_blacklist->nth(i))
io.printf("Skipping %s...\n", x) io.printf("Skipping %s...\n", x)
return 0 return
io.printf("Running %s...\n", x) io.printf("Running %s...\n", x)