aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCody <cody@codyq.dev>2023-06-06 21:51:55 -0500
committerCody <cody@codyq.dev>2023-06-06 21:51:55 -0500
commit25c5ccb29a6f2387a04bfb5d50874e00084c15d6 (patch)
tree398674a8a87d78ae6ca94952b911006265f28281
parent9c41dd96cd3652ce9c46307184e8055704655338 (diff)
downloadsloth-25c5ccb29a6f2387a04bfb5d50874e00084c15d6.tar.gz
Misc
-rw-r--r--crates/sloth/src/compiler/mod.rs235
-rw-r--r--crates/sloth/src/compiler/symbol.rs79
-rw-r--r--crates/sloth/src/main.rs19
3 files changed, 137 insertions, 196 deletions
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<String, u32>,
-}
+// 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<String, u32>,
-
- 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<String, u32>,
- stmts: Vec<Stmt>,
- ) -> Chunk {
- let mut me = Self {
- variables,
- objects,
- chunk: Chunk::default(),
- };
+pub struct CompileOrder {
+ code: Vec<Stmt>,
+}
- 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<Stmt>) {
+ let mut queue = Vec::<CompileOrder>::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<Stmt>) -> 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<SymbolTable>,
+}
+
+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<String>, 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<String, Symbol>;
+
+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());
}