This commit is contained in:
2025-05-30 17:51:16 +02:00
parent f72e8a4149
commit 3a876a97d3
5 changed files with 68 additions and 22 deletions

View File

@@ -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(())
} }

View File

@@ -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);

View File

@@ -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>> {

View File

@@ -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,

View File

@@ -2,7 +2,7 @@ let a: I64 = 0
let b: I64 = 1 let b: I64 = 1
while a < 100000 while a < 100000
print a print(a)
let temp: I64 = b let temp: I64 = b
b = a + b b = a + b
a = temp a = temp