break and continue
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
/target
|
||||
/out*
|
||||
/TODO
|
||||
/musl-*
|
||||
/musl-*
|
||||
/vscode
|
||||
@@ -17,5 +17,5 @@ func main[] : I64
|
||||
n = n + i
|
||||
if num_divisors(n) > 500
|
||||
print_i64(n)
|
||||
return 0
|
||||
break
|
||||
i = i + 1
|
||||
@@ -7,5 +7,5 @@ func main[] : I64
|
||||
found = found + 1
|
||||
if found == 10001
|
||||
print_i64(i)
|
||||
return 0
|
||||
break
|
||||
i = i + 1
|
||||
@@ -7,7 +7,7 @@ func main[] : I64
|
||||
|
||||
if guess == answer
|
||||
print("You win!")
|
||||
return 0
|
||||
break
|
||||
else if guess < answer
|
||||
print("Too low!")
|
||||
else
|
||||
|
||||
@@ -13,6 +13,8 @@ pub struct Var {
|
||||
pub struct Env {
|
||||
scopes: Vec<HashMap<String, Var>>,
|
||||
next_offset: usize,
|
||||
loop_begin_label: String,
|
||||
loop_end_label: String,
|
||||
}
|
||||
|
||||
impl Env {
|
||||
@@ -20,6 +22,8 @@ impl Env {
|
||||
Env {
|
||||
scopes: vec![HashMap::new()],
|
||||
next_offset: 8,
|
||||
loop_begin_label: String::new(),
|
||||
loop_end_label: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,16 +314,21 @@ _builtin_array_free:
|
||||
emit!(&mut self.output, "{}:", end_label);
|
||||
}
|
||||
Stmt::While { condition, body } => {
|
||||
let begin_label = self.label();
|
||||
let end_label = self.label();
|
||||
let old_loop_begin_label = env.loop_begin_label.clone();
|
||||
let old_loop_end_label = env.loop_end_label.clone();
|
||||
env.loop_begin_label = self.label();
|
||||
env.loop_end_label = self.label();
|
||||
|
||||
emit!(&mut self.output, "{}:", begin_label);
|
||||
emit!(&mut self.output, "{}:", env.loop_begin_label);
|
||||
self.compile_expr(env, condition)?;
|
||||
emit!(&mut self.output, " test rax, rax");
|
||||
emit!(&mut self.output, " je {}", end_label);
|
||||
emit!(&mut self.output, " je {}", env.loop_end_label);
|
||||
self.compile_stmt(env, *body.clone())?;
|
||||
emit!(&mut self.output, " jmp {}", begin_label);
|
||||
emit!(&mut self.output, "{}:", end_label);
|
||||
emit!(&mut self.output, " jmp {}", env.loop_begin_label);
|
||||
emit!(&mut self.output, "{}:", env.loop_end_label);
|
||||
|
||||
env.loop_begin_label = old_loop_begin_label;
|
||||
env.loop_end_label = old_loop_end_label;
|
||||
}
|
||||
Stmt::Function {
|
||||
name,
|
||||
@@ -371,28 +380,40 @@ _builtin_array_free:
|
||||
end,
|
||||
body,
|
||||
} => {
|
||||
let begin_label = self.label();
|
||||
let end_label = self.label();
|
||||
let old_loop_begin_label = env.loop_begin_label.clone();
|
||||
let old_loop_end_label = env.loop_end_label.clone();
|
||||
env.loop_begin_label = self.label();
|
||||
env.loop_end_label = self.label();
|
||||
|
||||
env.push_scope();
|
||||
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, "{}:", env.loop_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);
|
||||
emit!(&mut self.output, " jge {}", env.loop_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);
|
||||
emit!(&mut self.output, " jmp {}", env.loop_begin_label);
|
||||
emit!(&mut self.output, "{}:", env.loop_end_label);
|
||||
env.pop_scope();
|
||||
|
||||
env.loop_begin_label = old_loop_begin_label;
|
||||
env.loop_end_label = old_loop_end_label;
|
||||
}
|
||||
Stmt::Break => {
|
||||
emit!(&mut self.output, " jmp {}", env.loop_end_label);
|
||||
}
|
||||
Stmt::Continue => {
|
||||
// TODO: skips incrementing when used in a for loop
|
||||
emit!(&mut self.output, " jmp {}", env.loop_begin_label);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -37,6 +37,8 @@ pub enum Stmt {
|
||||
body: Box<Stmt>,
|
||||
},
|
||||
Return(Expr),
|
||||
Break,
|
||||
Continue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -193,6 +195,10 @@ impl Parser {
|
||||
self.for_statement()
|
||||
} else if self.match_token(&[TokenType::KeywordReturn]) {
|
||||
Ok(Stmt::Return(self.expression()?))
|
||||
} else if self.match_token(&[TokenType::KeywordBreak]) {
|
||||
Ok(Stmt::Break)
|
||||
} else if self.match_token(&[TokenType::KeywordContinue]) {
|
||||
Ok(Stmt::Continue)
|
||||
} else {
|
||||
Ok(Stmt::Expression(self.expression()?))
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ pub enum TokenType {
|
||||
KeywordIn,
|
||||
KeywordFunc,
|
||||
KeywordReturn,
|
||||
KeywordBreak,
|
||||
KeywordContinue,
|
||||
|
||||
Indent,
|
||||
Dedent,
|
||||
@@ -335,6 +337,8 @@ impl Tokenizer {
|
||||
"in" => TokenType::KeywordIn,
|
||||
"func" => TokenType::KeywordFunc,
|
||||
"return" => TokenType::KeywordReturn,
|
||||
"break" => TokenType::KeywordBreak,
|
||||
"continue" => TokenType::KeywordContinue,
|
||||
"true" => TokenType::True,
|
||||
"false" => TokenType::False,
|
||||
_ => TokenType::Identifier,
|
||||
|
||||
Reference in New Issue
Block a user