From ae4c1af949c7230c07b2a7cc86a2e4031c37f651 Mon Sep 17 00:00:00 2001 From: Cody Date: Sun, 25 Jun 2023 23:23:04 -0500 Subject: [PATCH] getting loopy --- examples/hello.sloth | 17 ++- sloth/src/analysis/mod.rs | 4 +- sloth/src/analysis/setup.rs | 259 ++++++++++++++++++---------------- sloth/src/codegen/mod.rs | 268 ++++++++++++++++++++++++++++++------ sloth/src/main.rs | 10 +- sloth/src/symtable.rs | 16 ++- test.c | 12 +- test.sloth | 7 - 8 files changed, 404 insertions(+), 189 deletions(-) delete mode 100644 test.sloth diff --git a/examples/hello.sloth b/examples/hello.sloth index 5deb0fc..4b99943 100644 --- a/examples/hello.sloth +++ b/examples/hello.sloth @@ -1,13 +1,12 @@ -# foreign fn example(); +foreign fn addz(lhs: Int, rhs: Int) Int; -foreign fn foo() Int; -foreign fn bar(y: Int, z: Int) Float; +fn haiiii() Void {} -fn main() Int { - foo(); - foo(); - foo(); - bar(5, 8 * 3 + foo()); - return 7 + 5; +fn hehehaha() Int { + var x: Int = 0; + while x < 10 { + x = x + 1; + } + return x; } diff --git a/sloth/src/analysis/mod.rs b/sloth/src/analysis/mod.rs index 29f1a91..1c2f0d2 100644 --- a/sloth/src/analysis/mod.rs +++ b/sloth/src/analysis/mod.rs @@ -23,7 +23,9 @@ impl AnalysisError { } pub fn analyze(root: &mut Stmt) -> Result<(), AnalysisError> { - setup::populate_symtable(&root.as_node())?; + let mut populator = setup::Populator::default(); + populator.populate_symtable(&root.as_node())?; + setup::propagate_types_stmt(root)?; check_usage(&root.as_node())?; diff --git a/sloth/src/analysis/setup.rs b/sloth/src/analysis/setup.rs index e690131..ad0bf93 100644 --- a/sloth/src/analysis/setup.rs +++ b/sloth/src/analysis/setup.rs @@ -2,80 +2,107 @@ use super::AnalysisError; use crate::parser::ast::{ AstNode, Expr, ExprKind, Function, FunctionInput, FunctionKind, Literal, Stmt, StmtKind, }; -use crate::symtable::{Symbol, SymbolTable, Type}; - -pub(super) fn populate_symtable(node: &AstNode) -> Result<(), AnalysisError> { - if let AstNode::Stmt(stmt) = node { - let mut table = stmt.symtable.clone(); - - match &stmt.kind { - StmtKind::DefineVariable { - identifier, typ, .. - } => { - // When a variable is defined add it to the symbol table of the current scope. - let symbol = build_value_symbol(&table, typ)?; - table.insert(identifier.to_owned(), symbol); - } - StmtKind::DefineFunction(Function { - identifier, - inputs, - output, - kind, - }) => { - // When a function is defined add the function to the symbol - // table of the current scope, and add the inputs to the child - // (body) scope. - let function_symbol = build_function_symbol(&table, inputs, output.as_deref())?; - table.insert(identifier.to_owned(), function_symbol); - - if let FunctionKind::Normal { body } = kind { - let mut body_table = body.symtable.clone(); - - for input in inputs { - let symbol = build_value_symbol(&body_table, &input.typ)?; - body_table.insert(input.identifier.to_owned(), symbol); +use crate::symtable::{Symbol, SymbolTable, Type, ValueSymbol}; + +#[derive(Default)] +pub struct Populator { + next_id: i32, +} + +impl Populator { + fn reserve_id(&mut self) -> i32 { + let id = self.next_id; + self.next_id += 1; + id + } +} + +impl Populator { + pub(super) fn populate_symtable(&mut self, node: &AstNode) -> Result<(), AnalysisError> { + if let AstNode::Stmt(stmt) = node { + let mut table = stmt.symtable.clone(); + + match &stmt.kind { + StmtKind::DefineVariable { + identifier, typ, .. + } => { + // When a variable is defined add it to the symbol table of the current scope. + let symbol = self.build_value_symbol(&table, typ)?; + table.insert(identifier.to_owned(), symbol); + } + StmtKind::DefineFunction(Function { + identifier, + inputs, + output, + kind, + }) => { + // When a function is defined add the function to the symbol + // table of the current scope, and add the inputs to the child + // (body) scope. + let function_symbol = + self.build_function_symbol(&table, inputs, output.as_deref())?; + table.insert(identifier.to_owned(), function_symbol); + + if let FunctionKind::Normal { body } = kind { + let mut body_table = body.symtable.clone(); + + for input in inputs { + let symbol = self.build_value_symbol(&body_table, &input.typ)?; + body_table.insert(input.identifier.to_owned(), symbol); + } } } + _ => (), } - _ => (), } - } - for child in node.children() { - populate_symtable(&child)?; - } - - Ok(()) -} + for child in node.children() { + self.populate_symtable(&child)?; + } -fn build_value_symbol(table: &SymbolTable, typ: &str) -> Result { - let typ = table - .get_type(typ) - .ok_or(AnalysisError::UnknownIdentifier(0, typ.to_owned()))?; + Ok(()) + } - Ok(Symbol::Value(typ)) -} + fn build_value_symbol( + &mut self, + table: &SymbolTable, + typ: &str, + ) -> Result { + let typ = table + .get_type(typ) + .ok_or(AnalysisError::UnknownIdentifier(0, typ.to_owned()))?; + + Ok(Symbol::Value(ValueSymbol { + typ, + id: self.reserve_id(), + })) + } -fn build_function_symbol( - table: &SymbolTable, - inputs: &[FunctionInput], - output: Option<&str>, -) -> Result { - let inputs = inputs - .iter() - .map(|it| table.get_type(&it.typ)) - .collect::>>() - .ok_or(AnalysisError::UnknownIdentifier(0, "0xOwO".to_owned()))?; - - let output = output - .map(|it| table.get_type(it)) - .unwrap_or(Some(Type::Void)) - .ok_or(AnalysisError::UnknownIdentifier(0, "0xUwU".to_owned()))?; - - Ok(Symbol::Value(Type::Function { - inputs, - output: output.into(), - })) + fn build_function_symbol( + &mut self, + table: &SymbolTable, + inputs: &[FunctionInput], + output: Option<&str>, + ) -> Result { + let inputs = inputs + .iter() + .map(|it| table.get_type(&it.typ)) + .collect::>>() + .ok_or(AnalysisError::UnknownIdentifier(0, "0xOwO".to_owned()))?; + + let output = output + .map(|it| table.get_type(it)) + .unwrap_or(Some(Type::Void)) + .ok_or(AnalysisError::UnknownIdentifier(0, "0xUwU".to_owned()))?; + + Ok(Symbol::Value(ValueSymbol { + typ: Type::Function { + inputs, + output: output.into(), + }, + id: self.reserve_id(), + })) + } } pub(super) fn propagate_types_stmt(node: &mut Stmt) -> Result<(), AnalysisError> { @@ -123,63 +150,61 @@ pub(super) fn propagate_types_stmt(node: &mut Stmt) -> Result<(), AnalysisError> } pub(super) fn propagate_types(node: &mut Expr) -> Result<(), AnalysisError> { - let typ = match &mut node.kind { - ExprKind::Grouping(child) => { - propagate_types(child)?; - child - .typ - .clone() - .ok_or(AnalysisError::Unknown(node.line, "owo choco"))? - } - ExprKind::Literal(lit) => match lit { - Literal::Integer(_) => Type::Integer, - Literal::Float(_) => Type::Float, - Literal::Boolean(_) => Type::Boolean, - _ => todo!(), - }, - ExprKind::Identifier(identifier) => { - let table = node.symtable.clone(); - table - .get_value(identifier) - .ok_or(AnalysisError::UnknownIdentifier( - node.line, - identifier.to_owned(), - ))? - } - ExprKind::BinaryOp { lhs, rhs, .. } => { - // Propagating the types to the children - propagate_types(lhs)?; - propagate_types(rhs)?; - - if lhs.typ != rhs.typ { - return Err(AnalysisError::TypeMismatch(node.line)); + let typ = + match &mut node.kind { + ExprKind::Grouping(child) => { + propagate_types(child)?; + child + .typ + .clone() + .ok_or(AnalysisError::Unknown(node.line, "owo choco"))? } + ExprKind::Literal(lit) => match lit { + Literal::Integer(_) => Type::Integer, + Literal::Float(_) => Type::Float, + Literal::Boolean(_) => Type::Boolean, + _ => todo!(), + }, + ExprKind::Identifier(identifier) => { + let table = node.symtable.clone(); + table.get_value(identifier).map(|it| it.typ).ok_or( + AnalysisError::UnknownIdentifier(node.line, identifier.to_owned()), + )? + } + ExprKind::BinaryOp { lhs, rhs, .. } => { + // Propagating the types to the children + propagate_types(lhs)?; + propagate_types(rhs)?; - lhs.typ - .clone() - .ok_or(AnalysisError::Unknown(node.line, "owo?? choco???"))? - } - ExprKind::UnaryOp { value, .. } => { - propagate_types(value)?; + if lhs.typ != rhs.typ { + return Err(AnalysisError::TypeMismatch(node.line)); + } - value.typ.clone().ok_or(AnalysisError::Unknown( - node.line, - "YOU'RE WRONG... SULFURIC ACID!", - ))? - } - ExprKind::Call { callee, args } => { - propagate_types(callee)?; - for arg in args { - propagate_types(arg)?; + lhs.typ + .clone() + .ok_or(AnalysisError::Unknown(node.line, "owo?? choco???"))? + } + ExprKind::UnaryOp { value, .. } => { + propagate_types(value)?; + + value.typ.clone().ok_or(AnalysisError::Unknown( + node.line, + "YOU'RE WRONG... SULFURIC ACID!", + ))? } + ExprKind::Call { callee, args } => { + propagate_types(callee)?; + for arg in args { + propagate_types(arg)?; + } - let Some(Type::Function { ref output, .. }) = callee.typ else { + let Some(Type::Function { ref output, .. }) = callee.typ else { return Err(AnalysisError::TypeMismatch(node.line)); }; - *output.clone() - } - }; + *output.clone() + } + }; node.typ = Some(typ); @@ -195,8 +220,8 @@ mod tests { #[test] fn haiiiiiuwu() { let mut table = SymbolTable::new(); - table.insert("poggo".to_owned(), Symbol::Value(Type::Integer)); - table.insert("poggu".to_owned(), Symbol::Value(Type::Float)); + // table.insert("poggo".to_owned(), Symbol::Value(Type::Integer)); + // table.insert("poggu".to_owned(), Symbol::Value(Type::Float)); let mut x = Expr::new( 0, diff --git a/sloth/src/codegen/mod.rs b/sloth/src/codegen/mod.rs index fb83c99..81832e9 100644 --- a/sloth/src/codegen/mod.rs +++ b/sloth/src/codegen/mod.rs @@ -1,11 +1,19 @@ +use std::collections::HashMap; use std::io::Write; +use std::path::Path; use inkwell::builder::Builder; use inkwell::context::Context; use inkwell::module::Module; -use inkwell::types::{BasicMetadataTypeEnum, BasicType}; -use inkwell::values::{BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue}; -use itertools::Itertools; +use inkwell::targets::{ + CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine, +}; +use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum}; +use inkwell::values::{ + BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue, PointerValue, +}; +use inkwell::{FloatPredicate, IntPredicate, OptimizationLevel}; +use itertools::{Either, Itertools}; use crate::parser::ast::{ BinaryOp, Expr, ExprKind, Function, FunctionKind, Literal, Stmt, StmtKind, @@ -18,41 +26,141 @@ pub struct Compiler<'ctx> { module: Module<'ctx>, current_func: Option>, + current_func_void: bool, + + references: HashMap>, } impl<'ctx> Compiler<'ctx> { - pub fn codegen(context: &'ctx Context, module: &str, code: &Stmt) { + pub fn new(context: &'ctx Context, module: &str) -> Self { let builder = context.create_builder(); let module = context.create_module(module); - let mut this = Compiler { + Compiler { context, builder, module, current_func: None, - }; + current_func_void: false, + + references: Default::default(), + } + } + pub fn codegen(&mut self, code: &Stmt) { let StmtKind::Block(ref stmts) = &code.kind else { panic!("Code root should be a block"); }; for stmt in stmts { - this.codegen_stmt(stmt); - this.current_func.unwrap().print_to_stderr(); + self.codegen_stmt(stmt); + self.current_func.unwrap().print_to_stderr(); } } + fn codegen_alloca(&mut self, typ: BasicTypeEnum<'ctx>, name: &str) -> PointerValue<'ctx> { + let builder = self.context.create_builder(); + + let entry = self.current_func.unwrap().get_first_basic_block().unwrap(); + + match entry.get_first_instruction() { + Some(first) => builder.position_before(&first), + None => builder.position_at_end(entry), + } + + builder.build_alloca(typ, &format!("alloca {name}")) + } + fn codegen_stmt(&mut self, code: &Stmt) { match &code.kind { StmtKind::Block(stmts) => self.codegen_block(stmts), StmtKind::ExprStmt(expr) => { self.codegen_expr(expr); } + StmtKind::IfStmt { + condition, + if_then, + else_then, + } => { + // Get the current function + let func = self.current_func.unwrap(); + + // Get the condition + let condition = self.codegen_expr(condition).unwrap().into_int_value(); + + // Add the branching logic + let then_bb = self.context.append_basic_block(func, "then"); + let else_bb = self.context.append_basic_block(func, "else"); + let continue_bb = self.context.append_basic_block(func, "continue"); + + self.builder + .build_conditional_branch(condition, then_bb, else_bb); + + // Building the blocks for then + self.builder.position_at_end(then_bb); + self.codegen_stmt(if_then); + self.builder.build_unconditional_branch(continue_bb); + + // Building the blocks for else + self.builder.position_at_end(else_bb); + if let Some(else_then) = else_then { + self.codegen_stmt(else_then); + } + self.builder.build_unconditional_branch(continue_bb); + + // Position the builder at the end of the continue block + self.builder.position_at_end(continue_bb); + } + StmtKind::WhileStmt { condition, body } => { + // Get the current function + let func = self.current_func.unwrap(); + + let loop_bb = self.context.append_basic_block(func, "loop"); + let body_bb = self.context.append_basic_block(func, "loop body"); + let after_bb = self.context.append_basic_block(func, "after loop"); + + self.builder.build_unconditional_branch(loop_bb); + + // Building the blocks for the head of the loop + self.builder.position_at_end(loop_bb); + let condition = self.codegen_expr(condition).unwrap().into_int_value(); + self.builder + .build_conditional_branch(condition, body_bb, after_bb); + + // Building the blocks for the body of the loop + self.builder.position_at_end(body_bb); + self.codegen_stmt(body); + self.builder.build_unconditional_branch(loop_bb); + + // Position the builder at the end of the loop + self.builder.position_at_end(after_bb); + } StmtKind::Return(expr) => { - let res = self.codegen_expr(expr); + let res = self.codegen_expr(expr).unwrap(); self.builder.build_return(Some(&res)); } + StmtKind::DefineVariable { + identifier, value, .. + } => { + let table = code.symtable.clone(); + let symbol = table.get_value(identifier).unwrap(); + + let ptr = self.codegen_alloca(self.type_as_basic_type(symbol.typ), identifier); + let init_value = self.codegen_expr(value).unwrap(); + + self.builder.build_store(ptr, init_value); + self.references.insert(symbol.id, ptr); + } + StmtKind::AssignVariable { identifier, value } => { + let table = code.symtable.clone(); + let symbol = table.get_value(identifier).unwrap(); + + let ptr = self.references.get(&symbol.id).unwrap(); + let init_value = self.codegen_expr(value).unwrap(); + + self.builder.build_store(*ptr, init_value); + } StmtKind::DefineFunction(function) => { let table = code.symtable.clone(); self.codegen_function(table, function.clone()); @@ -61,7 +169,17 @@ impl<'ctx> Compiler<'ctx> { // the block contents if let FunctionKind::Normal { body } = &function.kind { if let StmtKind::Block(body) = &body.kind { + // Make the block containing the code for the function + let func = self.current_func.unwrap(); + let block = self.context.append_basic_block(func, "entrypoint"); + + // Position the builder to be at the block + self.builder.position_at_end(block); self.codegen_block(body); + + if self.current_func_void { + self.builder.build_return(None); + } } }; } @@ -70,6 +188,9 @@ impl<'ctx> Compiler<'ctx> { } fn codegen_function(&mut self, table: SymbolTable, function: Function) -> FunctionValue { + // Clear references to variables + self.references.clear(); + let inputs = function.inputs; let inputs_typ = inputs .iter() @@ -96,59 +217,76 @@ impl<'ctx> Compiler<'ctx> { .add_function(&function.identifier, llvm_function_type, None); self.current_func = Some(llvm_function); + self.current_func_void = matches!(output_typ, Type::Void); llvm_function } fn codegen_block(&mut self, code: &[Stmt]) { - let Some(current_func) = self.current_func else { - panic!("Block codegen requires function"); - }; - - let block = self.context.append_basic_block(current_func, "block"); - - self.builder.position_at_end(block); - for stmt in code { self.codegen_stmt(stmt); } } - fn codegen_expr(&self, code: &Expr) -> BasicValueEnum<'ctx> { - // AnyValue - match &code.kind { + fn codegen_expr(&self, code: &Expr) -> Option> { + Some(match &code.kind { ExprKind::Literal(literal) => self.codegen_value(literal.clone()), - ExprKind::Grouping(inner) => self.codegen_expr(inner), + ExprKind::Grouping(inner) => self.codegen_expr(inner)?, ExprKind::Identifier(ident) => { - // FIXME: Do thsi - todo!() + let table = code.symtable.clone(); + let symbol = table.get_value(ident).unwrap(); + let ptr = self.references.get(&symbol.id).unwrap(); + + self.builder + .build_load(self.type_as_basic_type(symbol.typ.clone()), *ptr, "deref") } ExprKind::BinaryOp { op, lhs, rhs } => match lhs.typ { - Some(Type::Integer) => { - let lhs_gen = self.codegen_expr(lhs).into_int_value(); - let rhs_gen = self.codegen_expr(rhs).into_int_value(); + Some(Type::Integer) | Some(Type::Boolean) => { + use IntPredicate::*; + + let l = self.codegen_expr(lhs).unwrap().into_int_value(); + let r = self.codegen_expr(rhs).unwrap().into_int_value(); match op { - BinaryOp::Add => self.builder.build_int_add(lhs_gen, rhs_gen, "add"), - BinaryOp::Sub => self.builder.build_int_sub(lhs_gen, rhs_gen, "sub"), - BinaryOp::Mul => self.builder.build_int_mul(lhs_gen, rhs_gen, "mul"), - BinaryOp::Div => self.builder.build_int_signed_div(lhs_gen, rhs_gen, "div"), + BinaryOp::Add => self.builder.build_int_add(l, r, "add"), + BinaryOp::Sub => self.builder.build_int_sub(l, r, "sub"), + BinaryOp::Mul => self.builder.build_int_mul(l, r, "mul"), + BinaryOp::Div => self.builder.build_int_signed_div(l, r, "div"), + BinaryOp::Mod => self.builder.build_int_signed_rem(l, r, "mod"), + + BinaryOp::Gt => self.builder.build_int_compare(SGT, l, r, "gt"), + BinaryOp::GtEq => self.builder.build_int_compare(SGE, l, r, ""), + BinaryOp::Lt => self.builder.build_int_compare(SLT, l, r, "lt"), + BinaryOp::LtEq => self.builder.build_int_compare(SLE, l, r, ""), + + BinaryOp::EqEq => self.builder.build_int_compare(EQ, l, r, ""), + BinaryOp::NotEq => self.builder.build_int_compare(NE, l, r, ""), _ => panic!(), } .into() } Some(Type::Float) => { - let lhs_gen = self.codegen_expr(lhs).into_float_value(); - let rhs_gen = self.codegen_expr(rhs).into_float_value(); + use FloatPredicate::*; + + let l = self.codegen_expr(lhs).unwrap().into_float_value(); + let r = self.codegen_expr(rhs).unwrap().into_float_value(); match op { - BinaryOp::Add => self.builder.build_float_add(lhs_gen, rhs_gen, "add"), - BinaryOp::Sub => self.builder.build_float_sub(lhs_gen, rhs_gen, "sub"), - BinaryOp::Mul => self.builder.build_float_mul(lhs_gen, rhs_gen, "mul"), - BinaryOp::Div => self.builder.build_float_div(lhs_gen, rhs_gen, "div"), + BinaryOp::Add => self.builder.build_float_add(l, r, "add").into(), + BinaryOp::Sub => self.builder.build_float_sub(l, r, "sub").into(), + BinaryOp::Mul => self.builder.build_float_mul(l, r, "mul").into(), + BinaryOp::Div => self.builder.build_float_div(l, r, "div").into(), + BinaryOp::Mod => self.builder.build_float_rem(l, r, "mod").into(), + + BinaryOp::Gt => self.builder.build_float_compare(OGT, l, r, "gt").into(), + BinaryOp::GtEq => self.builder.build_float_compare(OGE, l, r, "gt").into(), + BinaryOp::Lt => self.builder.build_float_compare(OLT, l, r, "lt").into(), + BinaryOp::LtEq => self.builder.build_float_compare(OLE, l, r, "le").into(), + + BinaryOp::EqEq => self.builder.build_float_compare(OEQ, l, r, "eq").into(), + BinaryOp::NotEq => self.builder.build_float_compare(ONE, l, r, "ne").into(), _ => panic!(), } - .into() } None => unreachable!("Critical Error: Type should never be null by this point"), _ => todo!(), @@ -164,15 +302,20 @@ impl<'ctx> Compiler<'ctx> { let args = args .iter() .map(|arg| self.codegen_expr(arg)) - .map(|arg| arg.into()) + .map(|arg| arg.unwrap().into()) .collect::>(); - self.builder + let call = self + .builder .build_call(function, &args, "") - .try_as_basic_value() - .unwrap_left() + .try_as_basic_value(); + + match call { + Either::Left(left) => left, + Either::Right(_) => return None, + } } - } + }) } fn codegen_value(&self, value: Literal) -> BasicValueEnum<'ctx> { @@ -187,18 +330,53 @@ impl<'ctx> Compiler<'ctx> { .f64_type() .const_float(value) .as_basic_value_enum(), + Literal::Boolean(value) => self + .context + .bool_type() + .const_int(if value { 1 } else { 0 }, false) + .as_basic_value_enum(), _ => unimplemented!(), } } - fn type_as_metadata_type(&self, typ: Type) -> BasicMetadataTypeEnum<'ctx> { + fn type_as_basic_type(&self, typ: Type) -> BasicTypeEnum<'ctx> { match typ { Type::Integer => self.context.i64_type().into(), Type::Float => self.context.f64_type().into(), Type::Boolean => self.context.bool_type().into(), - _ => todo!(), // Type::Function { inputs, output } => todo!(), + _ => todo!(), } } - fn write_obj(&self, file: &mut impl Write) {} + fn type_as_metadata_type(&self, typ: Type) -> BasicMetadataTypeEnum<'ctx> { + self.type_as_basic_type(typ).into() + } + + pub fn write_obj(&self, file: &mut impl Write, filetype: FileType) { + Target::initialize_native(&InitializationConfig::default()).unwrap(); + + let triple = TargetMachine::get_default_triple(); + let target = Target::from_triple(&triple).unwrap(); + let machine = target + .create_target_machine( + &triple, + "x86-64", + "", + OptimizationLevel::None, + RelocMode::Default, + CodeModel::Default, + ) + .unwrap(); + + self.module.set_triple(&triple); + + let buffer = machine + .write_to_memory_buffer(&self.module, filetype) + .unwrap(); + // machine + // .write_to_file(&self.module, filetype, Path::new("export.o")) + // .unwrap(); + + file.write_all(buffer.as_slice()).unwrap(); + } } diff --git a/sloth/src/main.rs b/sloth/src/main.rs index bdcb4cb..c51b147 100644 --- a/sloth/src/main.rs +++ b/sloth/src/main.rs @@ -14,10 +14,12 @@ pub mod parser; pub mod sloth_std; pub mod symtable; +use std::fs::File; use std::{env, fs}; use codegen::Compiler; use inkwell::context::Context; +use inkwell::targets::FileType; use itertools::Itertools; use lexer::Lexer; use parser::AstParser; @@ -62,7 +64,13 @@ fn main() { // println!("Suces"); let context = Context::create(); - Compiler::codegen(&context, "hi", &ast); + let mut compiler = Compiler::new(&context, "s"); + let mut output_file = File::create("output.o").unwrap(); + + compiler.codegen(&ast); + compiler.write_obj(&mut output_file, FileType::Object); + + // Compiler::codegen(&context, "hi", &ast); // let graph = GraphBuilder::generate(Some(&source), &ast).unwrap(); // println!("{graph}"); diff --git a/sloth/src/symtable.rs b/sloth/src/symtable.rs index b2bb209..8bfd16e 100644 --- a/sloth/src/symtable.rs +++ b/sloth/src/symtable.rs @@ -3,6 +3,8 @@ use std::collections::hash_map::Entry::Vacant; use std::collections::HashMap; use std::rc::Rc; +use inkwell::values::PointerValue; + #[derive(Debug, Default)] struct Scope { parent: Option>, @@ -61,10 +63,10 @@ impl SymbolTable { None } - pub fn get_value(&self, identifier: &str) -> Option { + pub fn get_value(&self, identifier: &str) -> Option { let symbol = self.get(identifier)?; - if let Symbol::Value(ref typ) = *symbol { - return Some(typ.clone()); + if let Symbol::Value(ref symbol) = *symbol { + return Some(symbol.clone()); } None @@ -130,7 +132,13 @@ pub enum Symbol { /// Symbol referencing a compile time type, such as the Int symbol Type(Type), /// Symbol referencing a runtime value, such as the println symbol - Value(Type), + Value(ValueSymbol), +} + +#[derive(Clone, Debug)] +pub struct ValueSymbol { + pub typ: Type, + pub id: i32, } #[derive(Clone, Debug, PartialEq, PartialOrd)] diff --git a/test.c b/test.c index 3a39c44..26925e0 100644 --- a/test.c +++ b/test.c @@ -1,11 +1,13 @@ #include -int add(int, int); -int subtract(int, int); +long long hehehaha(); + +long long addz(long long lhs, long long rhs) { + return lhs + rhs + 1; +} int main() { - int a = add(5, 2); - int b = subtract(3, 8); - printf("%d %d\n", a, b); + long long res = hehehaha(); + printf("%d\n", res); return 0; } diff --git a/test.sloth b/test.sloth deleted file mode 100644 index 8ad1754..0000000 --- a/test.sloth +++ /dev/null @@ -1,7 +0,0 @@ -fn add(x, y) { - return x + y; -} - -fn subtract(x, y) { - return x - y; -}