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