calls
This commit is contained in:
@@ -106,22 +106,12 @@ section .note.GNU-stack
|
|||||||
pub fn compile_stmt(&mut self, env: &mut Env, stmt: Stmt) -> Result<(), Box<dyn Error>> {
|
pub 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)?,
|
||||||
Stmt::Print(expr) => {
|
|
||||||
self.compile_expr(env, expr)?;
|
|
||||||
writeln!(
|
|
||||||
&mut self.output,
|
|
||||||
" mov rdi, format
|
|
||||||
mov rsi, rax
|
|
||||||
xor rax, rax
|
|
||||||
call printf"
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
Stmt::Var {
|
Stmt::Var {
|
||||||
name,
|
name,
|
||||||
var_type,
|
var_type,
|
||||||
initializer,
|
initializer,
|
||||||
} => {
|
} => {
|
||||||
// TODO
|
// TODO: types
|
||||||
assert!(var_type.lexeme == "I64");
|
assert!(var_type.lexeme == "I64");
|
||||||
|
|
||||||
self.compile_expr(env, initializer)?;
|
self.compile_expr(env, initializer)?;
|
||||||
@@ -193,7 +183,11 @@ section .note.GNU-stack
|
|||||||
TokenType::Xor => writeln!(&mut self.output, " xor rax, rbx")?,
|
TokenType::Xor => writeln!(&mut self.output, " xor rax, rbx")?,
|
||||||
TokenType::And => todo!(),
|
TokenType::And => todo!(),
|
||||||
TokenType::Or => todo!(),
|
TokenType::Or => todo!(),
|
||||||
TokenType::DoubleEqual => todo!(),
|
TokenType::DoubleEqual => {
|
||||||
|
writeln!(&mut self.output, " cmp rax, rbx")?;
|
||||||
|
writeln!(&mut self.output, " sete al")?;
|
||||||
|
writeln!(&mut self.output, " movzx rax, al")?;
|
||||||
|
}
|
||||||
TokenType::NotEqual => todo!(),
|
TokenType::NotEqual => todo!(),
|
||||||
TokenType::Greater => todo!(),
|
TokenType::Greater => todo!(),
|
||||||
TokenType::GreaterEqual => todo!(),
|
TokenType::GreaterEqual => todo!(),
|
||||||
@@ -248,6 +242,30 @@ section .note.GNU-stack
|
|||||||
var.stack_offset
|
var.stack_offset
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
Expr::Call {
|
||||||
|
callee,
|
||||||
|
paren: _,
|
||||||
|
args,
|
||||||
|
} => {
|
||||||
|
let callee = match *callee {
|
||||||
|
Expr::Variable(name) => name.lexeme,
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
assert!(callee == "print");
|
||||||
|
assert!(args.len() == 1);
|
||||||
|
|
||||||
|
self.compile_expr(env, args.first().unwrap().clone())?;
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
&mut self.output,
|
||||||
|
" mov rdi, format
|
||||||
|
mov rsi, rax
|
||||||
|
xor rax, rax
|
||||||
|
call printf"
|
||||||
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,16 @@ use std::{
|
|||||||
env,
|
env,
|
||||||
error::Error,
|
error::Error,
|
||||||
fs,
|
fs,
|
||||||
|
path::Path,
|
||||||
process::{self, Command},
|
process::{self, Command},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
|
fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
|
||||||
let source = fs::read_to_string(path.clone())?;
|
let source = fs::read_to_string(path.clone())?;
|
||||||
|
|
||||||
// TODO: basename
|
let filename = Path::new(&path).file_name().unwrap().to_str().unwrap();
|
||||||
let tokenizer = tokenizer::Tokenizer::new(path, source);
|
|
||||||
|
let tokenizer = tokenizer::Tokenizer::new(filename.to_owned(), source);
|
||||||
let tokens = tokenizer.tokenize()?;
|
let tokens = tokenizer.tokenize()?;
|
||||||
|
|
||||||
let parser = parser::Parser::new(tokens);
|
let parser = parser::Parser::new(tokens);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use crate::tokenizer::{MotError, Token, TokenType, error};
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Expression(Expr),
|
Expression(Expr),
|
||||||
Print(Expr),
|
|
||||||
Var {
|
Var {
|
||||||
name: Token,
|
name: Token,
|
||||||
var_type: Token,
|
var_type: Token,
|
||||||
@@ -41,6 +40,11 @@ pub enum Expr {
|
|||||||
name: Token,
|
name: Token,
|
||||||
value: Box<Expr>,
|
value: Box<Expr>,
|
||||||
},
|
},
|
||||||
|
Call {
|
||||||
|
callee: Box<Expr>,
|
||||||
|
paren: Token,
|
||||||
|
args: Vec<Expr>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
@@ -95,9 +99,7 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn statement(&mut self) -> Result<Stmt, Box<dyn Error>> {
|
fn statement(&mut self) -> Result<Stmt, Box<dyn Error>> {
|
||||||
if self.match_token(&[TokenType::KeywordPrint]) {
|
if self.match_token(&[TokenType::KeywordIf]) {
|
||||||
Ok(Stmt::Print(self.expression()?))
|
|
||||||
} else if self.match_token(&[TokenType::KeywordIf]) {
|
|
||||||
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()
|
||||||
@@ -268,7 +270,33 @@ impl Parser {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.primary()
|
self.call()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self) -> Result<Expr, Box<dyn Error>> {
|
||||||
|
let mut expr = self.primary()?;
|
||||||
|
|
||||||
|
while self.match_token(&[TokenType::LeftParen]) {
|
||||||
|
let mut args = vec![];
|
||||||
|
if !self.check(&TokenType::RightParen) {
|
||||||
|
loop {
|
||||||
|
args.push(self.expression()?);
|
||||||
|
if !self.match_token(&[TokenType::Comma]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let paren = self.consume(TokenType::RightParen, "expected ')' after arguments")?;
|
||||||
|
|
||||||
|
expr = Expr::Call {
|
||||||
|
callee: Box::new(expr),
|
||||||
|
paren,
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn primary(&mut self) -> Result<Expr, Box<dyn Error>> {
|
fn primary(&mut self) -> Result<Expr, Box<dyn Error>> {
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ pub enum TokenType {
|
|||||||
String,
|
String,
|
||||||
Number,
|
Number,
|
||||||
|
|
||||||
KeywordPrint,
|
|
||||||
KeywordLet,
|
KeywordLet,
|
||||||
KeywordIf,
|
KeywordIf,
|
||||||
KeywordElse,
|
KeywordElse,
|
||||||
@@ -295,7 +294,6 @@ impl Tokenizer {
|
|||||||
|
|
||||||
let lexeme: String = self.source[self.start..self.current].iter().collect();
|
let lexeme: String = self.source[self.start..self.current].iter().collect();
|
||||||
self.add_token(match lexeme.as_str() {
|
self.add_token(match lexeme.as_str() {
|
||||||
"print" => TokenType::KeywordPrint,
|
|
||||||
"let" => TokenType::KeywordLet,
|
"let" => TokenType::KeywordLet,
|
||||||
"if" => TokenType::KeywordIf,
|
"if" => TokenType::KeywordIf,
|
||||||
"else" => TokenType::KeywordElse,
|
"else" => TokenType::KeywordElse,
|
||||||
|
|||||||
Reference in New Issue
Block a user