pipe, return
This commit is contained in:
@@ -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>>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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())?;
|
self.compile_expr(env, args.first().unwrap().clone())?;
|
||||||
writeln!(&mut self.output, " mov rdi, rax")?;
|
writeln!(&mut self.output, " mov rdi, rax")?;
|
||||||
|
}
|
||||||
|
|
||||||
writeln!(&mut self.output, " call {}", callee)?;
|
writeln!(&mut self.output, " call {}", callee)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()?;
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user