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>> {
|
||||
match stmt {
|
||||
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 {
|
||||
name,
|
||||
var_type,
|
||||
initializer,
|
||||
} => {
|
||||
// TODO
|
||||
// TODO: types
|
||||
assert!(var_type.lexeme == "I64");
|
||||
|
||||
self.compile_expr(env, initializer)?;
|
||||
@@ -193,7 +183,11 @@ section .note.GNU-stack
|
||||
TokenType::Xor => writeln!(&mut self.output, " xor rax, rbx")?,
|
||||
TokenType::And => 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::Greater => todo!(),
|
||||
TokenType::GreaterEqual => todo!(),
|
||||
@@ -248,6 +242,30 @@ section .note.GNU-stack
|
||||
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(())
|
||||
}
|
||||
|
||||
@@ -6,14 +6,16 @@ use std::{
|
||||
env,
|
||||
error::Error,
|
||||
fs,
|
||||
path::Path,
|
||||
process::{self, Command},
|
||||
};
|
||||
|
||||
fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
|
||||
let source = fs::read_to_string(path.clone())?;
|
||||
|
||||
// TODO: basename
|
||||
let tokenizer = tokenizer::Tokenizer::new(path, source);
|
||||
let filename = Path::new(&path).file_name().unwrap().to_str().unwrap();
|
||||
|
||||
let tokenizer = tokenizer::Tokenizer::new(filename.to_owned(), source);
|
||||
let tokens = tokenizer.tokenize()?;
|
||||
|
||||
let parser = parser::Parser::new(tokens);
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::tokenizer::{MotError, Token, TokenType, error};
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Stmt {
|
||||
Expression(Expr),
|
||||
Print(Expr),
|
||||
Var {
|
||||
name: Token,
|
||||
var_type: Token,
|
||||
@@ -41,6 +40,11 @@ pub enum Expr {
|
||||
name: Token,
|
||||
value: Box<Expr>,
|
||||
},
|
||||
Call {
|
||||
callee: Box<Expr>,
|
||||
paren: Token,
|
||||
args: Vec<Expr>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct Parser {
|
||||
@@ -95,9 +99,7 @@ impl Parser {
|
||||
}
|
||||
|
||||
fn statement(&mut self) -> Result<Stmt, Box<dyn Error>> {
|
||||
if self.match_token(&[TokenType::KeywordPrint]) {
|
||||
Ok(Stmt::Print(self.expression()?))
|
||||
} else if self.match_token(&[TokenType::KeywordIf]) {
|
||||
if self.match_token(&[TokenType::KeywordIf]) {
|
||||
self.if_statement()
|
||||
} else if self.match_token(&[TokenType::KeywordWhile]) {
|
||||
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>> {
|
||||
|
||||
@@ -30,7 +30,6 @@ pub enum TokenType {
|
||||
String,
|
||||
Number,
|
||||
|
||||
KeywordPrint,
|
||||
KeywordLet,
|
||||
KeywordIf,
|
||||
KeywordElse,
|
||||
@@ -295,7 +294,6 @@ impl Tokenizer {
|
||||
|
||||
let lexeme: String = self.source[self.start..self.current].iter().collect();
|
||||
self.add_token(match lexeme.as_str() {
|
||||
"print" => TokenType::KeywordPrint,
|
||||
"let" => TokenType::KeywordLet,
|
||||
"if" => TokenType::KeywordIf,
|
||||
"else" => TokenType::KeywordElse,
|
||||
|
||||
Reference in New Issue
Block a user