From 9aaaa2935f1a414448fe6a86eb04e179c7761b19 Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Wed, 27 Nov 2024 21:36:17 -0700 Subject: [PATCH] compiler wip --- Cargo.toml | 4 + src/compiler/mod.rs | 178 ++++++++++++++++++++++++++++++++++---------- tests/file.stlg | 13 +--- 3 files changed, 146 insertions(+), 49 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a46402b..32ae60f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,10 @@ name = "stationlang" version = "0.1.0" edition = "2021" +[[bin]] +name = "slang" +path = "src/main.rs" + [dependencies] clap = { version = "^4.5", features = ["derive"] } quick-error = "2.0.1" diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 150161b..f9ac0ec 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -1,6 +1,8 @@ use crate::parser::tree_node::*; use crate::parser::Parser as ASTParser; +use std::borrow::BorrowMut; use std::collections::HashMap; +use std::collections::VecDeque; use std::io::BufWriter; use std::io::Write; @@ -24,14 +26,27 @@ quick_error! { } } +macro_rules! variable_index { + ($compiler:expr, $name:expr) => { + $compiler + .variable_scope + .iter() + .rev() + .find(|v| v.contains_key(&$name)) + .map(|v| v[&$name]) + .ok_or(CompileError::ScopeError)? + }; +} + pub struct Compiler<'a> { parser: ASTParser, /// Max stack size for the program is by default 512. variable_scope: Vec>, + function_locations: HashMap, output: &'a mut BufWriter>, stack_pointer: usize, /// A map of variable names to register numbers. 0-15 are reserved for variables, 16 is the stack pointer, 17 is the return address - register: HashMap, + register: VecDeque, max_stack_size: usize, current_line: usize, } @@ -45,14 +60,34 @@ impl<'a> Compiler<'a> { Self { parser, variable_scope: Vec::new(), + function_locations: HashMap::new(), output: writer, stack_pointer: 0, - register: HashMap::new(), + register: VecDeque::new(), max_stack_size, current_line: 0, } } + fn write_output(&mut self, output: impl Into) -> Result<(), CompileError> { + self.output.write(output.into().as_bytes())?; + self.current_line += 1; + + Ok(()) + } + + fn push_register(&mut self) -> Result<(), CompileError> { + if self.register.len() >= 15 { + return Err(CompileError::ScopeError); + } + self.register.push_back(self.register.len() as u8); + Ok(()) + } + + fn pop_register(&mut self) -> Result { + self.register.pop_back().ok_or(CompileError::ScopeError) + } + pub fn compile(mut self) -> Result<(), CompileError> { let ast = self.parser.parse_all()?; @@ -67,71 +102,136 @@ impl<'a> Compiler<'a> { fn expression(&mut self, expression: Expression) -> Result<(), CompileError> { match expression { - Expression::BlockExpression(block) => self.block_expression(block)?, - Expression::DeclarationExpression(name, expr) => { - self.declaration_expression(name, expr)? + Expression::BinaryExpression(expr) => self.binary_expression(expr)?, + Expression::BlockExpression(expr) => self.block_expression(expr)?, + Expression::DeclarationExpression(ident, expr) => { + self.declaration_expression(ident, *expr)? } - Expression::ReturnExpression(expr) => self.return_expression(*expr)?, - Expression::FunctionExpression(func) => self.function_expression(func)?, + Expression::FunctionExpression(expr) => self.function_expression(expr)?, + _ => todo!("{:?}", expression), }; - todo!() - } - - fn function_expression(&mut self, func: FunctionExpression) -> Result<(), CompileError> { - for arg in func.arguments { - self.variable_scope - .last_mut() - .ok_or(CompileError::ScopeError)? - .insert(arg, self.stack_pointer); - self.stack_pointer += 1; - } - - for expr in func.body.0 { - self.expression(expr)?; - } - Ok(()) } - fn return_expression(&mut self, expression: Expression) -> Result<(), CompileError> { - // pop last var off the stack and push it into the first available register - let register = self.register.len() as u8; - self.output - .write(&format!("pop r{}\n", register).as_bytes())?; + fn function_expression(&mut self, expr: FunctionExpression) -> Result<(), CompileError> { + // in stack order: return address, arguments + + self.function_locations + .insert(expr.name.clone(), self.current_line); + + self.variable_scope.push(HashMap::new()); + let total_args = expr.arguments.len(); + for (index, arg) in expr.arguments.iter().enumerate() { + + } - self.stack_pointer - .checked_sub(1) - .ok_or(CompileError::ScopeError)?; - self.current_line += 1; Ok(()) } fn declaration_expression( &mut self, - name: String, - expression: Box, + ident: String, + expression: Expression, ) -> Result<(), CompileError> { - self.expression(*expression)?; + let stack_index = self.stack_pointer; + self.stack_pointer += 1; + + match expression { + Expression::Literal(Literal::Number(num)) => { + self.write_output(format!("poke {stack_index} {num}\n"))?; + } + _ => { + self.expression(expression)?; + let register = self.register.len(); + self.write_output(format!("poke {stack_index} r{register}\n"))?; + self.register.pop_back(); + } + }; self.variable_scope .last_mut() .ok_or(CompileError::ScopeError)? - .insert(name, self.stack_pointer); - self.stack_pointer += 1; + .insert(ident, stack_index); + Ok(()) } fn block_expression(&mut self, expression: BlockExpression) -> Result<(), CompileError> { - // Push a new scope. This will be read from all the child expressions self.variable_scope.push(HashMap::new()); for expr in expression.0 { self.expression(expr)?; } - // Remove the scope we just added, all variables are now out of scope self.variable_scope.pop(); + + Ok(()) + } + + fn binary_expression(&mut self, expression: BinaryExpression) -> Result<(), CompileError> { + fn handle_expression<'a>( + compiler: &'a mut Compiler, + left: Expression, + right: Expression, + operator: &'static str, + register_number: u8, + ) -> Result<(), CompileError> { + let value_left = match left { + Expression::Literal(Literal::Number(num)) => { + format!("{num}") + } + Expression::Variable(name) => { + let stack_index = variable_index!(compiler, name); + compiler.write_output(format!( + "get r{0} d0 {stack_index}\n", + register_number + 1 + ))?; + format!("r{0}", register_number + 1) + } + _ => todo!(), + }; + + let value_right = match right { + Expression::Literal(Literal::Number(num)) => { + format!("{num}") + } + Expression::Variable(name) => { + let stack_index = variable_index!(compiler, name); + compiler.write_output(format!( + "get r{0} d0 {stack_index}\n", + register_number + 2 + ))?; + format!("r{0}", register_number + 2) + } + _ => todo!(), + }; + + compiler.write_output(format!( + "{operator} r{register_number} {value_left} {value_right}\n" + ))?; + + Ok(()) + } + + let result_register = self.register.len(); + + match expression { + BinaryExpression::Add(left, right) => { + handle_expression(self, *left, *right, "add", result_register as u8)? + } + BinaryExpression::Subtract(left, right) => { + handle_expression(self, *left, *right, "sub", result_register as u8)? + } + BinaryExpression::Multiply(left, right) => { + handle_expression(self, *left, *right, "mul", result_register as u8)? + } + BinaryExpression::Divide(left, right) => { + handle_expression(self, *left, *right, "div", result_register as u8)? + } + _ => todo!("Exponents have a different instruction set. {{ exp r? a(r?|num) }}"), + } + Ok(()) } } diff --git a/tests/file.stlg b/tests/file.stlg index 18f7c8b..6efd478 100644 --- a/tests/file.stlg +++ b/tests/file.stlg @@ -1,12 +1,5 @@ -fn doStuff() { - let i = { - return 234.5; - }; +let i = 234 + 432; - i = 5; +let y = i / 432.54; - // This comment is going to be ignored. - return i; // we returned here -} - -doStuff(); \ No newline at end of file +let z = i / y; \ No newline at end of file