diff --git a/examples/hello_42.dm b/examples/hello_42.dm index a427e8a..779a58c 100644 --- a/examples/hello_42.dm +++ b/examples/hello_42.dm @@ -2,4 +2,7 @@ use std::core::println fn main(args: Array) let hello = 42 + let world = hello + 16 + println(hello) + println(world) end \ No newline at end of file diff --git a/src/asm/assemble_ir.rs b/src/asm/assemble_ir.rs new file mode 100644 index 0000000..4f19a77 --- /dev/null +++ b/src/asm/assemble_ir.rs @@ -0,0 +1,260 @@ +use crate::asm::{AsmBinaryOperator, AsmFunction, AsmInstruction, AsmOperand, ControlUnit, ControlUnitId, VirtualRegisterId}; +use crate::ir::{IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement}; +use std::collections::HashMap; +use std::ops::Deref; +use std::rc::Rc; + +struct AssemblyContext { + control_unit_counter: ControlUnitId, + control_units: Vec, + virtual_register_counter: VirtualRegisterId, + virtual_registers: HashMap, VirtualRegisterId>, +} + +impl AssemblyContext { + pub fn new() -> Self { + Self { + control_unit_counter: 0, + control_units: Vec::new(), + virtual_register_counter: 0, + virtual_registers: HashMap::new(), + } + } + + fn next_control_unit_id(&mut self) -> ControlUnitId { + let id = self.control_unit_counter; + self.control_unit_counter += 1; + id + } + + pub fn new_control_unit(&mut self) -> ControlUnitId { + let new_id = self.next_control_unit_id(); + self.control_units.push(ControlUnit::new(new_id)); + new_id + } + + pub fn current_control_unit(&mut self) -> &ControlUnit { + if self.control_units.is_empty() { + self.new_control_unit(); + } + self.control_units.last().unwrap() + } + + pub fn current_control_unit_mut(&mut self) -> &mut ControlUnit { + if self.control_units.is_empty() { + self.new_control_unit(); + } + self.control_units.last_mut().unwrap() + } + + pub fn into_control_units(self) -> Vec { + self.control_units + } + + pub fn get_virtual_register(&self, name: &str) -> VirtualRegisterId { + *self + .virtual_registers + .get(name) + .expect(&format!("Did not set a virtual register for name {}", name)) + } + + pub fn next_virtual_register(&mut self, name: &str) -> VirtualRegisterId { + if self.virtual_registers.contains_key(name) { + panic!( + "Should not already have a virtual register with name {}", + name + ); + } + let virtual_register_id = self.virtual_register_counter; + self.virtual_register_counter += 1; + self.virtual_registers + .insert(name.into(), virtual_register_id); + virtual_register_id + } +} + +pub fn assemble_ir_function(ir_function: &IrFunction) -> AsmFunction { + let mut context = AssemblyContext::new(); + + // body + for statement in ir_function.statements() { + assemble_ir_statement(statement, &mut context); + } + + AsmFunction::new(ir_function.name().into(), context.into_control_units()) +} + +fn assemble_ir_statement(ir_statement: &IrStatement, context: &mut AssemblyContext) { + match ir_statement { + IrStatement::Allocate(_) => { + todo!() + } + IrStatement::Call(ir_call) => { + assemble_ir_call(ir_call, context); + } + IrStatement::Return(ir_return) => { + assemble_ir_return(ir_return, context); + } + IrStatement::Assign(ir_assign) => { + assemble_ir_assign(ir_assign, context); + } + IrStatement::MakeClosure(_) => { + todo!() + } + IrStatement::BinaryOperation(ir_binary_operation) => { + assemble_ir_binary_operation(ir_binary_operation, context) + } + } +} + +fn assemble_ir_assign(ir_assign: &IrAssign, context: &mut AssemblyContext) { + let source_operand = match ir_assign.rhs() { + IrExpression::Variable(ir_variable) => { + let virtual_register_id = context.get_virtual_register(ir_variable.name()); + AsmOperand::VirtualRegister(virtual_register_id) + } + IrExpression::ConstRef(ir_const_ref) => AsmOperand::Constant { + name: ir_const_ref.name_owned(), + }, + IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal), + }; + let destination = context.next_virtual_register(ir_assign.lhs().name()); + context + .current_control_unit_mut() + .append_instruction(AsmInstruction::Move { + source: source_operand, + destination, + }) +} + +fn ir_literal_to_asm_operand(ir_literal: &IrLiteral) -> AsmOperand { + match ir_literal { + IrLiteral::I8(i) => AsmOperand::I8(*i), + IrLiteral::I16(i) => AsmOperand::I16(*i), + IrLiteral::I32(i) => AsmOperand::I32(*i), + IrLiteral::I64(i) => AsmOperand::I64(*i), + IrLiteral::I128(i) => AsmOperand::I128(*i), + IrLiteral::ISize(i) => AsmOperand::ISize(*i), + IrLiteral::U8(u) => AsmOperand::U8(*u), + IrLiteral::U16(u) => AsmOperand::U16(*u), + IrLiteral::U32(u) => AsmOperand::U32(*u), + IrLiteral::U64(u) => AsmOperand::U64(*u), + IrLiteral::U128(u) => AsmOperand::U128(*u), + IrLiteral::USize(u) => AsmOperand::USize(*u), + IrLiteral::Boolean(b) => AsmOperand::Boolean(*b), + IrLiteral::Float(f) => AsmOperand::Float(*f), + IrLiteral::Double(d) => AsmOperand::Double(*d), + } +} + +fn assemble_ir_call(ir_call: &IrCall, context: &mut AssemblyContext) { + // push args + for argument in ir_call.arguments() { + match argument { + IrExpression::Variable(ir_variable) => { + let variable_register_id = context.get_virtual_register(ir_variable.name()); + context + .current_control_unit_mut() + .append_instruction(AsmInstruction::Push { + source: AsmOperand::VirtualRegister(variable_register_id), + }) + } + IrExpression::ConstRef(ir_const_ref) => context + .current_control_unit_mut() + .append_instruction(AsmInstruction::Push { + source: AsmOperand::Constant { + name: ir_const_ref.name_owned(), + }, + }), + IrExpression::Literal(ir_literal) => context + .current_control_unit_mut() + .append_instruction(AsmInstruction::Push { + source: ir_literal_to_asm_operand(ir_literal), + }), + } + } + // issue call + match ir_call.call_type() { + IrCallType::Static => { + context + .current_control_unit_mut() + .append_instruction(AsmInstruction::InvokeStatic { + fqn: ir_call.function_name_owned(), + }); + } + IrCallType::Object => { + context + .current_control_unit_mut() + .append_instruction(AsmInstruction::InvokeObject { + fqn: ir_call.function_name_owned(), + }) + } + } +} + +fn assemble_ir_return(ir_return: &IrReturn, context: &mut AssemblyContext) { + let operand = match ir_return.expression() { + IrExpression::Variable(ir_variable) => { + let variable_virtual_register_id = context.get_virtual_register(ir_variable.name()); + AsmOperand::VirtualRegister(variable_virtual_register_id) + } + IrExpression::ConstRef(ir_const_ref) => AsmOperand::Constant { + name: ir_const_ref.name_owned(), + }, + IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal), + }; + context + .current_control_unit_mut() + .append_instruction(AsmInstruction::Return { operand }); +} + +fn assemble_ir_binary_operation(ir_binary_operation: &IrBinaryOperation, context: &mut AssemblyContext) { + let left = match ir_binary_operation.left() { + IrExpression::Variable(ir_variable) => { + AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name())) + } + IrExpression::ConstRef(ir_const_ref) => { + unreachable!("Cannot assemble binary operation with a lhs IrConstRef") + } + IrExpression::Literal(ir_literal) => { + ir_literal_to_asm_operand(ir_literal) + } + }; + let right = match ir_binary_operation.right() { + IrExpression::Variable(ir_variable) => { + AsmOperand::VirtualRegister(context.get_virtual_register(ir_variable.name())) + }, + IrExpression::ConstRef(ir_const_ref) => { + unreachable!("Cannot assemble binary operation with a rhs IrConstRef") + } + IrExpression::Literal(ir_literal) => { + ir_literal_to_asm_operand(ir_literal) + } + }; + let destination = context.next_virtual_register(ir_binary_operation.destination().name()); + let operator = match ir_binary_operation.operator() { + IrBinaryOperator::Add => { + AsmBinaryOperator::Add + } + IrBinaryOperator::Subtract => { + AsmBinaryOperator::Subtract + } + IrBinaryOperator::Multiply => { + AsmBinaryOperator::Multiply + } + IrBinaryOperator::Divide => { + AsmBinaryOperator::Divide + } + IrBinaryOperator::Exponent => { + todo!() + } + }; + + let instruction = AsmInstruction::BinaryOperation { + destination, + left, + right, + operator + }; + context.current_control_unit_mut().append_instruction(instruction); +} \ No newline at end of file diff --git a/src/asm/mod.rs b/src/asm/mod.rs new file mode 100644 index 0000000..c31b52b --- /dev/null +++ b/src/asm/mod.rs @@ -0,0 +1,240 @@ +pub mod assemble_ir; + +use std::fmt::{Display, Formatter}; +use std::rc::Rc; + +pub type ControlUnitId = usize; + +pub type VirtualRegisterId = u32; + +pub struct AsmFunction { + fqn: Rc, + control_units: Vec, +} + +impl AsmFunction { + pub fn new(fqn: Rc, control_units: Vec) -> Self { + Self { fqn, control_units } + } +} + +impl Display for AsmFunction { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!(f, "fn {}", self.fqn)?; + for control_unit in &self.control_units { + writeln!(f, " #{}:", control_unit.id)?; + for instruction in &control_unit.instructions { + writeln!(f, " {}", instruction)?; + } + } + Ok(()) + } +} + +pub struct ControlUnit { + id: ControlUnitId, + successor_ids: Vec, + instructions: Vec, +} + +impl ControlUnit { + pub fn new(id: ControlUnitId) -> Self { + Self { + id, + successor_ids: vec![], + instructions: vec![], + } + } + + pub fn append_instruction(&mut self, instruction: AsmInstruction) { + self.instructions.push(instruction); + } + + pub fn append_instructions(&mut self, instructions: Vec) { + self.instructions.extend(instructions); + } +} + +pub enum AsmInstruction { + Goto { + control_unit_id: ControlUnitId, + }, + Move { + source: AsmOperand, + destination: VirtualRegisterId, + }, + Push { + source: AsmOperand, + }, + Pop { + destination: VirtualRegisterId, + }, + Allocate { + class_name: Rc, + destination: VirtualRegisterId, + }, + InvokeStatic { + fqn: Rc, + }, + InvokeObject { + fqn: Rc, + }, + Return { + operand: AsmOperand, + }, + BinaryOperation { + destination: VirtualRegisterId, + left: AsmOperand, + right: AsmOperand, + operator: AsmBinaryOperator, + }, +} + +impl Display for AsmInstruction { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + AsmInstruction::Goto { control_unit_id } => { + write!(f, "goto #{}", control_unit_id) + } + AsmInstruction::Move { + source, + destination, + } => { + write!(f, "move vr{}, {}", destination, source) + } + AsmInstruction::Push { source } => { + write!(f, "push {}", source) + } + AsmInstruction::Pop { destination } => { + write!(f, "pop vr{}", destination) + } + AsmInstruction::Allocate { + class_name, + destination, + } => { + write!(f, "allocate r{}, {}", destination, class_name) + } + AsmInstruction::InvokeStatic { fqn } => { + write!(f, "invoke_static {}", fqn) + } + AsmInstruction::InvokeObject { fqn } => { + write!(f, "invoke_object {}", fqn) + } + AsmInstruction::Return { operand } => { + write!(f, "return {}", operand) + } + AsmInstruction::BinaryOperation { + destination, + left, + right, + operator, + } => { + write!(f, "op{} vr{}, {}, {}", operator, destination, left, right) + } + } + } +} + +pub enum AsmOperand { + I8(i8), + I16(i16), + I32(i32), + I64(i64), + I128(i128), + ISize(isize), + U8(u8), + U16(u16), + U32(u32), + U64(u64), + U128(u128), + USize(usize), + Float(f32), + Double(f64), + Boolean(bool), + Constant { name: Rc }, + VirtualRegister(VirtualRegisterId), +} + +impl Display for AsmOperand { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + AsmOperand::I8(i) => { + write!(f, "{}i8", i) + } + AsmOperand::I16(i) => { + write!(f, "{}i16", i) + } + AsmOperand::I32(i) => { + write!(f, "{}i32", i) + } + AsmOperand::I64(i) => { + write!(f, "{}i64", i) + } + AsmOperand::I128(i) => { + write!(f, "{}i128", i) + } + AsmOperand::ISize(i) => { + write!(f, "{}isize", i) + } + AsmOperand::U8(u) => { + write!(f, "{}u8", u) + } + AsmOperand::U16(u) => { + write!(f, "{}u16", u) + } + AsmOperand::U32(u) => { + write!(f, "{}u32", u) + } + AsmOperand::U64(u) => { + write!(f, "{}u64", u) + } + AsmOperand::U128(u) => { + write!(f, "{}u128", u) + } + AsmOperand::USize(u) => { + write!(f, "{}usize", u) + } + AsmOperand::Float(float) => { + write!(f, "{}f32", float) + } + AsmOperand::Double(d) => { + write!(f, "{}f64", d) + } + AsmOperand::Boolean(b) => { + write!(f, "{}", b) + } + AsmOperand::Constant { name } => { + write!(f, "<{}>", name) + } + AsmOperand::VirtualRegister(id) => { + write!(f, "vr{}", id) + } + } + } +} + +pub enum AsmBinaryOperator { + Add, + Subtract, + Multiply, + Divide, +} + +impl Display for AsmBinaryOperator { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + AsmBinaryOperator::Add => { + write!(f, "+") + } + AsmBinaryOperator::Subtract => { + write!(f, "-") + } + AsmBinaryOperator::Multiply => { + write!(f, "*") + } + AsmBinaryOperator::Divide => { + write!(f, "/") + } + } + } +} diff --git a/src/bin/dmc/ir.rs b/src/bin/dmc/ir.rs index bb1055a..9529587 100644 --- a/src/bin/dmc/ir.rs +++ b/src/bin/dmc/ir.rs @@ -1,14 +1,16 @@ -use std::path::PathBuf; -use deimos::ast::node::CompilationUnit; -use deimos::ir::Ir; -use deimos::ir::lower_ast::lower_compilation_unit; -use deimos::ir::lower_ir::lower_ir_function; -use deimos::util::indent_writer::IndentWriter; use crate::name_analysis::name_analysis; +use deimos::asm::assemble_ir::assemble_ir_function; +use deimos::ast::node::CompilationUnit; +use deimos::ir::lower_ast::lower_compilation_unit; +use deimos::ir::Ir; +use deimos::util::indent_writer::IndentWriter; +use std::path::PathBuf; -pub fn compile_to_ir(paths: &[PathBuf]) -> Result, Box> { +pub fn compile_to_ir( + paths: &[PathBuf], +) -> Result, Box> { let compilation_units = name_analysis(&paths)?; - + for compilation_unit in &compilation_units { let cu_irs = lower_compilation_unit(compilation_unit); let mut out = String::new(); @@ -17,17 +19,17 @@ pub fn compile_to_ir(paths: &[PathBuf]) -> Result, Box { - let instructions = lower_ir_function(ir_function); - println!("{:#?}", instructions); + let asm_function = assemble_ir_function(ir_function); + println!("{}", asm_function); } _ => {} } } } - + Ok(compilation_units) -} \ No newline at end of file +} diff --git a/src/ir/lower_ast.rs b/src/ir/lower_ast.rs index 5d3161d..f8e7558 100644 --- a/src/ir/lower_ast.rs +++ b/src/ir/lower_ast.rs @@ -1,15 +1,15 @@ -use crate::ast::node::{ - CompilationUnit, Expression, Function, FunctionBlockBody, FunctionBody, Literal, - ModuleLevelDeclaration, Statement, VariableDeclaration, -}; +use crate::ast::node::{AdditiveExpression, AdditiveOperator, Call, Closure, CompilationUnit, Expression, ExpressionList, ExpressionStatement, Function, FunctionBlockBody, FunctionBody, Identifier, Literal, ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration}; use crate::ir::{ - Ir, IrAssign, IrConst, IrExpression, IrFunction, IrKind, IrLiteral, IrPrimitiveKind, - IrStatement, IrVariable, + Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrConst, IrExpression, + IrFunction, IrKind, IrLiteral, IrPrimitiveKind, IrStatement, IrVariable, +}; +use crate::name_analysis::symbol::{ + ExpressibleSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol, }; -use crate::name_analysis::symbol::{ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol}; use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; +use crate::ir::IrStatement::BinaryOperation; pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec { let mut result: Vec = vec![]; @@ -66,7 +66,7 @@ impl LocalsTable { self.stack_slot_count += 1; self.stack_slots.insert(ir_variable.clone(), stack_slot); } - + pub fn get_stack_slot(&self, ir_variable: &IrVariable) -> usize { *self.stack_slots.get(ir_variable).unwrap() } @@ -146,7 +146,7 @@ fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> I fn lower_function_body( function_body: &FunctionBody, - locals_table: &mut LocalsTable + locals_table: &mut LocalsTable, ) -> (Vec, Vec) { match function_body { FunctionBody::FunctionAliasBody(alias_body) => { @@ -163,7 +163,7 @@ fn lower_function_body( fn lower_function_block_body( body: &FunctionBlockBody, - locals_table: &mut LocalsTable + locals_table: &mut LocalsTable, ) -> (Vec, Vec) { let mut statements: Vec = vec![]; let mut consts: Vec = vec![]; @@ -176,7 +176,7 @@ fn lower_function_block_body( fn lower_statement( statement: &Statement, consts_pool: &mut Vec, - locals_table: &mut LocalsTable + locals_table: &mut LocalsTable, ) -> Vec { match statement { Statement::VariableDeclaration(variable_declaration) => { @@ -186,7 +186,7 @@ fn lower_statement( todo!() } Statement::ExpressionStatement(expression_statement) => { - todo!() + lower_expression_statement(expression_statement, consts_pool, locals_table) } Statement::UseStatement(use_statement) => { todo!() @@ -206,7 +206,7 @@ fn lower_statement( fn lower_variable_declaration( variable_declaration: &VariableDeclaration, consts_pool: &mut Vec, - locals_table: &mut LocalsTable + locals_table: &mut LocalsTable, ) -> Vec { let mut result: Vec = vec![]; let expression_t_var = lower_expression( @@ -225,11 +225,26 @@ fn lower_variable_declaration( result } +fn lower_expression_statement( + expression_statement: &ExpressionStatement, + consts_pool: &mut Vec, + locals_table: &mut LocalsTable, +) -> Vec { + let mut result: Vec = vec![]; + lower_expression( + expression_statement.expression(), + &mut result, + consts_pool, + locals_table, + ); + result +} + fn lower_expression( expression: &Expression, target: &mut Vec, consts_pool: &mut Vec, - locals_table: &mut LocalsTable + locals_table: &mut LocalsTable, ) -> IrVariable { match expression { Expression::Ternary(ternary) => { @@ -248,7 +263,7 @@ fn lower_expression( todo!() } Expression::Additive(additive) => { - todo!() + lower_additive_expression(additive, target, consts_pool, locals_table) } Expression::Multiplicative(multiplicative) => { todo!() @@ -257,12 +272,15 @@ fn lower_expression( todo!() } Expression::Suffix(suffix) => { - todo!() + lower_suffix_expression(suffix, target, consts_pool, locals_table) } Expression::Literal(literal) => lower_literal(literal, target, consts_pool, locals_table), - Expression::Identifier(identifier) => { - todo!() - } + Expression::Identifier(identifier_expression) => lower_identifier( + identifier_expression.identifier(), + target, + consts_pool, + locals_table, + ), Expression::Fqn(fqn) => { todo!() } @@ -275,11 +293,62 @@ fn lower_expression( } } +fn lower_suffix_expression( + suffix_expression: &SuffixExpression, + target: &mut Vec, + consts_pool: &mut Vec, + locals_table: &mut LocalsTable, +) -> IrVariable { + let receiver_variable = lower_expression( + suffix_expression.expression(), + target, + consts_pool, + locals_table, + ); + match suffix_expression.operator() { + SuffixOperator::PlusPlus => { + let result_var = locals_table.next_t_var(); + let operation = IrBinaryOperation::new( + result_var.clone(), + IrExpression::Variable(receiver_variable.into()), + IrExpression::Literal(IrLiteral::I32(1).into()), + IrBinaryOperator::Add, + ); + target.push(IrStatement::BinaryOperation(operation)); + result_var + } + SuffixOperator::MinusMinus => { + let result_var = locals_table.next_t_var(); + let operation = IrBinaryOperation::new( + result_var.clone(), + IrExpression::Variable(receiver_variable.into()), + IrExpression::Literal(IrLiteral::I32(1).into()), + IrBinaryOperator::Subtract, + ); + target.push(IrStatement::BinaryOperation(operation)); + result_var + } + SuffixOperator::ObjectIndex(object_index) => { + todo!() + } + SuffixOperator::Call(call) => lower_call( + call, + suffix_expression.expression(), + target, + consts_pool, + locals_table, + ), + SuffixOperator::ObjectProperty(object_property) => { + todo!() + } + } +} + fn lower_literal( literal: &Literal, statements: &mut Vec, consts_pool: &mut Vec, - locals_table: &mut LocalsTable + locals_table: &mut LocalsTable, ) -> IrVariable { match literal { Literal::IntLiteral(int_literal) => { @@ -313,3 +382,288 @@ fn lower_literal( } } } + +fn lower_call( + call: &Call, + receiver: &Expression, + target: &mut Vec, + consts_pool: &mut Vec, + locals_table: &mut LocalsTable, +) -> IrVariable { + let fqn = match receiver { + Expression::Ternary(_) => { + todo!() + } + Expression::Or(_) => { + todo!() + } + Expression::And(_) => { + todo!() + } + Expression::Comparison(_) => { + todo!() + } + Expression::Shift(_) => { + todo!() + } + Expression::Additive(_) => { + todo!() + } + Expression::Multiplicative(_) => { + todo!() + } + Expression::Prefix(_) => { + todo!() + } + Expression::Suffix(_) => { + todo!() + } + Expression::Literal(_) => { + todo!() + } + Expression::Identifier(identifier_expression) => { + match identifier_expression.expressible_symbol().unwrap() { + ExpressibleSymbol::Class(class_symbol) => { + todo!() + } + ExpressibleSymbol::Function(function_symbol) => { + function_symbol.borrow().fqn_formatted() + } + ExpressibleSymbol::ClassMember(class_member_symbol) => { + todo!() + } + ExpressibleSymbol::Parameter(parameter_symbol) => { + todo!() + } + ExpressibleSymbol::Variable(variable_symbol) => { + todo!() + } + } + } + Expression::Fqn(fqn) => { + todo!() + } + Expression::Closure(_) => { + todo!() + } + Expression::List(_) => { + todo!() + } + }; + let declared_type = match receiver { + Expression::Ternary(_) => { + todo!() + } + Expression::Or(_) => { + todo!() + } + Expression::And(_) => { + todo!() + } + Expression::Comparison(_) => { + todo!() + } + Expression::Shift(_) => { + todo!() + } + Expression::Additive(_) => { + todo!() + } + Expression::Multiplicative(_) => { + todo!() + } + Expression::Prefix(_) => { + todo!() + } + Expression::Suffix(_) => { + todo!() + } + Expression::Literal(_) => { + todo!() + } + Expression::Identifier(identifier_expression) => { + match identifier_expression.expressible_symbol().unwrap() { + ExpressibleSymbol::Class(_) => { + todo!() + } + ExpressibleSymbol::Function(function_symbol) => { + match function_symbol.borrow().return_type().expect(&format!( + "Expected return type for fn {}", + function_symbol.borrow().fqn_formatted() + )) { + TypeSymbol::Primitive(primitive_type_symbol) => match primitive_type_symbol + { + PrimitiveTypeSymbol::Byte => { + IrKind::Primitive(IrPrimitiveKind::I8.into()) + } + PrimitiveTypeSymbol::Char => { + todo!() + } + PrimitiveTypeSymbol::Short => { + IrKind::Primitive(IrPrimitiveKind::I16.into()) + } + PrimitiveTypeSymbol::Int => { + IrKind::Primitive(IrPrimitiveKind::I32.into()) + } + PrimitiveTypeSymbol::Long => { + IrKind::Primitive(IrPrimitiveKind::I64.into()) + } + PrimitiveTypeSymbol::Float => { + IrKind::Primitive(IrPrimitiveKind::Float.into()) + } + PrimitiveTypeSymbol::Double => { + IrKind::Primitive(IrPrimitiveKind::Double.into()) + } + PrimitiveTypeSymbol::Boolean => { + IrKind::Primitive(IrPrimitiveKind::Boolean.into()) + } + PrimitiveTypeSymbol::String => { + IrKind::Primitive(IrPrimitiveKind::String.into()) + } + PrimitiveTypeSymbol::TypedArray { inner_type } => { + todo!() + } + PrimitiveTypeSymbol::Any => { + IrKind::Primitive(IrPrimitiveKind::Any.into()) + } + PrimitiveTypeSymbol::Void => { + IrKind::Primitive(IrPrimitiveKind::Void.into()) + } + }, + TypeSymbol::Class(class_symbol) => { + todo!() + } + TypeSymbol::Interface(interface_symbol) => { + todo!() + } + TypeSymbol::Generic(generic_symbol) => { + todo!() + } + } + } + ExpressibleSymbol::ClassMember(_) => { + todo!() + } + ExpressibleSymbol::Parameter(_) => { + todo!() + } + ExpressibleSymbol::Variable(_) => { + todo!() + } + } + } + Expression::Fqn(_) => { + todo!() + } + Expression::Closure(_) => { + todo!() + } + Expression::List(_) => { + todo!() + } + }; + + let arg_vars = match call { + Call::ParenthesesCall(p_call) => { + let mut arg_vars: Vec = vec![]; + if let Some(expression_list) = p_call.expression_list() { + arg_vars.append(&mut lower_expression_list( + expression_list, + target, + consts_pool, + locals_table, + )); + } + if let Some(closure) = p_call.closure() { + arg_vars.push(lower_closure(closure, target, consts_pool, locals_table)); + } + arg_vars + } + Call::ClosureOnlyCall(c_call) => { + vec![lower_closure( + c_call.closure(), + target, + consts_pool, + locals_table, + )] + } + }; + let arg_expressions = arg_vars + .iter() + .map(|ir_variable| IrExpression::Variable(ir_variable.clone().into())) + .collect::>(); + + let result_var = locals_table.next_t_var(); + let call = IrCall::new( + result_var.name(), + declared_type.into(), + &fqn, + IrCallType::Static, + arg_expressions, + ); + target.push(IrStatement::Call(call)); + result_var +} + +fn lower_expression_list( + expression_list: &ExpressionList, + target: &mut Vec, + consts_pool: &mut Vec, + locals_table: &mut LocalsTable, +) -> Vec { + let mut results: Vec = vec![]; + for expression in expression_list.expressions() { + results.push(lower_expression( + expression, + target, + consts_pool, + locals_table, + )); + } + results +} + +fn lower_closure( + closure: &Closure, + target: &mut Vec, + consts_pool: &mut Vec, + locals_table: &mut LocalsTable, +) -> IrVariable { + todo!() +} + +fn lower_identifier( + identifier: &Identifier, + target: &mut Vec, + consts_pool: &mut Vec, + locals_table: &mut LocalsTable, +) -> IrVariable { + IrVariable::new(identifier.name()) +} + +fn lower_additive_expression( + additive: &AdditiveExpression, + target: &mut Vec, + consts_pool: &mut Vec, + locals_table: &mut LocalsTable, +) -> IrVariable { + let left_var = lower_expression(additive.left(), target, consts_pool, locals_table); + let right_var = lower_expression(additive.rhs().expression(), target, consts_pool, locals_table); + let destination = locals_table.next_t_var(); + let operator = match additive.rhs().operator() { + AdditiveOperator::Add => { + IrBinaryOperator::Add + } + AdditiveOperator::Subtract => { + IrBinaryOperator::Subtract + } + }; + let operation = IrBinaryOperation::new( + destination.clone(), + IrExpression::Variable(left_var.into()), + IrExpression::Variable(right_var.into()), + operator + ); + target.push(IrStatement::BinaryOperation(operation)); + destination +} diff --git a/src/ir/lower_ir.rs b/src/ir/lower_ir.rs index ef61c4f..3e190db 100644 --- a/src/ir/lower_ir.rs +++ b/src/ir/lower_ir.rs @@ -26,6 +26,9 @@ fn lower_ir_statement(ir_statement: &IrStatement, locals_table: &LocalsTable) -> IrStatement::MakeClosure(make_closure) => { todo!() } + IrStatement::BinaryOperation(binary_operation) => { + todo!() + } } } diff --git a/src/ir/mod.rs b/src/ir/mod.rs index 8b874f9..b915357 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -1,5 +1,7 @@ use crate::ir::lower_ast::LocalsTable; use crate::util::indent_writer::IndentWriter; +use std::fmt::{Display, Formatter}; +use std::rc::Rc; pub mod lower_ast; pub mod lower_ir; @@ -102,6 +104,7 @@ pub enum IrPrimitiveKind { String, Closure(Box), Ref(Box), + Any, Void, } @@ -134,6 +137,7 @@ impl IrPrimitiveKind { IrPrimitiveKind::Ref(ref_kind) => { todo!() } + IrPrimitiveKind::Any => writer.write("Any"), IrPrimitiveKind::Void => writer.write("Void"), } } @@ -262,6 +266,7 @@ pub enum IrStatement { Return(IrReturn), Assign(IrAssign), MakeClosure(IrMakeClosure), + BinaryOperation(IrBinaryOperation), } impl IrStatement { @@ -272,6 +277,7 @@ impl IrStatement { IrStatement::Return(ir_return) => ir_return.pretty_print(writer), IrStatement::Assign(assign) => assign.pretty_print(writer), IrStatement::MakeClosure(make_closure) => make_closure.pretty_print(writer), + IrStatement::BinaryOperation(binary_operation) => binary_operation.pretty_print(writer), } } } @@ -362,6 +368,86 @@ impl IrAllocate { } } +pub struct IrBinaryOperation { + destination: Box, + left: Box, + right: Box, + operator: IrBinaryOperator, +} + +impl IrBinaryOperation { + pub fn new( + destination: IrVariable, + left: IrExpression, + right: IrExpression, + operator: IrBinaryOperator, + ) -> Self { + Self { + destination: destination.into(), + left: left.into(), + right: right.into(), + operator, + } + } + + pub fn destination(&self) -> &IrVariable { + &self.destination + } + + pub fn left(&self) -> &IrExpression { + &self.left + } + + pub fn right(&self) -> &IrExpression { + &self.right + } + + pub fn operator(&self) -> &IrBinaryOperator { + &self.operator + } + + pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + writer.write_indented("")?; + self.destination.pretty_print(writer)?; + writer.write(" = ")?; + self.left.pretty_print(writer)?; + writer.write(&format!(" {} ", self.operator))?; + self.right.pretty_print(writer)?; + writer.writeln("")?; + Ok(()) + } +} + +pub enum IrBinaryOperator { + Add, + Subtract, + Multiply, + Divide, + Exponent, +} + +impl Display for IrBinaryOperator { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + IrBinaryOperator::Add => { + write!(f, "+") + } + IrBinaryOperator::Subtract => { + write!(f, "-") + } + IrBinaryOperator::Multiply => { + write!(f, "*") + } + IrBinaryOperator::Divide => { + write!(f, "/") + } + IrBinaryOperator::Exponent => { + write!(f, "^") + } + } + } +} + pub enum IrConst { String(IrStringConst), StringArray(IrStringArrayConst), @@ -421,10 +507,22 @@ impl IrVariable { } pub struct IrConstRef { - name: String, + name: Rc, } impl IrConstRef { + pub fn new(name: Rc) -> Self { + Self { name } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn name_owned(&self) -> Rc { + self.name.clone() + } + pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { writer.write(&self.name) } @@ -473,7 +571,8 @@ impl IrLiteral { pub struct IrCall { result_name: String, declared_type: Box, - function_name: String, + fqn: Rc, + call_type: IrCallType, arguments: Vec, } @@ -481,13 +580,15 @@ impl IrCall { pub fn new( result_name: &str, declared_type: Box, - function_name: &str, + fqn: &str, + call_type: IrCallType, arguments: Vec, ) -> Self { Self { result_name: result_name.to_string(), declared_type, - function_name: function_name.to_string(), + fqn: fqn.into(), + call_type, arguments, } } @@ -501,7 +602,15 @@ impl IrCall { } pub fn function_name(&self) -> &str { - &self.function_name + &self.fqn + } + + pub fn function_name_owned(&self) -> Rc { + self.fqn.clone() + } + + pub fn call_type(&self) -> &IrCallType { + &self.call_type } pub fn arguments(&self) -> &[IrExpression] { @@ -509,9 +618,9 @@ impl IrCall { } pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write_indented(&format!("let {}: ", self.result_name))?; + writer.write_indented(&format!("{}: ", self.result_name))?; self.declared_type.pretty_print(writer)?; - writer.write(&format!(" = call {}(", self.function_name))?; + writer.write(&format!(" = call {}(", self.fqn))?; for (i, argument) in self.arguments.iter().enumerate() { argument.pretty_print(writer)?; if i != self.arguments.len() - 1 { @@ -523,6 +632,11 @@ impl IrCall { } } +pub enum IrCallType { + Static, + Object, +} + pub struct IrAssign { lhs: Box, rhs: Box, @@ -532,11 +646,11 @@ impl IrAssign { pub fn new(lhs: Box, rhs: Box) -> Self { Self { lhs, rhs } } - + pub fn lhs(&self) -> &IrVariable { &self.lhs } - + pub fn rhs(&self) -> &IrExpression { &self.rhs } @@ -560,7 +674,7 @@ impl IrReturn { Self { expression } } - pub fn expression(&self) -> &Box { + pub fn expression(&self) -> &IrExpression { &self.expression } diff --git a/src/lib.rs b/src/lib.rs index f80ffc7..2bbb4c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ #![allow(warnings)] extern crate core; +pub mod asm; pub mod ast; pub mod diagnostic; pub mod ir; diff --git a/src/name_analysis/second_pass.rs b/src/name_analysis/second_pass.rs index 142a656..bd8210d 100644 --- a/src/name_analysis/second_pass.rs +++ b/src/name_analysis/second_pass.rs @@ -629,7 +629,8 @@ fn na_p2_expression( todo!() } Expression::Additive(additive) => { - todo!() + na_p2_expression(additive.left_mut(), symbol_table, diagnostics); + na_p2_expression(additive.rhs_mut().expression_mut(), symbol_table, diagnostics); } Expression::Multiplicative(multiplicative) => { todo!() diff --git a/src/name_analysis/symbol/function_symbol.rs b/src/name_analysis/symbol/function_symbol.rs index 4f44e6c..df7daa2 100644 --- a/src/name_analysis/symbol/function_symbol.rs +++ b/src/name_analysis/symbol/function_symbol.rs @@ -50,6 +50,10 @@ impl FunctionSymbol { return_type, } } + + pub fn fqn_formatted(&self) -> String { + self.fqn_parts.join("::") + } pub fn fqn_parts_owned(&self) -> Vec> { self.fqn_parts.to_vec() diff --git a/src/std_core/mod.rs b/src/std_core/mod.rs index 9f6cedf..63984a6 100644 --- a/src/std_core/mod.rs +++ b/src/std_core/mod.rs @@ -24,7 +24,7 @@ pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), Symbol true, None, &vec![Rc::new(RefCell::new(println_msg_symbol))], - None, + Some(TypeSymbol::Primitive(PrimitiveTypeSymbol::Void)), ); symbol_table.register_function_symbol(println_symbol);