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

View File

@@ -31,6 +31,7 @@ pub enum Stmt {
params: Vec<Param>, params: Vec<Param>,
body: Box<Stmt>, body: Box<Stmt>,
}, },
Return(Expr),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -139,11 +140,17 @@ impl Parser {
self.if_statement() self.if_statement()
} else if self.match_token(&[TokenType::KeywordWhile]) { } else if self.match_token(&[TokenType::KeywordWhile]) {
self.while_statement() self.while_statement()
} else if self.match_token(&[TokenType::KeywordReturn]) {
self.return_statement()
} else { } else {
Ok(Stmt::Expression(self.expression()?)) 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>> { fn if_statement(&mut self) -> Result<Stmt, Box<dyn Error>> {
let condition = self.expression()?; let condition = self.expression()?;
let then_branch = self.block()?; let then_branch = self.block()?;
@@ -177,7 +184,7 @@ impl Parser {
} }
fn assignment(&mut self) -> Result<Expr, Box<dyn Error>> { fn assignment(&mut self) -> Result<Expr, Box<dyn Error>> {
let expr = self.logical_or()?; let expr = self.pipe()?;
if self.match_token(&[TokenType::Equal]) { if self.match_token(&[TokenType::Equal]) {
let equals = self.previous().clone(); let equals = self.previous().clone();
@@ -195,6 +202,36 @@ impl Parser {
Ok(expr) 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>> { fn logical_or(&mut self) -> Result<Expr, Box<dyn Error>> {
let mut expr = self.logical_and()?; let mut expr = self.logical_and()?;

View File

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