From 25c5ccb29a6f2387a04bfb5d50874e00084c15d6 Mon Sep 17 00:00:00 2001 From: Cody Date: Tue, 6 Jun 2023 21:51:55 -0500 Subject: Misc --- crates/sloth/src/compiler/mod.rs | 235 ++++++++---------------------------- crates/sloth/src/compiler/symbol.rs | 79 ++++++++++++ crates/sloth/src/main.rs | 19 ++- 3 files changed, 137 insertions(+), 196 deletions(-) create mode 100644 crates/sloth/src/compiler/symbol.rs diff --git a/crates/sloth/src/compiler/mod.rs b/crates/sloth/src/compiler/mod.rs index bd05d1d..873f1a2 100644 --- a/crates/sloth/src/compiler/mod.rs +++ b/crates/sloth/src/compiler/mod.rs @@ -1,212 +1,75 @@ #![allow(unused)] +pub mod symbol; + use std::collections::HashMap; use sloth_bytecode::Opcode; -use sloth_vm::value::{Function, Object, ObjectType, Primitive}; -use sloth_vm::{Chunk, ObjectMap}; +use self::symbol::{Function, Symbol, SymbolTable, SymbolTableStack, SymbolType}; use crate::parser::ast::{BinaryOp, Expr, Literal, Stmt, UnaryOp}; -#[derive(Default, Clone)] -pub struct CompilerScope { - objects: HashMap, -} +// Modules: +// Symbols (Functions, Constants) +// +// Functions: +// Symbols (Functions, Variables, Constants) -#[derive(Eq, PartialEq)] -pub enum CompilerType { - Program, +pub enum CompilerMode { + Module, Function, } -pub struct Compiler<'a> { - variables: HashMap, - - objects: &'a mut ObjectMap, - chunk: Chunk, +pub struct Compiler { + symbols: SymbolTableStack, + mode: CompilerMode, } -impl<'a> Compiler<'a> { - pub fn compile( - objects: &'a mut ObjectMap, - variables: HashMap, - stmts: Vec, - ) -> Chunk { - let mut me = Self { - variables, - objects, - chunk: Chunk::default(), - }; +pub struct CompileOrder { + code: Vec, +} - for stmt in &stmts { - me.parse_statement(stmt); +impl Compiler { + fn new() -> Self { + Self { + symbols: SymbolTableStack::default(), + mode: CompilerMode::Module, } - - me.chunk - } - - fn push_constant(&mut self, value: Primitive) -> u16 { - let next = self.chunk.constants.len(); - self.chunk.constants.push(value); - next as u16 - } - - #[inline(always)] - fn write_opcode(&mut self, opcode: Opcode) { - self.write_u8(opcode as u8); - } - - #[inline(always)] - fn write_u8(&mut self, value: u8) { - self.chunk.code.push(value); } - #[inline(always)] - fn write_u16(&mut self, value: u16) { - let bytes = ((value >> 8) as u8, value as u8); - - self.write_u8(bytes.0); - self.write_u8(bytes.1); - } -} - -impl<'a> Compiler<'a> { - fn parse_statement(&mut self, stmt: &Stmt) { - match stmt { - Stmt::ExprStmt(expr) => { - self.parse_expression(expr); - } - Stmt::DefineFunction { - ident, - args, - body, - return_type, - } => { - if args.len() > 255 { - panic!("Function can not have more than 255 arguments"); + fn compile(&mut self, code: Vec) { + let mut queue = Vec::::new(); + + for stmt in code { + match stmt { + Stmt::DefineFunction { + ident, + args, + body, + return_type, + } => { + self.symbols.push_symbol(ident, Symbol { + typ: SymbolType::Function(Function { + arity: args.len() as u8, + returns_value: return_type.is_some(), + }), + }); + + todo!() } - let internal = - Compiler::compile(self.objects, self.variables.clone(), body.clone()); - let function = Function { - name: Some(ident.to_owned()), - chunk: internal, - arity: args.len() as u8, - returns_value: return_type.is_some(), - }; - - // Allocate the object as a function - let object = Object::new(ObjectType::Function(function)); - let ptr = self.objects.allocate(object); - - // Store it in variables - // Whenever there is a need to reference it just make a new constant lol - self.variables.insert(ident.to_owned(), ptr as u32); - } - Stmt::DefineVariable { name, value, typ } => { - // Take the expression and put whatever it evaluates to onto the stack - self.parse_expression(value); - // Store that as a variable - } - Stmt::DefineValue { name, value, typ } => todo!(), - Stmt::AssignVariable { name, value } => { - self.parse_expression(value); - - // - } - Stmt::If { - expr, - body, - else_if, - els, - } => todo!(), - Stmt::For { name, iter, body } => todo!(), - Stmt::While { condition, body } => todo!(), - Stmt::Return { value } => { - self.parse_expression(value); - self.write_opcode(Opcode::Return); + _ => panic!("Failed to compile module due to unexpected statement"), } } } -} - -impl<'a> Compiler<'a> { - fn parse_expression(&mut self, expr: &Expr) { - match expr { - Expr::Grouping(e) => self.parse_expression(e), - Expr::BinaryOp { op, lhs, rhs } => { - self.parse_expression(lhs); - self.parse_expression(rhs); - - let opcode = match op { - BinaryOp::Add => Opcode::Add, - BinaryOp::Con => todo!(), - BinaryOp::Sub => Opcode::Sub, - BinaryOp::Mul => Opcode::Mul, - BinaryOp::Pow => todo!(), - BinaryOp::Div => Opcode::Div, - BinaryOp::Mod => todo!(), - BinaryOp::BWSftRight => todo!(), - BinaryOp::BWSftLeft => todo!(), - BinaryOp::BWAnd => todo!(), - BinaryOp::BWOr => todo!(), - BinaryOp::BWXor => todo!(), - BinaryOp::Lt => todo!(), - BinaryOp::Gt => todo!(), - BinaryOp::LtEq => todo!(), - BinaryOp::GtEq => todo!(), - BinaryOp::EqEq => Opcode::Eq, - BinaryOp::NotEq => Opcode::Ne, - BinaryOp::LogAnd => todo!(), - BinaryOp::LogOr => todo!(), - BinaryOp::Range => todo!(), - }; - - self.write_opcode(opcode); - } - Expr::UnaryOp { op, value } => { - self.parse_expression(value); - - let opcode = match op { - UnaryOp::Not => todo!(), - UnaryOp::Neg => todo!(), - UnaryOp::BWComp => todo!(), - }; - - self.write_opcode(opcode); - } - Expr::Call { ident, args } => { - for arg in args.iter().rev() { - self.parse_expression(arg); - } - self.parse_expression(ident); - self.write_opcode(Opcode::Call); - } - Expr::Variable(var) => { - // TODO: THIS IS AWFUL AND I HATE IT - let a = self.variables.get(var).cloned().expect("Uh oh spaghettio"); - - let pos = self.chunk.constants.len(); - self.chunk.constants.push(Primitive::Object(a)); - self.write_opcode(Opcode::Constant); - self.write_u16(pos as u16); - } - Expr::Literal(lit) => { - let pos = self.chunk.constants.len(); - - match lit { - Literal::Integer(i) => self.chunk.constants.push(Primitive::Integer(*i)), - Literal::Float(f) => self.chunk.constants.push(Primitive::Float(*f)), - Literal::Bool(b) => self.chunk.constants.push(Primitive::Bool(*b)), - Literal::String(s) => todo!(), - _ => todo!(), - } - - self.write_opcode(Opcode::Constant); - self.write_u16(pos as u16); - } - Expr::Lambda => todo!(), - } + fn compile_function(&mut self, code: Vec) -> Function { + unimplemented!() } } + +pub fn generate_symbols() -> SymbolTable { + let mut table = SymbolTable::default(); + // + todo!() +} diff --git a/crates/sloth/src/compiler/symbol.rs b/crates/sloth/src/compiler/symbol.rs new file mode 100644 index 0000000..b10918f --- /dev/null +++ b/crates/sloth/src/compiler/symbol.rs @@ -0,0 +1,79 @@ +use std::collections::HashMap; + +pub struct SymbolTableStack { + inner: Vec, +} + +impl SymbolTableStack { + pub fn push_scope(&mut self) { + self.inner.push(SymbolTable::default()); + } + + pub fn pop_scope(&mut self) -> bool { + if self.inner.len() == 1 { + return false; + } + + self.inner.pop(); + true + } + + pub fn get_symbol(&self, identifier: &str) -> Option<&Symbol> { + for table in self.inner.iter().rev() { + if let Some(symbol) = table.get(identifier) { + return Some(symbol); + } + } + + None + } + + pub fn push_symbol(&mut self, identifier: impl Into, symbol: Symbol) { + let table = self + .inner + .last_mut() + .expect("Symbol table stack should always have at least 1 table"); + table.insert(identifier.into(), symbol); + } +} + +impl Default for SymbolTableStack { + fn default() -> Self { + Self { + inner: vec![SymbolTable::default()], + } + } +} + +// x 0x00 +// - x 0x01 +// - y 0x02 +// y 0x01 + +pub type SymbolTable = HashMap; + +pub struct Symbol { + pub typ: SymbolType, +} + +pub enum SymbolType { + Function(Function), + Variable(Variable), + Constant(Constant), +} + +pub struct Function { + pub arity: u8, + pub returns_value: bool, + // TODO: Types +} + +pub struct Variable { + pub idx: u16, + // TODO: Types +} + +pub struct Constant { + pub idx: u16, + // TODO: Types +} diff --git a/crates/sloth/src/main.rs b/crates/sloth/src/main.rs index ef27570..b770684 100644 --- a/crates/sloth/src/main.rs +++ b/crates/sloth/src/main.rs @@ -19,8 +19,6 @@ use parser::AstParser; use sloth_vm::value::Function; use sloth_vm::{ObjectMap, VM}; -use crate::compiler::Compiler; - fn main() { // let args = env::args().collect_vec(); // @@ -65,13 +63,14 @@ fn main() { let tokens = Lexer::new(source).collect_vec(); let ast = AstParser::new(tokens).parse(); let mut object_map = ObjectMap::default(); - let code = Compiler::compile(&mut object_map, HashMap::default(), ast.clone()); - - println!("{ast:?}\n\n"); - println!("{:?}\n\n", code.constants); - println!("{:?}\n\n", code.code); + // let code = Compiler::compile(&mut object_map, HashMap::default(), + // ast.clone()); - let mut vm = VM::new(object_map, Function::root(code)); - vm.run(); - println!("{:?}", vm.stack.peek()); + // println!("{ast:?}\n\n"); + // println!("{:?}\n\n", code.constants); + // println!("{:?}\n\n", code.code); + // + // let mut vm = VM::new(object_map, Function::root(code)); + // vm.run(); + // println!("{:?}", vm.stack.peek()); } -- cgit v1.2.3