addr-of operator

This commit is contained in:
2025-12-21 16:11:15 +01:00
parent a259d204be
commit d55ca11658
5 changed files with 43 additions and 1 deletions

View File

@@ -160,6 +160,9 @@ impl Analyzer {
self.analyze_expr(expr)?;
self.analyze_expr(index)?;
}
Expr::AddrOf { op: _, expr } => {
self.analyze_expr(expr)?;
}
}
Ok(())
}

View File

@@ -548,6 +548,31 @@ _builtin_environ:
emit!(&mut self.output, " add rdi, rax");
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(())
}

View File

@@ -71,6 +71,10 @@ pub enum Expr {
expr: Box<Expr>,
index: Box<Expr>,
},
AddrOf {
op: Token,
expr: Box<Expr>,
},
}
// TODO: currently they are all just 8 byte values
@@ -408,6 +412,14 @@ impl Parser {
}
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]) {
let op = self.previous().clone();
let right = self.unary()?;

View File

@@ -18,6 +18,7 @@ pub enum TokenType {
BitAnd,
BitOr,
Pipe,
At,
DoubleDot,
ShiftLeft,
ShiftRight,
@@ -154,6 +155,7 @@ impl Tokenizer {
'%' => self.add_token(TokenType::Mod),
'^' => self.add_token(TokenType::Xor),
':' => self.add_token(TokenType::Colon),
'@' => self.add_token(TokenType::At),
'.' => {
if self.match_char('.') {
self.add_token(TokenType::DoubleDot)

View File

@@ -1,5 +1,5 @@
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(x)
io.println("...\033[0m")