function declarations

This commit is contained in:
2025-05-30 18:33:52 +02:00
parent 2bc24c394d
commit b3475651eb
5 changed files with 76 additions and 32 deletions

View File

@@ -4,7 +4,7 @@ A very cool language
## Syntax
```go
func fib[U32 n] : U32
func fib[n: U32] : U32
if n <= 1
return n
return fib(n-2) + fib(n-1)

View File

@@ -1,8 +1,9 @@
let a: I64 = 0
let b: I64 = 1
func main[]
let a: I64 = 0
let b: I64 = 1
while a < 100000
print(a)
let temp: I64 = b
b = a + b
a = temp
while a < 100000
print(a)
let temp: I64 = b
b = a + b
a = temp

View File

@@ -67,32 +67,28 @@ impl Codegen {
writeln!(
&mut self.output,
"section .data
format db \"%d\", 10, 0
format db \"%ld\", 10, 0
section .text
extern printf
global main
main:
print:
push rbp
mov rbp, rsp
sub rsp, 256" // TODO
mov rdi, format
mov rsi, rax
xor rax, rax
call printf
pop rbp
ret
"
)?;
Ok(())
}
pub fn emit_epilogue(&mut self) -> Result<(), Box<dyn Error>> {
write!(
&mut self.output,
" mov rsp, rbp
pop rbp
mov rax, 0
ret
section .note.GNU-stack
db 0
"
)?;
writeln!(&mut self.output, "section .note.GNU-stack")?;
writeln!(&mut self.output, " db 0")?;
Ok(())
}
@@ -156,6 +152,22 @@ section .note.GNU-stack
writeln!(&mut self.output, " jmp {}", begin_label)?;
writeln!(&mut self.output, "{}:", end_label)?;
}
Stmt::Function { name, params, body } => {
assert!(params.is_empty()); // TODO
writeln!(&mut self.output, "global {}", name.lexeme)?;
writeln!(&mut self.output, "{}:", name.lexeme)?;
writeln!(&mut self.output, " push rbp")?;
writeln!(&mut self.output, " mov rbp, rsp")?;
writeln!(&mut self.output, " sub rsp, 256")?; // TODO
self.compile_stmt(env, *body)?;
writeln!(&mut self.output, " mov rsp, rbp")?;
writeln!(&mut self.output, " pop rbp")?;
writeln!(&mut self.output, " mov rax, 0")?;
writeln!(&mut self.output, " ret")?;
}
}
Ok(())
}
@@ -275,18 +287,11 @@ section .note.GNU-stack
};
// TODO
assert!(callee == "print");
assert!(args.len() == 1);
self.compile_expr(env, args.first().unwrap().clone())?;
writeln!(
&mut self.output,
" mov rdi, format
mov rsi, rax
xor rax, rax
call printf"
)?;
writeln!(&mut self.output, " mov rdi, rax")?;
writeln!(&mut self.output, " call {}", callee)?;
}
}
Ok(())

View File

@@ -2,6 +2,12 @@ use std::error::Error;
use crate::tokenizer::{MotError, Token, TokenType, error};
#[derive(Debug, Clone)]
pub struct Param {
var_type: Token,
var_name: Token,
}
#[derive(Debug, Clone)]
pub enum Stmt {
Expression(Expr),
@@ -20,6 +26,11 @@ pub enum Stmt {
condition: Expr,
body: Box<Stmt>,
},
Function {
name: Token,
params: Vec<Param>,
body: Box<Stmt>,
},
}
#[derive(Debug, Clone)]
@@ -69,11 +80,36 @@ impl Parser {
// TODO: synchronization after parse error
if self.match_token(&[TokenType::KeywordLet]) {
self.let_declaration()
} else if self.match_token(&[TokenType::KeywordFunc]) {
self.func_declaration()
} else {
self.statement()
}
}
// TOOD: parse return type
fn func_declaration(&mut self) -> Result<Stmt, Box<dyn Error>> {
let name = self.consume(TokenType::Identifier, "expected function name")?;
self.consume(TokenType::LeftBracket, "expected '[' after function name")?;
let mut params = vec![];
if !self.check(&TokenType::RightBracket) {
loop {
let var_name = self.consume(TokenType::Identifier, "expected parameter name")?;
self.consume(TokenType::Colon, "expected ':' after parameter name")?;
let var_type = self.consume(TokenType::Identifier, "expected parameter type")?;
params.push(Param { var_type, var_name });
if !self.match_token(&[TokenType::Comma]) {
break;
}
}
}
self.consume(TokenType::RightBracket, "expected ']' after arguments")?;
let body = Box::new(self.block()?);
Ok(Stmt::Function { name, params, body })
}
fn let_declaration(&mut self) -> Result<Stmt, Box<dyn Error>> {
let name = self.consume(TokenType::Identifier, "expected variable name")?;
self.consume(TokenType::Colon, "expected ':' after variable name")?;

View File

@@ -34,6 +34,7 @@ pub enum TokenType {
KeywordIf,
KeywordElse,
KeywordWhile,
KeywordFunc,
Indent,
Dedent,
@@ -298,6 +299,7 @@ impl Tokenizer {
"if" => TokenType::KeywordIf,
"else" => TokenType::KeywordElse,
"while" => TokenType::KeywordWhile,
"func" => TokenType::KeywordFunc,
_ => TokenType::Identifier,
})
}