addr-of operator
This commit is contained in:
@@ -160,6 +160,9 @@ impl Analyzer {
|
|||||||
self.analyze_expr(expr)?;
|
self.analyze_expr(expr)?;
|
||||||
self.analyze_expr(index)?;
|
self.analyze_expr(index)?;
|
||||||
}
|
}
|
||||||
|
Expr::AddrOf { op: _, expr } => {
|
||||||
|
self.analyze_expr(expr)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -548,6 +548,31 @@ _builtin_environ:
|
|||||||
emit!(&mut self.output, " add rdi, rax");
|
emit!(&mut self.output, " add rdi, rax");
|
||||||
emit!(&mut self.output, " call _builtin_read8");
|
emit!(&mut self.output, " call _builtin_read8");
|
||||||
}
|
}
|
||||||
|
Expr::AddrOf { op, expr } => match *expr {
|
||||||
|
Expr::Variable(name) => {
|
||||||
|
if self.analyzer.functions.contains_key(&name.lexeme) {
|
||||||
|
emit!(&mut self.output, " mov rax, {}", name.lexeme);
|
||||||
|
} else {
|
||||||
|
let var = match env.get_var(&name.lexeme) {
|
||||||
|
Some(x) => x,
|
||||||
|
None => {
|
||||||
|
return error!(
|
||||||
|
name.loc,
|
||||||
|
format!("undefined variable: {}", &name.lexeme)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
emit!(
|
||||||
|
&mut self.output,
|
||||||
|
" lea rax, QWORD [rbp-{}]",
|
||||||
|
var.stack_offset,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return error!(&op.loc, "can only take address of variables and functions");
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ pub enum Expr {
|
|||||||
expr: Box<Expr>,
|
expr: Box<Expr>,
|
||||||
index: Box<Expr>,
|
index: Box<Expr>,
|
||||||
},
|
},
|
||||||
|
AddrOf {
|
||||||
|
op: Token,
|
||||||
|
expr: Box<Expr>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: currently they are all just 8 byte values
|
// TODO: currently they are all just 8 byte values
|
||||||
@@ -408,6 +412,14 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn unary(&mut self) -> Result<Expr, ZernError> {
|
fn unary(&mut self) -> Result<Expr, ZernError> {
|
||||||
|
if self.match_token(&[TokenType::At]) {
|
||||||
|
let op = self.previous().clone();
|
||||||
|
let right = self.unary()?;
|
||||||
|
return Ok(Expr::AddrOf {
|
||||||
|
op,
|
||||||
|
expr: Box::new(right),
|
||||||
|
});
|
||||||
|
}
|
||||||
if self.match_token(&[TokenType::Bang, TokenType::Minus]) {
|
if self.match_token(&[TokenType::Bang, TokenType::Minus]) {
|
||||||
let op = self.previous().clone();
|
let op = self.previous().clone();
|
||||||
let right = self.unary()?;
|
let right = self.unary()?;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ pub enum TokenType {
|
|||||||
BitAnd,
|
BitAnd,
|
||||||
BitOr,
|
BitOr,
|
||||||
Pipe,
|
Pipe,
|
||||||
|
At,
|
||||||
DoubleDot,
|
DoubleDot,
|
||||||
ShiftLeft,
|
ShiftLeft,
|
||||||
ShiftRight,
|
ShiftRight,
|
||||||
@@ -154,6 +155,7 @@ impl Tokenizer {
|
|||||||
'%' => self.add_token(TokenType::Mod),
|
'%' => self.add_token(TokenType::Mod),
|
||||||
'^' => self.add_token(TokenType::Xor),
|
'^' => self.add_token(TokenType::Xor),
|
||||||
':' => self.add_token(TokenType::Colon),
|
':' => self.add_token(TokenType::Colon),
|
||||||
|
'@' => self.add_token(TokenType::At),
|
||||||
'.' => {
|
'.' => {
|
||||||
if self.match_char('.') {
|
if self.match_char('.') {
|
||||||
self.add_token(TokenType::DoubleDot)
|
self.add_token(TokenType::DoubleDot)
|
||||||
|
|||||||
2
test.zr
2
test.zr
@@ -1,5 +1,5 @@
|
|||||||
func run_test[x: String] : Void
|
func run_test[x: String] : Void
|
||||||
if str.equal(x, "raylib.zr") | str.equal(x, "x11.zr") | str.equal(x, "sqlite_todo.zr")
|
if str.equal(x, "puzzles") | str.equal(x, "raylib.zr") | str.equal(x, "x11.zr") | str.equal(x, "sqlite_todo.zr")
|
||||||
io.print("\033[93mSkipping ")
|
io.print("\033[93mSkipping ")
|
||||||
io.print(x)
|
io.print(x)
|
||||||
io.println("...\033[0m")
|
io.println("...\033[0m")
|
||||||
|
|||||||
Reference in New Issue
Block a user