Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions examples/abs.zy
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const std = import("std");

fn abs(x: i32): i32 {
return if x < 0 then -x else x
}

fn main(): void {
std.debug.print(abs(-42));
}
44 changes: 41 additions & 3 deletions src/codegen/zig/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,23 @@ impl ZigBackend {
StmtKind::Return(Some(e)) => format!("{}return {};\n", ind, self.gen_expr(e)),
StmtKind::Break => format!("{}break;\n", ind),
StmtKind::Continue => format!("{}continue;\n", ind),
StmtKind::If { cond, body } => self.gen_cond_block("if", cond, body, level),
StmtKind::If {
cond,
body,
else_body,
} => {
let mut s = self.gen_cond_block("if", cond, body, level);
if let Some(else_stmts) = else_body {
let ind = Self::indent(level);
s.pop(); // remove trailing '\n'
s.push_str(" else {\n");
for stmt in else_stmts {
s.push_str(&self.gen_stmt(stmt, level + 1));
}
s.push_str(&format!("{}}}\n", ind));
}
s
}
StmtKind::While { cond, body } => self.gen_cond_block("while", cond, body, level),
StmtKind::ExprStmt(e) => {
let s = self.gen_expr(e);
Expand Down Expand Up @@ -594,6 +610,15 @@ impl ZigBackend {
out.push('}');
out
}

ExprKind::If { cond, then, else_ } => {
format!(
"if ({}) {} else {}",
self.gen_expr(cond),
self.gen_expr(then),
self.gen_expr(else_)
)
}
}
}

