diff --git a/src/asm/assemble_ir.rs b/src/asm/assemble_ir.rs index 4f19a77..fc67444 100644 --- a/src/asm/assemble_ir.rs +++ b/src/asm/assemble_ir.rs @@ -1,7 +1,12 @@ -use crate::asm::{AsmBinaryOperator, AsmFunction, AsmInstruction, AsmOperand, ControlUnit, ControlUnitId, VirtualRegisterId}; -use crate::ir::{IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement}; +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 { @@ -81,7 +86,7 @@ pub fn assemble_ir_function(ir_function: &IrFunction) -> AsmFunction { assemble_ir_statement(statement, &mut context); } - AsmFunction::new(ir_function.name().into(), context.into_control_units()) + AsmFunction::new(ir_function.fqn().into(), context.into_control_units()) } fn assemble_ir_statement(ir_statement: &IrStatement, context: &mut AssemblyContext) { @@ -113,9 +118,6 @@ fn assemble_ir_assign(ir_assign: &IrAssign, context: &mut AssemblyContext) { 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()); @@ -144,6 +146,7 @@ fn ir_literal_to_asm_operand(ir_literal: &IrLiteral) -> AsmOperand { IrLiteral::Boolean(b) => AsmOperand::Boolean(*b), IrLiteral::Float(f) => AsmOperand::Float(*f), IrLiteral::Double(d) => AsmOperand::Double(*d), + IrLiteral::String(s) => AsmOperand::String(s.clone()), } } @@ -159,13 +162,6 @@ fn assemble_ir_call(ir_call: &IrCall, context: &mut AssemblyContext) { 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 { @@ -189,72 +185,60 @@ fn assemble_ir_call(ir_call: &IrCall, context: &mut AssemblyContext) { fqn: ir_call.function_name_owned(), }) } + IrCallType::PlatformStatic => {} + IrCallType::PlatformObject => {} } } 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) + let operand = ir_return.expression().map(|expression| { + match expression { + IrExpression::Variable(ir_variable) => { + let variable_virtual_register_id = context.get_virtual_register(ir_variable.name()); + AsmOperand::VirtualRegister(variable_virtual_register_id) + } + IrExpression::Literal(ir_literal) => ir_literal_to_asm_operand(ir_literal), } - 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) { +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) - } + 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) } + 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::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 + operator, }; - context.current_control_unit_mut().append_instruction(instruction); -} \ No newline at end of file + context + .current_control_unit_mut() + .append_instruction(instruction); +} diff --git a/src/asm/mod.rs b/src/asm/mod.rs index c31b52b..2e62b26 100644 --- a/src/asm/mod.rs +++ b/src/asm/mod.rs @@ -79,8 +79,14 @@ pub enum AsmInstruction { InvokeObject { fqn: Rc, }, + InvokePlatformStatic { + fqn: Rc, + }, + InvokePlatformObject { + fqn: Rc, + }, Return { - operand: AsmOperand, + operand: Option, }, BinaryOperation { destination: VirtualRegisterId, @@ -120,8 +126,18 @@ impl Display for AsmInstruction { AsmInstruction::InvokeObject { fqn } => { write!(f, "invoke_object {}", fqn) } + AsmInstruction::InvokePlatformStatic { fqn } => { + write!(f, "invoke_platform_static {}", fqn) + } + AsmInstruction::InvokePlatformObject { fqn } => { + write!(f, "invoke_platform_object {}", fqn) + } AsmInstruction::Return { operand } => { - write!(f, "return {}", operand) + write!(f, "return")?; + if let Some(operand) = operand { + write!(f, " {}", operand)?; + } + Ok(()) } AsmInstruction::BinaryOperation { destination, @@ -151,7 +167,7 @@ pub enum AsmOperand { Float(f32), Double(f64), Boolean(bool), - Constant { name: Rc }, + String(Rc), VirtualRegister(VirtualRegisterId), } @@ -203,8 +219,8 @@ impl Display for AsmOperand { AsmOperand::Boolean(b) => { write!(f, "{}", b) } - AsmOperand::Constant { name } => { - write!(f, "<{}>", name) + AsmOperand::String(s) => { + write!(f, "{}", s) } AsmOperand::VirtualRegister(id) => { write!(f, "vr{}", id) diff --git a/src/bin/dmc/ir.rs b/src/bin/dmc/ir.rs index 9529587..4cc6d24 100644 --- a/src/bin/dmc/ir.rs +++ b/src/bin/dmc/ir.rs @@ -13,12 +13,9 @@ pub fn compile_to_ir( for compilation_unit in &compilation_units { let cu_irs = lower_compilation_unit(compilation_unit); - let mut out = String::new(); - let mut indent_writer = IndentWriter::new(0, " ", &mut out); for ir in &cu_irs { - ir.pretty_print(&mut indent_writer)?; + println!("{}", ir) } - println!("{}", &out); for ir in &cu_irs { match ir { diff --git a/src/ir/lower_ast.rs b/src/ir/lower_ast.rs index f8e7558..993de63 100644 --- a/src/ir/lower_ast.rs +++ b/src/ir/lower_ast.rs @@ -1,119 +1,138 @@ -use crate::ast::node::{AdditiveExpression, AdditiveOperator, Call, Closure, CompilationUnit, Expression, ExpressionList, ExpressionStatement, Function, FunctionBlockBody, FunctionBody, Identifier, Literal, ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration}; +use crate::ast::node::{ + AdditiveExpression, AdditiveOperator, Call, CompilationUnit, Expression, ExpressionStatement, + Function, FunctionBlockBody, FunctionBody, FunctionEqualsBody, Literal, Module, + ModuleLevelDeclaration, Statement, SuffixExpression, SuffixOperator, VariableDeclaration, +}; use crate::ir::{ - Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrCall, IrCallType, IrConst, IrExpression, - IrFunction, IrKind, IrLiteral, IrPrimitiveKind, IrStatement, IrVariable, -}; -use crate::name_analysis::symbol::{ - ExpressibleSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol, + Ir, IrAssign, IrBinaryOperation, IrBinaryOperator, IrExpression, IrFunction, IrKind, IrLiteral, + IrPrimitiveKind, IrReturn, IrStatement, IrStructKind, IrVariable, }; +use crate::name_analysis::symbol::{ClassSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol}; use std::cell::RefCell; -use std::collections::HashMap; +use std::ops::Deref; use std::rc::Rc; -use crate::ir::IrStatement::BinaryOperation; -pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec { - let mut result: Vec = vec![]; - for declaration in compilation_unit.module_level_declarations() { - result.append(&mut lower_module_level_declaration(declaration)); - } - result +struct CuContext { + irs: Vec, } -fn lower_module_level_declaration(declaration: &ModuleLevelDeclaration) -> Vec { - match declaration { - ModuleLevelDeclaration::Module(module) => { - todo!() - } +impl CuContext { + pub fn new() -> Self { + Self { irs: vec![] } + } + + pub fn push_ir(&mut self, ir: Ir) { + self.irs.push(ir); + } + + pub fn into_irs(self) -> Vec { + self.irs + } +} + +pub fn lower_compilation_unit(compilation_unit: &CompilationUnit) -> Vec { + let mut context = CuContext::new(); + for declaration in compilation_unit.module_level_declarations() { + lower_module_level_declaration(declaration, &mut context); + } + context.into_irs() +} + +fn lower_module_level_declaration( + module_level_declaration: &ModuleLevelDeclaration, + cu_context: &mut CuContext, +) { + match module_level_declaration { + ModuleLevelDeclaration::Module(module) => lower_module(module, cu_context), ModuleLevelDeclaration::Interface(interface) => { todo!() } ModuleLevelDeclaration::Class(class) => { todo!() } - ModuleLevelDeclaration::Function(function) => lower_function(function), + ModuleLevelDeclaration::Function(function) => lower_function(function, cu_context), ModuleLevelDeclaration::PlatformFunction(platform_function) => { todo!() } } } -pub struct LocalsTable { - t_count: usize, - stack_slot_count: usize, - stack_slots: HashMap, +fn lower_module(module: &Module, cu_context: &mut CuContext) { + for declaration in module.declarations() { + lower_module_level_declaration(declaration, cu_context); + } } -impl LocalsTable { - pub fn new() -> Self { +struct FnContext { + t_var_count: usize, + statements: Vec, + return_type: Option, +} + +impl FnContext { + pub fn new(return_type: Option) -> Self { Self { - t_count: 0, - stack_slot_count: 0, - stack_slots: HashMap::new(), + t_var_count: 0, + statements: vec![], + return_type, } } - pub fn next_t_var(&mut self) -> IrVariable { - let t_num = self.t_count; - self.t_count += 1; - let t_name = format!("__t{}", t_num); - let t_var = IrVariable::new(&t_name); - self.register_stack_local(&t_var); + pub fn next_t_var(&mut self) -> String { + let t_var = format!("__t{}", self.t_var_count); + self.t_var_count += 1; t_var } - pub fn register_stack_local(&mut self, ir_variable: &IrVariable) { - let stack_slot = self.stack_slot_count; - self.stack_slot_count += 1; - self.stack_slots.insert(ir_variable.clone(), stack_slot); + pub fn push_statement(&mut self, statement: IrStatement) { + self.statements.push(statement); } - pub fn get_stack_slot(&self, ir_variable: &IrVariable) -> usize { - *self.stack_slots.get(ir_variable).unwrap() + pub fn into_statements(self) -> Vec { + self.statements + } + + pub fn return_type(&self) -> Option<&TypeSymbol> { + self.return_type.as_ref() } } -fn lower_function(function: &Function) -> Vec { +fn lower_function(function: &Function, cu_context: &mut CuContext) { let function_symbol = function.function_symbol().unwrap().borrow(); - let name = function_symbol.fqn_parts_owned().join("::"); - let parameters = lower_parameter_symbols(function_symbol.parameter_symbols()); - let return_type = lower_type_symbol(function_symbol.return_type().unwrap()); + let fqn = function_symbol.fqn_formatted(); + let parameters = parameter_symbols_to_ir_kinds(function_symbol.parameter_symbols()); + let return_type = type_symbol_to_ir_kind(function_symbol.return_type().unwrap()); - let mut locals_table = LocalsTable::new(); - let (statements, consts) = lower_function_body(function.function_body(), &mut locals_table); - - let mut result: Vec = vec![]; - result.push(Ir::Function(Box::new(IrFunction::new( - name, + let mut fn_context = FnContext::new(function_symbol.return_type_owned()); + lower_function_body(function.function_body(), &mut fn_context); + let ir_function = IrFunction::new( + &fqn, + function_symbol.is_public(), parameters, - Box::new(return_type), - statements, - Box::new(locals_table), - )))); - result.append( - &mut consts - .into_iter() - .map(|constant| Ir::Const(Box::new(constant))) - .collect(), + return_type, + fn_context.into_statements(), ); - result + cu_context.push_ir(Ir::Function(ir_function.into())); } -fn lower_parameter_symbols(parameter_symbols: &[Rc>]) -> Vec { +fn parameter_symbols_to_ir_kinds( + parameter_symbols: &[Rc>], +) -> Vec { parameter_symbols .iter() .map(|parameter_symbol_rc| parameter_symbol_rc.borrow()) - .map(|parameter_symbol| lower_type_symbol(parameter_symbol.type_symbol().unwrap())) + .map(|parameter_symbol_ref| { + type_symbol_to_ir_kind(parameter_symbol_ref.type_symbol().unwrap()) + }) .collect() } -fn lower_type_symbol(type_symbol: &TypeSymbol) -> IrKind { +fn type_symbol_to_ir_kind(type_symbol: &TypeSymbol) -> IrKind { match type_symbol { TypeSymbol::Primitive(primitive_type_symbol) => { - lower_primitive_type_symbol(primitive_type_symbol) - } - TypeSymbol::Class(class_type_symbol) => { - todo!() + primitive_type_symbol_to_ir_kind(primitive_type_symbol) } + TypeSymbol::Class(class_symbol) => class_symbol_to_ir_kind(class_symbol.borrow().deref()), TypeSymbol::Interface(interface_type_symbol) => { todo!() } @@ -123,7 +142,7 @@ fn lower_type_symbol(type_symbol: &TypeSymbol) -> IrKind { } } -fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> IrKind { +fn primitive_type_symbol_to_ir_kind(primitive_type_symbol: &PrimitiveTypeSymbol) -> IrKind { IrKind::Primitive(Box::new(match primitive_type_symbol { PrimitiveTypeSymbol::Byte => IrPrimitiveKind::I8, PrimitiveTypeSymbol::Char => IrPrimitiveKind::I8, @@ -134,59 +153,54 @@ fn lower_primitive_type_symbol(primitive_type_symbol: &PrimitiveTypeSymbol) -> I PrimitiveTypeSymbol::Double => IrPrimitiveKind::Double, PrimitiveTypeSymbol::Boolean => IrPrimitiveKind::Boolean, PrimitiveTypeSymbol::String => IrPrimitiveKind::String, - PrimitiveTypeSymbol::TypedArray { inner_type } => { - IrPrimitiveKind::Array(Box::new(lower_type_symbol(inner_type.as_ref().unwrap()))) - } - PrimitiveTypeSymbol::Any => { - todo!() - } + PrimitiveTypeSymbol::TypedArray { inner_type } => IrPrimitiveKind::Array(Box::new( + type_symbol_to_ir_kind(inner_type.as_ref().unwrap()), + )), + PrimitiveTypeSymbol::Any => IrPrimitiveKind::Any, PrimitiveTypeSymbol::Void => IrPrimitiveKind::Void, })) } -fn lower_function_body( - function_body: &FunctionBody, - locals_table: &mut LocalsTable, -) -> (Vec, Vec) { +fn class_symbol_to_ir_kind(class_type_symbol: &ClassSymbol) -> IrKind { + let struct_kind = IrStructKind::new(&class_type_symbol.fqn_formatted()); + IrKind::Struct(struct_kind.into()) +} + +fn lower_function_body(function_body: &FunctionBody, fn_context: &mut FnContext) { match function_body { FunctionBody::FunctionAliasBody(alias_body) => { todo!() } FunctionBody::FunctionEqualsBody(equals_body) => { - todo!() + lower_function_equals_body(equals_body, fn_context); } FunctionBody::FunctionBlockBody(block_body) => { - lower_function_block_body(block_body, locals_table) + lower_function_block_body(block_body, fn_context); } } } -fn lower_function_block_body( - body: &FunctionBlockBody, - locals_table: &mut LocalsTable, -) -> (Vec, Vec) { - let mut statements: Vec = vec![]; - let mut consts: Vec = vec![]; - for statement in body.statements() { - statements.append(&mut lower_statement(statement, &mut consts, locals_table)); - } - (statements, consts) +fn lower_function_equals_body(body: &FunctionEqualsBody, fn_context: &mut FnContext) { + todo!() } -fn lower_statement( - statement: &Statement, - consts_pool: &mut Vec, - locals_table: &mut LocalsTable, -) -> Vec { +fn lower_function_block_body(body: &FunctionBlockBody, fn_context: &mut FnContext) { + let statement_count = body.statements().count(); + for (i, statement) in body.statements().enumerate() { + lower_statement(statement, fn_context, i == statement_count - 1); + } +} + +fn lower_statement(statement: &Statement, fn_context: &mut FnContext, is_last: bool) { match statement { Statement::VariableDeclaration(variable_declaration) => { - lower_variable_declaration(variable_declaration, consts_pool, locals_table) + lower_variable_declaration(variable_declaration, fn_context) } Statement::AssignmentStatement(assignment_statement) => { todo!() } Statement::ExpressionStatement(expression_statement) => { - lower_expression_statement(expression_statement, consts_pool, locals_table) + lower_expression_statement(expression_statement, fn_context, is_last) } Statement::UseStatement(use_statement) => { todo!() @@ -205,465 +219,223 @@ fn lower_statement( fn lower_variable_declaration( variable_declaration: &VariableDeclaration, - consts_pool: &mut Vec, - locals_table: &mut LocalsTable, -) -> Vec { - let mut result: Vec = vec![]; - let expression_t_var = lower_expression( - variable_declaration.expression().unwrap(), - &mut result, - consts_pool, - locals_table, - ); - let target = IrVariable::new(variable_declaration.identifier().name()); - locals_table.register_stack_local(&target); - let assign_stmt = IrAssign::new( - Box::new(target), - Box::new(IrExpression::Variable(Box::new(expression_t_var))), - ); - result.push(IrStatement::Assign(assign_stmt)); - 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, -) -> IrVariable { - match expression { - Expression::Ternary(ternary) => { - todo!() - } - Expression::Or(or) => { - todo!() - } - Expression::And(and) => { - todo!() - } - Expression::Comparison(comparison) => { - todo!() - } - Expression::Shift(shift) => { - todo!() - } - Expression::Additive(additive) => { - lower_additive_expression(additive, target, consts_pool, locals_table) - } - Expression::Multiplicative(multiplicative) => { - todo!() - } - Expression::Prefix(prefix) => { - todo!() - } - Expression::Suffix(suffix) => { - lower_suffix_expression(suffix, target, consts_pool, locals_table) - } - Expression::Literal(literal) => lower_literal(literal, target, consts_pool, locals_table), - Expression::Identifier(identifier_expression) => lower_identifier( - identifier_expression.identifier(), - target, - consts_pool, - locals_table, + fn_context: &mut FnContext, +) { + let initializer = match variable_declaration.expression() { + Expression::Literal(literal) => literal_to_ir_expression(literal), + Expression::Identifier(identifier_expression) => IrExpression::Variable( + IrVariable::new(identifier_expression.identifier().name()).into(), ), Expression::Fqn(fqn) => { + todo!("Fqn as expressions") + } + _ => expression_to_ir_expression(variable_declaration.expression(), fn_context), + }; + + let result_variable = IrVariable::new(variable_declaration.identifier().name()); + let ir_assign = IrAssign::new(result_variable, initializer); + fn_context.push_statement(IrStatement::Assign(ir_assign.into())); +} + +fn literal_to_ir_expression(literal: &Literal) -> IrExpression { + match literal { + Literal::IntLiteral(i) => IrExpression::Literal(IrLiteral::I32(*i).into()), + Literal::LongLiteral(l) => IrExpression::Literal(IrLiteral::I64(*l).into()), + Literal::DoubleLiteral(d) => IrExpression::Literal(IrLiteral::Double(*d).into()), + Literal::SingleQuoteString(s) => { + IrExpression::Literal(IrLiteral::String(Rc::from(s.as_ref())).into()) + } + Literal::DString(d_string) => todo!(), + Literal::BacktickString(backtick_string) => { todo!() } - Expression::Closure(closure) => { + Literal::BooleanLiteral(b) => IrExpression::Literal(IrLiteral::Boolean(*b).into()), + } +} + +fn expression_to_ir_expression( + expression: &Expression, + fn_context: &mut FnContext, +) -> IrExpression { + IrExpression::Variable(expression_into_ir_variable(expression, fn_context).into()) +} + +fn expression_into_ir_variable(expression: &Expression, fn_context: &mut FnContext) -> IrVariable { + match expression { + Expression::Ternary(_) => { todo!() } - Expression::List(list) => { + Expression::Or(_) => { + todo!() + } + Expression::And(_) => { + todo!() + } + Expression::Comparison(_) => { + todo!() + } + Expression::Shift(_) => { + todo!() + } + Expression::Additive(additive_expression) => { + additive_expression_into_ir_variable(additive_expression, fn_context) + } + Expression::Multiplicative(_) => { + todo!() + } + Expression::Prefix(_) => { + todo!() + } + Expression::Suffix(suffix_expression) => { + suffix_expression_into_ir_variable(suffix_expression, fn_context) + } + Expression::Literal(literal) => { + let literal_as_ir_expression = literal_to_ir_expression(literal); + let t_var_name = fn_context.next_t_var(); + let t_var_ir_variable = IrVariable::new(&t_var_name); + let ir_assign = IrAssign::new(t_var_ir_variable.clone(), literal_as_ir_expression); + fn_context.push_statement(IrStatement::Assign(ir_assign.into())); + t_var_ir_variable + } + Expression::Identifier(identifier_expression) => { + IrVariable::new(identifier_expression.identifier().name()) + } + Expression::Fqn(_) => { + todo!("Fqn as expression") + } + Expression::Closure(_) => { + todo!() + } + Expression::List(_) => { todo!() } } } -fn lower_suffix_expression( - suffix_expression: &SuffixExpression, - target: &mut Vec, - consts_pool: &mut Vec, - locals_table: &mut LocalsTable, +fn additive_expression_into_ir_variable( + additive_expression: &AdditiveExpression, + fn_context: &mut FnContext, +) -> IrVariable { + let left = expression_to_ir_expression(additive_expression.left(), fn_context); + let right = expression_to_ir_expression(additive_expression.rhs().expression(), fn_context); + let operator = match additive_expression.rhs().operator() { + AdditiveOperator::Add => IrBinaryOperator::Add, + AdditiveOperator::Subtract => IrBinaryOperator::Subtract, + }; + let result_variable_name = fn_context.next_t_var(); + let result_ir_variable = IrVariable::new(&result_variable_name); + let add_op = IrBinaryOperation::new(result_ir_variable.clone(), left, right, operator); + fn_context.push_statement(IrStatement::BinaryOperation(add_op.into())); + result_ir_variable +} + +fn suffix_expression_into_ir_variable( + suffix_expression: &SuffixExpression, + fn_context: &mut FnContext, ) -> 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()), + let result_variable_name = fn_context.next_t_var(); + let result_ir_variable = IrVariable::new(&result_variable_name); + let plus_plus_op = IrBinaryOperation::new( + result_ir_variable.clone(), + expression_to_ir_expression(suffix_expression.expression(), fn_context), IrExpression::Literal(IrLiteral::I32(1).into()), IrBinaryOperator::Add, ); - target.push(IrStatement::BinaryOperation(operation)); - result_var + fn_context.push_statement(IrStatement::BinaryOperation(plus_plus_op.into())); + result_ir_variable } SuffixOperator::MinusMinus => { - let result_var = locals_table.next_t_var(); - let operation = IrBinaryOperation::new( - result_var.clone(), - IrExpression::Variable(receiver_variable.into()), + let result_variable_name = fn_context.next_t_var(); + let result_ir_variable = IrVariable::new(&result_variable_name); + let plus_plus_op = IrBinaryOperation::new( + result_ir_variable.clone(), + expression_to_ir_expression(suffix_expression.expression(), fn_context), IrExpression::Literal(IrLiteral::I32(1).into()), - IrBinaryOperator::Subtract, + IrBinaryOperator::Subtract, // n.b. ); - target.push(IrStatement::BinaryOperation(operation)); - result_var + fn_context.push_statement(IrStatement::BinaryOperation(plus_plus_op.into())); + result_ir_variable } SuffixOperator::ObjectIndex(object_index) => { + todo!("Object indexing") + } + SuffixOperator::Call(call) => { 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, -) -> IrVariable { - match literal { - Literal::IntLiteral(int_literal) => { - let t_var = locals_table.next_t_var(); - let assign_stmt = IrAssign::new( - Box::new(t_var.clone()), - Box::new(IrExpression::Literal(Box::new(IrLiteral::I32( - *int_literal, - )))), - ); - statements.push(IrStatement::Assign(assign_stmt)); - t_var +fn lower_expression_statement( + expression_statement: &ExpressionStatement, + fn_context: &mut FnContext, + is_last: bool, +) { + let is_void_return = if let Some(return_type_symbol) = fn_context.return_type() { + match return_type_symbol { + TypeSymbol::Primitive(primitive_type_symbol) => match primitive_type_symbol { + PrimitiveTypeSymbol::Void => true, + _ => false, + }, + _ => false, } - Literal::LongLiteral(long_literal) => { + } else { + false + }; + + if is_last && !is_void_return { + let return_statement = IrReturn::new(Some(expression_to_ir_expression( + expression_statement.expression(), + fn_context, + ))); + fn_context.push_statement(IrStatement::Return(return_statement.into())); + } else { + lower_side_effect_expression(expression_statement.expression(), fn_context); + } +} + +fn lower_side_effect_expression(expression: &Expression, fn_context: &mut FnContext) { + match expression { + Expression::Suffix(suffix_expression) => { + lower_side_effect_suffix_expression(suffix_expression, fn_context); + } + _ => { + todo!("Anything other than a suffix expression for side-effects should be eliminated as dead code.") + } + } +} + +fn lower_side_effect_suffix_expression( + suffix_expression: &SuffixExpression, + fn_context: &mut FnContext, +) { + match suffix_expression.operator() { + SuffixOperator::PlusPlus => { todo!() } - Literal::DoubleLiteral(double_literal) => { + SuffixOperator::MinusMinus => { todo!() } - Literal::SingleQuoteString(sq_string) => { + SuffixOperator::ObjectIndex(object_index) => { todo!() } - Literal::DString(d_string) => { - todo!() + SuffixOperator::Call(call) => { + call_to_ir_expression(call, suffix_expression.expression(), fn_context); } - Literal::BacktickString(b_string) => { - todo!() - } - Literal::BooleanLiteral(boolean_literal) => { + SuffixOperator::ObjectProperty(object_property) => { todo!() } } } -fn lower_call( +fn call_to_ir_expression( 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 { + fn_context: &mut FnContext, +) -> IrExpression { 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 deleted file mode 100644 index 3e190db..0000000 --- a/src/ir/lower_ir.rs +++ /dev/null @@ -1,134 +0,0 @@ -use crate::ir::lower_ast::LocalsTable; -use crate::ir::{IrAllocable, IrAllocate, IrAssign, IrCall, IrExpression, IrFunction, IrLiteral, IrReturn, IrStatement}; -use crate::vm::instruction::{Immediate, Instruction, Location}; -use std::ops::Deref; -use std::rc::Rc; - -pub fn lower_ir_function(ir_function: &IrFunction) -> Vec { - let mut instructions: Vec = vec![]; - for statement in ir_function.statements() { - instructions.append(&mut lower_ir_statement( - statement, - ir_function.locals_table(), - )); - } - instructions -} - -fn lower_ir_statement(ir_statement: &IrStatement, locals_table: &LocalsTable) -> Vec { - match ir_statement { - IrStatement::Allocate(allocate) => lower_ir_allocate(allocate), - IrStatement::Call(call) => lower_ir_call(call, locals_table), - IrStatement::Return(ir_return) => lower_return(ir_return, locals_table), - IrStatement::Assign(assign) => { - lower_ir_assign(assign, locals_table) - } - IrStatement::MakeClosure(make_closure) => { - todo!() - } - IrStatement::BinaryOperation(binary_operation) => { - todo!() - } - } -} - -fn lower_ir_allocate(ir_allocate: &IrAllocate) -> Vec { - let allocate_instruction = match ir_allocate.kind_to_alloc() { - IrAllocable::Struct(struct_kind) => Instruction::AllocateObject { - implementation_name: Rc::new(struct_kind.name().to_string()), - destination_register: 0, - }, - IrAllocable::Array(array_kind) => { - todo!() - } - }; - let push_instruction = Instruction::Push { source_register: 0 }; - vec![allocate_instruction, push_instruction] -} - -fn lower_ir_call(ir_call: &IrCall, locals_table: &LocalsTable) -> Vec { - let mut instructions: Vec = vec![]; - // push args - for argument in ir_call.arguments() { - lower_ir_expression(argument, &mut instructions, locals_table); - } - instructions -} - -fn lower_ir_expression( - ir_expression: &IrExpression, - instructions: &mut Vec, - locals_table: &LocalsTable, -) { - match ir_expression { - IrExpression::Variable(variable) => instructions.append(&mut vec![ - Instruction::Copy { - source: Location::FramePointer { - offset: locals_table.get_stack_slot(variable) as isize, - }, - destination: Location::Register(0), - }, - Instruction::Push { source_register: 0 }, - ]), - IrExpression::ConstRef(const_ref) => { - todo!() - } - IrExpression::Literal(literal) => { - let immediate = match literal.deref() { - IrLiteral::I8(v) => Immediate::I8(*v), - IrLiteral::I16(v) => Immediate::I16(*v), - IrLiteral::I32(v) => Immediate::I32(*v), - IrLiteral::I64(v) => Immediate::I64(*v), - IrLiteral::I128(v) => Immediate::I128(*v), - IrLiteral::ISize(v) => Immediate::ISize(*v), - IrLiteral::U8(v) => Immediate::U8(*v), - IrLiteral::U16(v) => Immediate::U16(*v), - IrLiteral::U32(v) => Immediate::U32(*v), - IrLiteral::U64(v) => Immediate::U64(*v), - IrLiteral::U128(v) => Immediate::U128(*v), - IrLiteral::USize(v) => Immediate::USize(*v), - IrLiteral::Boolean(v) => Immediate::Boolean(*v), - IrLiteral::Float(v) => Immediate::Float(*v), - IrLiteral::Double(v) => Immediate::Double(*v), - }; - instructions.append(&mut vec![ - Instruction::MoveImmediate { - destination_register: 0, - immediate, - }, - Instruction::Push { source_register: 0 }, - ]) - } - } -} - -fn lower_return(ir_return: &IrReturn, locals_table: &LocalsTable) -> Vec { - let mut instructions: Vec = vec![]; - lower_ir_expression(ir_return.expression(), &mut instructions, locals_table); - instructions.append(&mut vec![ - Instruction::Pop { - destination_register: Some(0), - }, - Instruction::PopFrame, - Instruction::Push { source_register: 0 }, - Instruction::Return, - ]); - instructions -} - -fn lower_ir_assign(ir_assign: &IrAssign, locals_table: &LocalsTable) -> Vec { - let mut instructions: Vec = vec![]; - lower_ir_expression(ir_assign.rhs(), &mut instructions, locals_table); - instructions.append(&mut vec![ - Instruction::Pop { - destination_register: Some(0), - }, - Instruction::Copy { - source: Location::Register(0), - destination: Location::FramePointer { - offset: locals_table.get_stack_slot(ir_assign.lhs()) as isize, - } - } - ]); - instructions -} \ No newline at end of file diff --git a/src/ir/mod.rs b/src/ir/mod.rs index b915357..3776d04 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -1,72 +1,123 @@ -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; pub enum Ir { Struct(Box), Function(Box), PlatformFunction(Box), - Const(Box), } -impl Ir { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - match self { - Ir::Struct(ir_struct) => ir_struct.pretty_print(writer), - Ir::Function(ir_function) => ir_function.pretty_print(writer), - Ir::PlatformFunction(ir_platform_function) => ir_platform_function.pretty_print(writer), - Ir::Const(ir_const) => ir_const.pretty_print(writer), - } +impl Display for Ir { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!( + f, + "{}\n", + match self { + Ir::Struct(ir_struct) => { + format!("{}", ir_struct) + } + Ir::Function(ir_function) => { + format!("{}", ir_function) + } + Ir::PlatformFunction(ir_platform_function) => { + format!("{}", ir_platform_function) + } + } + ) } } pub struct IrStruct { - name: String, + name: Rc, is_public: bool, members: Vec, } impl IrStruct { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + pub fn new(name: &str, is_public: bool, members: Vec) -> Self { + Self { + name: name.into(), + is_public, + members, + } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn name_owned(&self) -> Rc { + self.name.clone() + } + + pub fn is_public(&self) -> bool { + self.is_public + } + + pub fn members(&self) -> &[IrStructMember] { + &self.members + } +} + +impl Display for IrStruct { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if self.is_public { - writer.writeln(&format!("pub struct {} {{", self.name))?; - } else { - writer.writeln(&format!("struct {} {{", self.name))?; + write!(f, "pub ")?; } - writer.increase_indent(); + writeln!(f, "struct {} {{", self.name)?; for member in &self.members { - member.pretty_print(writer)?; - writer.write("\n")?; + writeln!(f, " {}", member)?; } - writer.decrease_indent(); - writer.writeln("}")?; + writeln!(f, "}}")?; Ok(()) } } pub struct IrStructMember { - name: String, + name: Rc, kind: Box, is_public: bool, is_mut: bool, } impl IrStructMember { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { + pub fn new(name: &str, kind: IrKind, is_public: bool, is_mut: bool) -> Self { + Self { + name: name.into(), + kind: kind.into(), + is_public, + is_mut, + } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn name_owned(&self) -> Rc { + self.name.clone() + } + + pub fn kind(&self) -> &IrKind { + &self.kind + } + + pub fn is_public(&self) -> bool { + self.is_public + } +} + +impl Display for IrStructMember { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if self.is_public { - writer.write("pub ")?; + write!(f, "pub ")?; } if self.is_mut { - writer.write("mut ")?; + write!(f, "mut ")?; } - writer.write(&self.name)?; - writer.write(": ")?; - self.kind.pretty_print(writer)?; - Ok(()) + write!(f, "{}: {}", self.name, self.kind) } } @@ -75,11 +126,15 @@ pub enum IrKind { Struct(Box), } -impl IrKind { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { +impl Display for IrKind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - IrKind::Primitive(primitive) => primitive.pretty_print(writer), - IrKind::Struct(struct_kind) => struct_kind.pretty_print(writer), + IrKind::Primitive(ir_primitive_kind) => { + write!(f, "{}", ir_primitive_kind) + } + IrKind::Struct(ir_struct_kind) => { + write!(f, "{}", ir_struct_kind) + } } } } @@ -103,99 +158,115 @@ pub enum IrPrimitiveKind { Array(Box), String, Closure(Box), - Ref(Box), Any, Void, } -impl IrPrimitiveKind { - fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - match self { - IrPrimitiveKind::I8 => writer.write("i8"), - IrPrimitiveKind::I16 => writer.write("i16"), - IrPrimitiveKind::I32 => writer.write("i32"), - IrPrimitiveKind::I64 => writer.write("i64"), - IrPrimitiveKind::I128 => writer.write("i128"), - IrPrimitiveKind::ISize => writer.write("isize"), - IrPrimitiveKind::U8 => writer.write("u8"), - IrPrimitiveKind::U16 => writer.write("u16"), - IrPrimitiveKind::U32 => writer.write("u32"), - IrPrimitiveKind::U64 => writer.write("u64"), - IrPrimitiveKind::U128 => writer.write("u128"), - IrPrimitiveKind::USize => writer.write("usize"), - IrPrimitiveKind::Float => writer.write("f32"), - IrPrimitiveKind::Double => writer.write("f64"), - IrPrimitiveKind::Boolean => writer.write("boolean"), - IrPrimitiveKind::Array(kind) => { - writer.write("Array<")?; - kind.pretty_print(writer)?; - writer.write(">")?; - Ok(()) - } - IrPrimitiveKind::String => writer.write("String"), - IrPrimitiveKind::Closure(closure_kind) => writer.write("Closure"), - IrPrimitiveKind::Ref(ref_kind) => { - todo!() - } - IrPrimitiveKind::Any => writer.write("Any"), - IrPrimitiveKind::Void => writer.write("Void"), - } +impl Display for IrPrimitiveKind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let s = match self { + IrPrimitiveKind::I8 => "i8", + IrPrimitiveKind::I16 => "i16", + IrPrimitiveKind::I32 => "i32", + IrPrimitiveKind::I64 => "i64", + IrPrimitiveKind::I128 => "i128", + IrPrimitiveKind::ISize => "isize", + IrPrimitiveKind::U8 => "u8", + IrPrimitiveKind::U16 => "u16", + IrPrimitiveKind::U32 => "u32", + IrPrimitiveKind::U64 => "u64", + IrPrimitiveKind::U128 => "u128", + IrPrimitiveKind::USize => "usize", + IrPrimitiveKind::Float => "f32", + IrPrimitiveKind::Double => "f64", + IrPrimitiveKind::Boolean => "Boolean", + IrPrimitiveKind::Array(inner_kind) => &format!("Array<{}>", inner_kind), + IrPrimitiveKind::String => "String", + IrPrimitiveKind::Closure(ir_closure_kind) => &format!("{}", ir_closure_kind), + IrPrimitiveKind::Any => "Any", + IrPrimitiveKind::Void => "Void", + }; + write!(f, "{}", s) } } pub struct IrStructKind { - name: String, + name: Rc, } impl IrStructKind { pub fn new(name: &str) -> Self { - Self { - name: name.to_string(), - } + Self { name: name.into() } } pub fn name(&self) -> &str { &self.name } - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write(&self.name) + pub fn name_owned(&self) -> Rc { + self.name.clone() + } +} + +impl Display for IrStructKind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name) } } pub struct IrClosureKind { - captures_struct_name: String, + captures_struct_name: Rc, parameters: Vec, return_type: Box, } +impl Display for IrClosureKind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Closure |{}| ({}) -> {}", + self.captures_struct_name, + self.parameters + .iter() + .map(|ir_kind| format!("{}", ir_kind)) + .collect::>() + .join(", "), + self.return_type + ) + } +} + pub struct IrFunction { - name: String, + fqn: Rc, + is_public: bool, parameters: Vec, return_type: Box, statements: Vec, - locals_table: Box, } impl IrFunction { pub fn new( - name: String, + fqn: &str, + is_public: bool, parameters: Vec, - return_type: Box, + return_type: IrKind, statements: Vec, - locals_table: Box, ) -> Self { Self { - name, + fqn: fqn.into(), + is_public, parameters, - return_type, + return_type: return_type.into(), statements, - locals_table, } } - pub fn name(&self) -> &str { - &self.name + pub fn fqn(&self) -> &str { + &self.fqn + } + + pub fn fqn_owned(&self) -> Rc { + self.fqn.clone() } pub fn parameters(&self) -> &[IrKind] { @@ -209,76 +280,93 @@ impl IrFunction { pub fn statements(&self) -> &[IrStatement] { &self.statements } +} - pub fn locals_table(&self) -> &LocalsTable { - &self.locals_table - } - - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write("fn ")?; - writer.write(&self.name)?; - writer.write("(")?; - for (i, parameter) in self.parameters.iter().enumerate() { - parameter.pretty_print(writer)?; - if i != self.parameters.len() - 1 { - writer.write(", ")?; - } +impl Display for IrFunction { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if self.is_public { + write!(f, "pub ")?; } - writer.write(") -> ")?; - self.return_type.pretty_print(writer)?; - writer.write(" {\n")?; - writer.increase_indent(); + writeln!( + f, + "fn {}({}) -> {} {{", + self.fqn, + self.parameters + .iter() + .map(|ir_kind| format!("{}", ir_kind)) + .collect::>() + .join(", "), + self.return_type + )?; for statement in &self.statements { - statement.pretty_print(writer)?; + writeln!(f, " {}", statement)?; } - writer.decrease_indent(); - writer.writeln("}") - } -} - -pub struct IrPlatformFunction { - name: String, - parameters: Vec, - return_type: Box, -} - -impl IrPlatformFunction { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write("platform fn ")?; - writer.write(&self.name)?; - writer.write("(")?; - for (i, parameter) in self.parameters.iter().enumerate() { - parameter.pretty_print(writer)?; - if i != self.parameters.len() - 1 { - writer.write(", ")?; - } - } - writer.write(") -> ")?; - self.return_type.pretty_print(writer)?; - writer.write("\n")?; + writeln!(f, "}}")?; Ok(()) } } -pub enum IrStatement { - Allocate(IrAllocate), - Call(IrCall), - Return(IrReturn), - Assign(IrAssign), - MakeClosure(IrMakeClosure), - BinaryOperation(IrBinaryOperation), +pub struct IrPlatformFunction { + fqn: Rc, + is_public: bool, + parameters: Vec, + return_type: Box, } -impl IrStatement { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - match self { - IrStatement::Allocate(allocate) => allocate.pretty_print(writer), - IrStatement::Call(call) => call.pretty_print(writer), - 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), +impl Display for IrPlatformFunction { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if self.is_public { + write!(f, "pub ")?; } + writeln!( + f, + "platform fn {}({}) -> {}", + self.fqn, + self.parameters + .iter() + .map(|ir_kind| format!("{}", ir_kind)) + .collect::>() + .join(", "), + self.return_type + ) + } +} + +pub enum IrStatement { + Allocate(Box), + Call(Box), + Return(Box), + Assign(Box), + MakeClosure(Box), + BinaryOperation(Box), +} + +impl Display for IrStatement { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + IrStatement::Allocate(ir_allocate) => { + format!("{}", ir_allocate) + } + IrStatement::Call(ir_call) => { + format!("{}", ir_call) + } + IrStatement::Return(ir_return) => { + format!("{}", ir_return) + } + IrStatement::Assign(ir_assign) => { + format!("{}", ir_assign) + } + IrStatement::MakeClosure(ir_make_closure) => { + format!("{}", ir_make_closure) + } + IrStatement::BinaryOperation(ir_binary_operation) => { + format!("{}", ir_binary_operation) + } + } + ) } } @@ -287,11 +375,15 @@ pub enum IrAllocable { Array(Box), } -impl IrAllocable { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { +impl Display for IrAllocable { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - IrAllocable::Struct(struct_kind) => struct_kind.pretty_print(writer), - IrAllocable::Array(array_kind) => array_kind.pretty_print(writer), + IrAllocable::Struct(ir_struct_kind) => { + write!(f, "{}(", ir_struct_kind) + } + IrAllocable::Array(ir_array_kind) => { + write!(f, "{}(", ir_array_kind) + } } } } @@ -301,11 +393,15 @@ pub enum IrArrayKind { DynamicSize(Box), } -impl IrArrayKind { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { +impl Display for IrArrayKind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - IrArrayKind::StaticSize(static_array_kind) => static_array_kind.pretty_print(writer), - IrArrayKind::DynamicSize(dynamic_array_kind) => dynamic_array_kind.pretty_print(writer), + IrArrayKind::StaticSize(ir_static_array_kind) => { + write!(f, "{}", ir_static_array_kind) + } + IrArrayKind::DynamicSize(ir_dynamic_array_kind) => { + write!(f, "{}", ir_dynamic_array_kind) + } } } } @@ -315,12 +411,9 @@ pub struct IrStaticArrayKind { size: usize, } -impl IrStaticArrayKind { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write("[")?; - self.inner_kind.pretty_print(writer)?; - writer.write(&format!("; {}]", self.size))?; - Ok(()) +impl Display for IrStaticArrayKind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "Array<{}>[{}]", self.inner_kind, self.size) } } @@ -329,26 +422,33 @@ pub struct IrDynamicArrayKind { size_expr: Box, } -impl IrDynamicArrayKind { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write("[")?; - self.inner_kind.pretty_print(writer)?; - writer.write("; ")?; - self.size_expr.pretty_print(writer)?; - writer.write("]")?; - Ok(()) +impl Display for IrDynamicArrayKind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "Array<{}>", self.inner_kind) } } pub struct IrAllocate { - name: String, + result_variable: Rc, declared_kind: Box, kind_to_alloc: Box, } impl IrAllocate { - pub fn name(&self) -> &str { - &self.name + pub fn new( + result_variable: &str, + declared_kind: IrAllocable, + kind_to_alloc: IrAllocable, + ) -> Self { + Self { + result_variable: result_variable.into(), + declared_kind: declared_kind.into(), + kind_to_alloc: kind_to_alloc.into(), + } + } + + pub fn result_variable(&self) -> &str { + &self.result_variable } pub fn declared_kind(&self) -> &IrAllocable { @@ -358,13 +458,15 @@ impl IrAllocate { pub fn kind_to_alloc(&self) -> &IrAllocable { &self.kind_to_alloc } +} - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write_indented(&format!("let {}: ", self.name))?; - self.declared_kind.pretty_print(writer)?; - writer.write(" = alloc")?; - self.kind_to_alloc.pretty_print(writer)?; - Ok(()) +impl Display for IrAllocate { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}: {} = alloc {}", + self.result_variable, self.declared_kind, self.kind_to_alloc + ) } } @@ -405,16 +507,15 @@ impl IrBinaryOperation { 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(()) +impl Display for IrBinaryOperation { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{} = {} {} {}", + self.destination, self.left, self.operator, self.right + ) } } @@ -448,83 +549,46 @@ impl Display for IrBinaryOperator { } } -pub enum IrConst { - String(IrStringConst), - StringArray(IrStringArrayConst), -} - -impl IrConst { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - todo!() - } -} - -pub struct IrStringConst { - name: String, - value: String, -} - -pub struct IrStringArrayConst { - name: String, - value: Vec, -} - pub enum IrExpression { Variable(Box), - ConstRef(Box), Literal(Box), } -impl IrExpression { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - match self { - IrExpression::Variable(variable) => variable.pretty_print(writer), - IrExpression::ConstRef(const_ref) => const_ref.pretty_print(writer), - IrExpression::Literal(literal) => literal.pretty_print(writer), - } +impl Display for IrExpression { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + IrExpression::Variable(ir_variable) => { + format!("{}", ir_variable) + } + IrExpression::Literal(ir_literal) => { + format!("{}", ir_literal) + } + } + ) } } #[derive(Clone, Hash, Eq, PartialEq)] pub struct IrVariable { - name: String, + name: Rc, } impl IrVariable { pub fn new(name: &str) -> Self { - Self { - name: name.to_string(), - } + Self { name: name.into() } } pub fn name(&self) -> &str { &self.name } - - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write(&self.name) - } } -pub struct IrConstRef { - 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) +impl Display for IrVariable { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name) } } @@ -544,57 +608,63 @@ pub enum IrLiteral { Boolean(bool), Float(f32), Double(f64), + String(Rc), } -impl IrLiteral { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - match self { - IrLiteral::I8(v) => writer.write(&format!("{}", v)), - IrLiteral::I16(v) => writer.write(&format!("{}", v)), - IrLiteral::I32(v) => writer.write(&format!("{}", v)), - IrLiteral::I64(v) => writer.write(&format!("{}", v)), - IrLiteral::I128(v) => writer.write(&format!("{}", v)), - IrLiteral::ISize(v) => writer.write(&format!("{}", v)), - IrLiteral::U8(v) => writer.write(&format!("{}", v)), - IrLiteral::U16(v) => writer.write(&format!("{}", v)), - IrLiteral::U32(v) => writer.write(&format!("{}", v)), - IrLiteral::U64(v) => writer.write(&format!("{}", v)), - IrLiteral::U128(v) => writer.write(&format!("{}", v)), - IrLiteral::USize(v) => writer.write(&format!("{}", v)), - IrLiteral::Boolean(v) => writer.write(&format!("{}", v)), - IrLiteral::Float(v) => writer.write(&format!("{}", v)), - IrLiteral::Double(v) => writer.write(&format!("{}", v)), - } +impl Display for IrLiteral { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + IrLiteral::I8(i) => format!("{}", *i), + IrLiteral::I16(i) => format!("{}", *i), + IrLiteral::I32(i) => format!("{}", *i), + IrLiteral::I64(i) => format!("{}", *i), + IrLiteral::I128(i) => format!("{}", *i), + IrLiteral::ISize(i) => format!("{}", *i), + IrLiteral::U8(u) => format!("{}", *u), + IrLiteral::U16(u) => format!("{}", *u), + IrLiteral::U32(u) => format!("{}", *u), + IrLiteral::U64(u) => format!("{}", *u), + IrLiteral::U128(u) => format!("{}", *u), + IrLiteral::USize(u) => format!("{}", *u), + IrLiteral::Boolean(b) => format!("{}", *b), + IrLiteral::Float(float) => format!("{}", *float), + IrLiteral::Double(double) => format!("{}", *double), + IrLiteral::String(s) => format!("{}", s), + } + ) } } pub struct IrCall { - result_name: String, + result_variable: Option>, declared_type: Box, - fqn: Rc, + function_fqn: Rc, call_type: IrCallType, arguments: Vec, } impl IrCall { pub fn new( - result_name: &str, - declared_type: Box, + result_variable: Option<&str>, + declared_type: IrKind, fqn: &str, call_type: IrCallType, arguments: Vec, ) -> Self { Self { - result_name: result_name.to_string(), - declared_type, - fqn: fqn.into(), + result_variable: result_variable.map(Rc::from), + declared_type: declared_type.into(), + function_fqn: fqn.into(), call_type, arguments, } } - pub fn result_name(&self) -> &str { - &self.result_name + pub fn result_variable(&self) -> Option<&str> { + self.result_variable.as_ref().map(Rc::as_ref) } pub fn declared_type(&self) -> &IrKind { @@ -602,11 +672,11 @@ impl IrCall { } pub fn function_name(&self) -> &str { - &self.fqn + &self.function_fqn } pub fn function_name_owned(&self) -> Rc { - self.fqn.clone() + self.function_fqn.clone() } pub fn call_type(&self) -> &IrCallType { @@ -616,25 +686,51 @@ impl IrCall { pub fn arguments(&self) -> &[IrExpression] { &self.arguments } +} - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write_indented(&format!("{}: ", self.result_name))?; - self.declared_type.pretty_print(writer)?; - writer.write(&format!(" = call {}(", self.fqn))?; - for (i, argument) in self.arguments.iter().enumerate() { - argument.pretty_print(writer)?; - if i != self.arguments.len() - 1 { - writer.write(", ")?; - } +impl Display for IrCall { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if let Some(result_variable) = &self.result_variable { + write!(f, "{}: {} = ", result_variable, self.declared_type)?; } - writer.write(")\n")?; - Ok(()) + write!( + f, + "{} {}({})", + self.call_type, + self.function_fqn, + self.arguments + .iter() + .map(|ir_expression| ir_expression.to_string()) + .collect::>() + .join(", ") + ) } } pub enum IrCallType { Static, Object, + PlatformStatic, + PlatformObject, +} + +impl Display for IrCallType { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + IrCallType::Static => { + write!(f, "call_static") + } + IrCallType::Object => { + write!(f, "call_object") + } + IrCallType::PlatformStatic => { + write!(f, "call_platform_static") + } + IrCallType::PlatformObject => { + write!(f, "call_platform_object") + } + } + } } pub struct IrAssign { @@ -643,8 +739,11 @@ pub struct IrAssign { } impl IrAssign { - pub fn new(lhs: Box, rhs: Box) -> Self { - Self { lhs, rhs } + pub fn new(lhs: IrVariable, rhs: IrExpression) -> Self { + Self { + lhs: lhs.into(), + rhs: rhs.into(), + } } pub fn lhs(&self) -> &IrVariable { @@ -654,34 +753,36 @@ impl IrAssign { pub fn rhs(&self) -> &IrExpression { &self.rhs } +} - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write_indented("")?; - self.lhs.pretty_print(writer)?; - writer.write(" = ")?; - self.rhs.pretty_print(writer)?; - writer.write("\n")?; - Ok(()) +impl Display for IrAssign { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{} = {}", self.lhs, self.rhs) } } pub struct IrReturn { - expression: Box, + expression: Option>, } impl IrReturn { - pub fn new(expression: Box) -> Self { - Self { expression } + pub fn new(expression: Option) -> Self { + Self { + expression: expression.map(Box::new), + } } - pub fn expression(&self) -> &IrExpression { - &self.expression + pub fn expression(&self) -> Option<&IrExpression> { + self.expression.as_ref().map(Box::as_ref) } +} - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { - writer.write_indented("return ")?; - self.expression.pretty_print(writer)?; - writer.write("\n")?; +impl Display for IrReturn { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "return")?; + if let Some(expression) = &self.expression { + write!(f, " {}", expression)?; + } Ok(()) } } @@ -690,13 +791,13 @@ pub struct IrMakeClosure { captures_kind: Option>, parameters: Vec, return_type: Box, - name: String, - fn_name: String, + result_variable: Rc, + function_fqn: Rc, captures_variable: Box, } -impl IrMakeClosure { - pub fn pretty_print(&self, writer: &mut IndentWriter) -> std::fmt::Result { +impl Display for IrMakeClosure { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { todo!() } } diff --git a/src/lib.rs b/src/lib.rs index 2bbb4c9..28c7499 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![feature(new_range_api)] -#![feature(coerce_unsized)] #![feature(unsize)] +#![feature(coerce_unsized)] #![allow(warnings)] extern crate core; diff --git a/src/name_analysis/second_pass.rs b/src/name_analysis/second_pass.rs index bd8210d..989f1ed 100644 --- a/src/name_analysis/second_pass.rs +++ b/src/name_analysis/second_pass.rs @@ -529,9 +529,7 @@ fn na_p2_variable_declaration( } // initializer - if let Some(expression) = variable_declaration.expression_mut() { - na_p2_expression(expression, symbol_table, diagnostics); - } + na_p2_expression(variable_declaration.expression_mut(), symbol_table, diagnostics); } fn na_p2_assignment_statement( diff --git a/src/name_analysis/symbol/class_symbol.rs b/src/name_analysis/symbol/class_symbol.rs index 4a076b2..ea7f50a 100644 --- a/src/name_analysis/symbol/class_symbol.rs +++ b/src/name_analysis/symbol/class_symbol.rs @@ -24,6 +24,10 @@ impl ClassSymbol { } } + pub fn fqn_formatted(&self) -> String { + self.fqn_parts.join("::") + } + pub fn declared_name(&self) -> &str { self.fqn_parts.last().unwrap() } diff --git a/src/name_analysis/symbol/function_symbol.rs b/src/name_analysis/symbol/function_symbol.rs index df7daa2..d1468c3 100644 --- a/src/name_analysis/symbol/function_symbol.rs +++ b/src/name_analysis/symbol/function_symbol.rs @@ -86,6 +86,10 @@ impl FunctionSymbol { pub fn return_type(&self) -> Option<&TypeSymbol> { self.return_type.as_ref() } + + pub fn return_type_owned(&self) -> Option { + self.return_type.clone() + } pub fn set_return_type(&mut self, type_symbol: TypeSymbol) { self.return_type = Some(type_symbol); diff --git a/src/parser/ast.yaml b/src/parser/ast.yaml index 70cbe7f..a3154f3 100644 --- a/src/parser/ast.yaml +++ b/src/parser/ast.yaml @@ -694,9 +694,7 @@ VariableDeclaration: - type_use: member: optional: true - - expression: - member: - optional: true + - expression fields: - variable_symbol: kind: VariableSymbol