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

View File

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

View File

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

View File

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

View File

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