parse return types, disallow nested functions
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
func main[]
|
func main[] : I64
|
||||||
let a: I64 = 0
|
let a: I64 = 0
|
||||||
let b: I64 = 1
|
let b: I64 = 1
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ impl Env {
|
|||||||
pub fn new() -> Env {
|
pub fn new() -> Env {
|
||||||
Env {
|
Env {
|
||||||
scopes: vec![HashMap::new()],
|
scopes: vec![HashMap::new()],
|
||||||
next_offset: 1,
|
next_offset: 8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ impl Env {
|
|||||||
|
|
||||||
pub fn define_var(&mut self, name: String, var_type: String) -> usize {
|
pub fn define_var(&mut self, name: String, var_type: String) -> usize {
|
||||||
let offset = self.next_offset;
|
let offset = self.next_offset;
|
||||||
self.next_offset += 1;
|
self.next_offset += 8;
|
||||||
self.scopes.last_mut().unwrap().insert(name, Var {
|
self.scopes.last_mut().unwrap().insert(name, Var {
|
||||||
var_type,
|
var_type,
|
||||||
stack_offset: offset,
|
stack_offset: offset,
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ print:
|
|||||||
|
|
||||||
self.compile_expr(env, initializer)?;
|
self.compile_expr(env, initializer)?;
|
||||||
let offset = env.define_var(name.lexeme.clone(), var_type.lexeme);
|
let offset = env.define_var(name.lexeme.clone(), var_type.lexeme);
|
||||||
writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset * 8)?;
|
writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset)?;
|
||||||
}
|
}
|
||||||
Stmt::Block(statements) => {
|
Stmt::Block(statements) => {
|
||||||
env.push_scope();
|
env.push_scope();
|
||||||
@@ -110,8 +110,14 @@ print:
|
|||||||
writeln!(&mut self.output, " jmp {}", begin_label)?;
|
writeln!(&mut self.output, " jmp {}", begin_label)?;
|
||||||
writeln!(&mut self.output, "{}:", end_label)?;
|
writeln!(&mut self.output, "{}:", end_label)?;
|
||||||
}
|
}
|
||||||
Stmt::Function { name, params, body } => {
|
Stmt::Function {
|
||||||
|
name,
|
||||||
|
params,
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
assert!(params.is_empty()); // TODO
|
assert!(params.is_empty()); // TODO
|
||||||
|
assert!(return_type.lexeme == "I64");
|
||||||
|
|
||||||
writeln!(&mut self.output, "global {}", name.lexeme)?;
|
writeln!(&mut self.output, "global {}", name.lexeme)?;
|
||||||
writeln!(&mut self.output, "{}:", name.lexeme)?;
|
writeln!(&mut self.output, "{}:", name.lexeme)?;
|
||||||
@@ -222,7 +228,7 @@ print:
|
|||||||
writeln!(
|
writeln!(
|
||||||
&mut self.output,
|
&mut self.output,
|
||||||
" mov rax, QWORD [rbp-{}]",
|
" mov rax, QWORD [rbp-{}]",
|
||||||
var.stack_offset * 8
|
var.stack_offset
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
Expr::Assign { name, value } => {
|
Expr::Assign { name, value } => {
|
||||||
@@ -237,7 +243,7 @@ print:
|
|||||||
writeln!(
|
writeln!(
|
||||||
&mut self.output,
|
&mut self.output,
|
||||||
" mov QWORD [rbp-{}], rax",
|
" mov QWORD [rbp-{}], rax",
|
||||||
var.stack_offset * 8
|
var.stack_offset
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Expr::Call {
|
Expr::Call {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ pub enum Stmt {
|
|||||||
Function {
|
Function {
|
||||||
name: Token,
|
name: Token,
|
||||||
params: Vec<Param>,
|
params: Vec<Param>,
|
||||||
|
return_type: Token,
|
||||||
body: Box<Stmt>,
|
body: Box<Stmt>,
|
||||||
},
|
},
|
||||||
Return(Expr),
|
Return(Expr),
|
||||||
@@ -62,11 +63,16 @@ pub enum Expr {
|
|||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
tokens: Vec<Token>,
|
tokens: Vec<Token>,
|
||||||
current: usize,
|
current: usize,
|
||||||
|
is_inside_function: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
pub fn new(tokens: Vec<Token>) -> Parser {
|
pub fn new(tokens: Vec<Token>) -> Parser {
|
||||||
Parser { tokens, current: 0 }
|
Parser {
|
||||||
|
tokens,
|
||||||
|
current: 0,
|
||||||
|
is_inside_function: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(mut self) -> Result<Vec<Stmt>, Box<dyn Error>> {
|
pub fn parse(mut self) -> Result<Vec<Stmt>, Box<dyn Error>> {
|
||||||
@@ -78,11 +84,19 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn declaration(&mut self) -> Result<Stmt, Box<dyn Error>> {
|
fn declaration(&mut self) -> Result<Stmt, Box<dyn Error>> {
|
||||||
|
if !self.is_inside_function {
|
||||||
|
if self.match_token(&[TokenType::KeywordFunc]) {
|
||||||
|
return self.func_declaration();
|
||||||
|
}
|
||||||
|
return error!(
|
||||||
|
self.peek().loc,
|
||||||
|
"statements not allowed outside function body"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: synchronization after parse error
|
// TODO: synchronization after parse error
|
||||||
if self.match_token(&[TokenType::KeywordLet]) {
|
if self.match_token(&[TokenType::KeywordLet]) {
|
||||||
self.let_declaration()
|
self.let_declaration()
|
||||||
} else if self.match_token(&[TokenType::KeywordFunc]) {
|
|
||||||
self.func_declaration()
|
|
||||||
} else {
|
} else {
|
||||||
self.statement()
|
self.statement()
|
||||||
}
|
}
|
||||||
@@ -107,8 +121,19 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.consume(TokenType::RightBracket, "expected ']' after arguments")?;
|
self.consume(TokenType::RightBracket, "expected ']' after arguments")?;
|
||||||
|
self.consume(TokenType::Colon, "expected ':' after '['")?;
|
||||||
|
let return_type = self.consume(TokenType::Identifier, "expected return type")?;
|
||||||
|
|
||||||
|
self.is_inside_function = true;
|
||||||
let body = Box::new(self.block()?);
|
let body = Box::new(self.block()?);
|
||||||
Ok(Stmt::Function { name, params, body })
|
self.is_inside_function = false;
|
||||||
|
|
||||||
|
Ok(Stmt::Function {
|
||||||
|
name,
|
||||||
|
params,
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn let_declaration(&mut self) -> Result<Stmt, Box<dyn Error>> {
|
fn let_declaration(&mut self) -> Result<Stmt, Box<dyn Error>> {
|
||||||
|
|||||||
Reference in New Issue
Block a user