pipe, return

This commit is contained in:
2025-05-30 22:20:42 +02:00
parent 397f87c242
commit cfe35bcc9d
4 changed files with 61 additions and 11 deletions

View File

@@ -49,9 +49,9 @@ impl Env {
}
pub trait Codegen {
fn get_output(&self) -> String;
fn emit_prologue(&mut self) -> Result<(), Box<dyn Error>>;
fn emit_epilogue(&mut self) -> Result<(), Box<dyn Error>>;
fn get_output(&self) -> String;
fn compile_stmt(&mut self, env: &mut Env, stmt: Stmt) -> Result<(), Box<dyn Error>>;
fn compile_expr(&mut self, env: &mut Env, expr: Expr) -> Result<(), Box<dyn Error>>;
}

View File

@@ -26,6 +26,10 @@ impl CodegenX86_64 {
}
impl Codegen for CodegenX86_64 {
fn get_output(&self) -> String {
self.output.clone()
}
fn emit_prologue(&mut self) -> Result<(), Box<dyn Error>> {
writeln!(
&mut self.output,
@@ -55,10 +59,6 @@ print:
Ok(())
}
fn get_output(&self) -> String {
self.output.clone()
}
fn compile_stmt(&mut self, env: &mut Env, stmt: Stmt) -> Result<(), Box<dyn Error>> {
match stmt {
Stmt::Expression(expr) => self.compile_expr(env, expr)?,
@@ -121,9 +121,15 @@ print:
self.compile_stmt(env, *body)?;
writeln!(&mut self.output, " mov rax, 0")?;
writeln!(&mut self.output, " mov rsp, rbp")?;
writeln!(&mut self.output, " pop rbp")?;
writeln!(&mut self.output, " ret")?;
}
Stmt::Return(expr) => {
self.compile_expr(env, expr)?;
writeln!(&mut self.output, " mov rsp, rbp")?;
writeln!(&mut self.output, " pop rbp")?;
writeln!(&mut self.output, " mov rax, 0")?;
writeln!(&mut self.output, " ret")?;
}
}
@@ -245,10 +251,12 @@ print:
};
// TODO
assert!(args.len() == 1);
assert!(args.len() <= 1);
if args.len() == 1 {
self.compile_expr(env, args.first().unwrap().clone())?;
writeln!(&mut self.output, " mov rdi, rax")?;
}
writeln!(&mut self.output, " call {}", callee)?;
}
}

View File

@@ -31,6 +31,7 @@ pub enum Stmt {
params: Vec<Param>,
body: Box<Stmt>,
},
Return(Expr),
}
#[derive(Debug, Clone)]
@@ -139,11 +140,17 @@ impl Parser {
self.if_statement()
} else if self.match_token(&[TokenType::KeywordWhile]) {
self.while_statement()
} else if self.match_token(&[TokenType::KeywordReturn]) {
self.return_statement()
} else {
Ok(Stmt::Expression(self.expression()?))
}
}
fn return_statement(&mut self) -> Result<Stmt, Box<dyn Error>> {
Ok(Stmt::Return(self.expression()?))
}
fn if_statement(&mut self) -> Result<Stmt, Box<dyn Error>> {
let condition = self.expression()?;
let then_branch = self.block()?;
@@ -177,7 +184,7 @@ impl Parser {
}
fn assignment(&mut self) -> Result<Expr, Box<dyn Error>> {
let expr = self.logical_or()?;
let expr = self.pipe()?;
if self.match_token(&[TokenType::Equal]) {
let equals = self.previous().clone();
@@ -195,6 +202,36 @@ impl Parser {
Ok(expr)
}
fn pipe(&mut self) -> Result<Expr, Box<dyn Error>> {
let mut expr = self.logical_or()?;
while self.match_token(&[TokenType::Pipe]) {
let pipe = self.previous().clone();
let right = self.equality()?;
match right {
Expr::Call {
callee,
paren,
args,
} => {
let mut new_args = args;
new_args.insert(0, expr);
expr = Expr::Call {
callee,
paren,
args: new_args,
}
}
_ => {
return error!(pipe.loc, "tried to pipe into a non-call expression");
}
};
}
Ok(expr)
}
fn logical_or(&mut self) -> Result<Expr, Box<dyn Error>> {
let mut expr = self.logical_and()?;

View File

@@ -17,6 +17,7 @@ pub enum TokenType {
Colon,
And,
Or,
Pipe,
Equal,
DoubleEqual,
@@ -35,6 +36,7 @@ pub enum TokenType {
KeywordElse,
KeywordWhile,
KeywordFunc,
KeywordReturn,
Indent,
Dedent,
@@ -159,8 +161,10 @@ impl Tokenizer {
'|' => {
if self.match_char('|') {
self.add_token(TokenType::Or);
} else if self.match_char('>') {
self.add_token(TokenType::Pipe);
} else {
return error!(self.loc, "expected '|' after '|'");
return error!(self.loc, "expected '>' or '|' after '|'");
}
}
'!' => {
@@ -300,6 +304,7 @@ impl Tokenizer {
"else" => TokenType::KeywordElse,
"while" => TokenType::KeywordWhile,
"func" => TokenType::KeywordFunc,
"return" => TokenType::KeywordReturn,
_ => TokenType::Identifier,
})
}