From 3a876a97d3259977b90cc464006e927d3ee63bf2 Mon Sep 17 00:00:00 2001 From: Toni Date: Fri, 30 May 2025 17:51:16 +0200 Subject: [PATCH] calls --- src/codegen.rs | 42 ++++++++++++++++++++++++++++++------------ src/main.rs | 6 ++++-- src/parser.rs | 38 +++++++++++++++++++++++++++++++++----- src/tokenizer.rs | 2 -- test.mot | 2 +- 5 files changed, 68 insertions(+), 22 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index bb922d3..1fa6522 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -106,22 +106,12 @@ section .note.GNU-stack pub fn compile_stmt(&mut self, env: &mut Env, stmt: Stmt) -> Result<(), Box> { 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(()) } diff --git a/src/main.rs b/src/main.rs index bddccca..b48144b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,14 +6,16 @@ use std::{ env, error::Error, fs, + path::Path, process::{self, Command}, }; fn compile_file(path: String) -> Result<(), Box> { 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); diff --git a/src/parser.rs b/src/parser.rs index c728a72..b630dcb 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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, }, + Call { + callee: Box, + paren: Token, + args: Vec, + }, } pub struct Parser { @@ -95,9 +99,7 @@ impl Parser { } fn statement(&mut self) -> Result> { - 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> { + 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> { diff --git a/src/tokenizer.rs b/src/tokenizer.rs index b2d51a4..ad5e713 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -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, diff --git a/test.mot b/test.mot index 235111c..a4b0591 100644 --- a/test.mot +++ b/test.mot @@ -2,7 +2,7 @@ let a: I64 = 0 let b: I64 = 1 while a < 100000 - print a + print(a) let temp: I64 = b b = a + b a = temp \ No newline at end of file