for loop
This commit is contained in:
@@ -228,7 +228,10 @@ set:
|
||||
return error!(&name.loc, format!("unknown type: {}", return_type.lexeme));
|
||||
}
|
||||
|
||||
emit!(&mut self.output, "global {}", name.lexeme);
|
||||
// TODO
|
||||
if name.lexeme == "main" {
|
||||
emit!(&mut self.output, "global {}", name.lexeme);
|
||||
}
|
||||
emit!(&mut self.output, "{}:", name.lexeme);
|
||||
emit!(&mut self.output, " push rbp");
|
||||
emit!(&mut self.output, " mov rbp, rsp");
|
||||
@@ -271,6 +274,33 @@ set:
|
||||
emit!(&mut self.output, " call exit");
|
||||
emit!(&mut self.output, "{}:", skip_label);
|
||||
}
|
||||
Stmt::For {
|
||||
var,
|
||||
start,
|
||||
end,
|
||||
body,
|
||||
} => {
|
||||
let begin_label = self.label();
|
||||
let end_label = self.label();
|
||||
|
||||
let offset = env.define_var(var.lexeme, "I64".into());
|
||||
|
||||
self.compile_expr(env, start)?;
|
||||
emit!(&mut self.output, " mov QWORD [rbp-{}], rax", offset);
|
||||
emit!(&mut self.output, "{}:", begin_label);
|
||||
emit!(&mut self.output, " mov rax, QWORD [rbp-{}]", offset);
|
||||
emit!(&mut self.output, " push rax");
|
||||
self.compile_expr(env, end)?;
|
||||
emit!(&mut self.output, " pop rcx");
|
||||
emit!(&mut self.output, " cmp rcx, rax");
|
||||
emit!(&mut self.output, " jge {}", end_label);
|
||||
self.compile_stmt(env, *body)?;
|
||||
emit!(&mut self.output, " mov rax, QWORD [rbp-{}]", offset);
|
||||
emit!(&mut self.output, " add rax, 1");
|
||||
emit!(&mut self.output, " mov QWORD [rbp-{}], rax", offset);
|
||||
emit!(&mut self.output, " jmp {}", begin_label);
|
||||
emit!(&mut self.output, "{}:", end_label);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ fn compile_file(path: String) -> Result<(), ZernError> {
|
||||
}
|
||||
|
||||
if !Command::new("nasm")
|
||||
.args(["-f", "elf64", "-o", "out.o", "out.s"])
|
||||
.args(["-f", "elf64", "-w+all", "-o", "out.o", "out.s"])
|
||||
.status()
|
||||
.unwrap()
|
||||
.success()
|
||||
|
||||
@@ -24,6 +24,12 @@ pub enum Stmt {
|
||||
condition: Expr,
|
||||
body: Box<Stmt>,
|
||||
},
|
||||
For {
|
||||
var: Token,
|
||||
start: Expr,
|
||||
end: Expr,
|
||||
body: Box<Stmt>,
|
||||
},
|
||||
Function {
|
||||
name: Token,
|
||||
params: Vec<Param>,
|
||||
@@ -167,6 +173,8 @@ impl Parser {
|
||||
self.if_statement()
|
||||
} else if self.match_token(&[TokenType::KeywordWhile]) {
|
||||
self.while_statement()
|
||||
} else if self.match_token(&[TokenType::KeywordFor]) {
|
||||
self.for_statement()
|
||||
} else if self.match_token(&[TokenType::KeywordReturn]) {
|
||||
Ok(Stmt::Return(self.expression()?))
|
||||
} else if self.match_token(&[TokenType::KeywordAssert]) {
|
||||
@@ -207,6 +215,22 @@ impl Parser {
|
||||
})
|
||||
}
|
||||
|
||||
fn for_statement(&mut self) -> Result<Stmt, ZernError> {
|
||||
let var = self.consume(TokenType::Identifier, "expected variable name after 'for'")?;
|
||||
self.consume(TokenType::KeywordIn, "expected 'in' after variable name")?;
|
||||
let start = self.expression()?;
|
||||
self.consume(TokenType::Colon, "expected ':' after the number")?;
|
||||
let end = self.expression()?;
|
||||
|
||||
let body = self.block()?;
|
||||
Ok(Stmt::For {
|
||||
var,
|
||||
start,
|
||||
end,
|
||||
body: Box::new(body),
|
||||
})
|
||||
}
|
||||
|
||||
fn expression(&mut self) -> Result<Expr, ZernError> {
|
||||
self.assignment()
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ pub enum TokenType {
|
||||
KeywordIf,
|
||||
KeywordElse,
|
||||
KeywordWhile,
|
||||
KeywordFor,
|
||||
KeywordIn,
|
||||
KeywordFunc,
|
||||
KeywordReturn,
|
||||
KeywordAssert,
|
||||
@@ -310,6 +312,8 @@ impl Tokenizer {
|
||||
"if" => TokenType::KeywordIf,
|
||||
"else" => TokenType::KeywordElse,
|
||||
"while" => TokenType::KeywordWhile,
|
||||
"for" => TokenType::KeywordFor,
|
||||
"in" => TokenType::KeywordIn,
|
||||
"func" => TokenType::KeywordFunc,
|
||||
"return" => TokenType::KeywordReturn,
|
||||
"assert" => TokenType::KeywordAssert,
|
||||
|
||||
Reference in New Issue
Block a user