Expand All @@ -607,8 +632,16 @@ impl ZigBackend {
Self::expr_references_var(value, var)
}
StmtKind::Return(Some(e)) => Self::expr_references_var(e, var),
StmtKind::If { cond, body } => {
Self::expr_references_var(cond, var) || Self::stmts_reference_var(body, var)
StmtKind::If {
cond,
body,
else_body,
} => {
Self::expr_references_var(cond, var)
|| Self::stmts_reference_var(body, var)
|| else_body
.as_ref()
.is_some_and(|s| Self::stmts_reference_var(s, var))
}
StmtKind::While { cond, body } => {
Self::expr_references_var(cond, var) || Self::stmts_reference_var(body, var)
Expand Down Expand Up @@ -647,6 +680,11 @@ impl ZigBackend {
ExprKind::Index { obj, idx } => {
Self::expr_references_var(obj, var) || Self::expr_references_var(idx, var)
}
ExprKind::If { cond, then, else_ } => {
Self::expr_references_var(cond, var)
|| Self::expr_references_var(then, var)
|| Self::expr_references_var(else_, var)
}
_ => false,
}
}
Expand Down
15 changes: 13 additions & 2 deletions src/codegen/zig/stdlib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,14 @@ impl ZigBackend {
self.expr_uses_allocator(value)
}
StmtKind::Return(Some(e)) => self.expr_uses_allocator(e),
StmtKind::If { cond, body } => {
self.expr_uses_allocator(cond) || self.uses_allocator(body)
StmtKind::If {
cond,
body,
else_body,
} => {
self.expr_uses_allocator(cond)
|| self.uses_allocator(body)
|| else_body.as_ref().is_some_and(|s| self.uses_allocator(s))
}
StmtKind::While { cond, body } => {
self.expr_uses_allocator(cond) || self.uses_allocator(body)
Expand Down Expand Up @@ -96,6 +102,11 @@ impl ZigBackend {
ExprKind::Index { obj, idx } => {
self.expr_uses_allocator(obj) || self.expr_uses_allocator(idx)
}
ExprKind::If { cond, then, else_ } => {
self.expr_uses_allocator(cond)
|| self.expr_uses_allocator(then)
|| self.expr_uses_allocator(else_)
}
_ => false,
}
}
Expand Down
31 changes: 29 additions & 2 deletions src/codegen/zig/tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,18 @@ impl ZigBackend {
}
StmtKind::Return(Some(e)) => self.expr_calls_any(e, targets),
StmtKind::ExprStmt(e) => self.expr_calls_any(e, targets),
StmtKind::If { cond, body } | StmtKind::While { cond, body } => {
StmtKind::If {
cond,
body,
else_body,
} => {
self.expr_calls_any(cond, targets)
|| self.stmts_call_any(body, targets)
|| else_body
.as_ref()
.is_some_and(|s| self.stmts_call_any(s, targets))
}
StmtKind::While { cond, body } => {
self.expr_calls_any(cond, targets) || self.stmts_call_any(body, targets)
}
_ => false,
Expand Down Expand Up @@ -89,6 +100,11 @@ impl ZigBackend {
SwitchBody::Block(stmts) => self.stmts_call_any(stmts, targets),
})
}
ExprKind::If { cond, then, else_ } => {
self.expr_calls_any(cond, targets)
|| self.expr_calls_any(then, targets)
|| self.expr_calls_any(else_, targets)
}
_ => false,
}
}
Expand All @@ -113,7 +129,15 @@ impl ZigBackend {
self.expr_uses_std(value)
}
StmtKind::Return(Some(e)) => self.expr_uses_std(e),
StmtKind::If { cond, body } => self.expr_uses_std(cond) || self.stmts_use_std(body),
StmtKind::If {
cond,
body,
else_body,
} => {
self.expr_uses_std(cond)
|| self.stmts_use_std(body)
|| else_body.as_ref().is_some_and(|s| self.stmts_use_std(s))
}
StmtKind::While { cond, body } => self.expr_uses_std(cond) || self.stmts_use_std(body),
StmtKind::ExprStmt(e) => self.expr_uses_std(e),
_ => false,
Expand Down Expand Up @@ -163,6 +187,9 @@ impl ZigBackend {
}
ExprKind::ArrayLiteral(elems) => elems.iter().any(|e| self.expr_uses_std(e)),
ExprKind::Index { obj, idx } => self.expr_uses_std(obj) || self.expr_uses_std(idx),
ExprKind::If { cond, then, else_ } => {
self.expr_uses_std(cond) || self.expr_uses_std(then) || self.expr_uses_std(else_)
}
_ => false,
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub enum Token {
Switch,
Catch,
Else,
Then,
// Type keywords
Void,
// Literals
Expand Down Expand Up @@ -132,7 +133,7 @@ fn tokenize_raw(source: &str) -> Vec<(Token, Span)> {
'\n' => {
chars.next();
// Insert AutoSemi if the previous token can end a statement
if tokens.last().map(|(t, _)| can_end_stmt(t)).unwrap_or(false) {
if tokens.last().is_some_and(|(t, _)| can_end_stmt(t)) {
tokens.push((Token::AutoSemi, (pos, pos + 1)));
}
}
Expand Down Expand Up @@ -307,6 +308,7 @@ fn tokenize_raw(source: &str) -> Vec<(Token, Span)> {
"switch" => Token::Switch,
"catch" => Token::Catch,
"else" => Token::Else,
"then" => Token::Then,
"and" => Token::And,
"or" => Token::Or,
"void" => Token::Void,
Expand Down
39 changes: 38 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ pub enum ExprKind {
obj: Box<Expr>,
idx: Box<Expr>,
}, // arr[i] index expression
If {
cond: Box<Expr>,
then: Box<Expr>,
else_: Box<Expr>,
},
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -145,6 +150,7 @@ pub enum StmtKind {
If {
cond: Expr,
body: Vec<Stmt>,
else_body: Option<Vec<Stmt>>,
},
While {
cond: Expr,
Expand Down Expand Up @@ -549,8 +555,21 @@ impl Parser {
self.expect(Token::LBrace);
let body = self.parse_block();
self.expect(Token::RBrace);
let else_body = if self.peek() == &Token::Else {
self.advance();
self.expect(Token::LBrace);
let b = self.parse_block();
self.expect(Token::RBrace);
Some(b)
} else {
None
};
Stmt {
kind: StmtKind::If { cond, body },
kind: StmtKind::If {
cond,
body,
else_body,
},
span,
}
}
Expand Down Expand Up @@ -887,6 +906,24 @@ impl Parser {
span,
}
}
Token::If => {
let span_start = self.peek_span().0;
self.advance();
let cond = self.parse_expr();
self.expect(Token::Then);
let then = self.parse_expr();
self.expect(Token::Else);
let else_ = self.parse_expr();
let span = (span_start, self.prev_end());
Expr {
kind: ExprKind::If {
cond: Box::new(cond),
then: Box::new(then),
else_: Box::new(else_),
},
span,
}
}
Token::Import => {
let span_start = self.peek_span().0;
self.advance();
Expand Down
Loading