diff --git a/dmc-lib/src/ast/call.rs b/dmc-lib/src/ast/call.rs index 4a452f3..bd3dd86 100644 --- a/dmc-lib/src/ast/call.rs +++ b/dmc-lib/src/ast/call.rs @@ -7,11 +7,8 @@ use crate::source_range::SourceRange; use crate::symbol::Symbol; use crate::symbol::callable_symbol::CallableSymbol; use crate::symbol::expressible_symbol::ExpressibleSymbol; -use crate::symbol::function_symbol::FunctionSymbol; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; -use std::cell::RefCell; -use std::rc::Rc; pub struct Call { callee: Box, @@ -156,12 +153,17 @@ impl Call { self.return_type_info.as_ref().unwrap() } - fn get_callee_symbol(&self) -> Rc> { + fn get_callee_symbol(&self) -> CallableSymbol { match self.callee() { Expression::Identifier(identifier) => { let expressible_symbol = identifier.expressible_symbol(); match expressible_symbol { - ExpressibleSymbol::Function(function_symbol) => function_symbol.clone(), + ExpressibleSymbol::Function(function_symbol) => { + CallableSymbol::Function(function_symbol.clone()) + } + ExpressibleSymbol::Class(class_symbol) => { + CallableSymbol::Class(class_symbol.clone()) + } _ => panic!("Calling things other than functions not yet supported."), } } @@ -181,12 +183,26 @@ impl Call { }) .map(Option::unwrap) .collect(); - let function_symbol = self.get_callee_symbol(); - IrCall::new( - function_symbol.borrow().declared_name_owned(), - arguments, - function_symbol.clone(), - ) + let callable_symbol = self.get_callee_symbol(); + match callable_symbol { + CallableSymbol::Function(function_symbol) => IrCall::new( + function_symbol.borrow().declared_name_owned(), + arguments, + function_symbol.borrow().is_extern(), + ), + CallableSymbol::Class(class_symbol) => { + let constructor_symbol = class_symbol + .borrow() + .constructor_symbol() + .cloned() + .expect("Default constructors not supported yet."); + IrCall::new( + constructor_symbol.borrow().declared_name_owned(), + arguments, + false, + ) + } + } } pub fn source_range(&self) -> &SourceRange { diff --git a/dmc-lib/src/ast/class.rs b/dmc-lib/src/ast/class.rs index e4c17ff..4483ef9 100644 --- a/dmc-lib/src/ast/class.rs +++ b/dmc-lib/src/ast/class.rs @@ -103,10 +103,13 @@ impl Class { } // 5. gather functions + // note: for each function, insert at index 0 a self parameter let functions_diagnostics: Vec = self .functions .iter_mut() - .map(|function| function.gather_declared_names(symbol_table)) + .map(|function| { + function.gather_declared_names(symbol_table, self.class_symbol.as_ref()) + }) .filter_map(Result::err) .flatten() .collect(); @@ -124,13 +127,15 @@ impl Class { pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { self.constructor .as_mut() - .map(|constructor| constructor.check_name_usages(symbol_table)) + .map(|constructor| { + constructor.check_name_usages(symbol_table, self.class_symbol.as_ref()) + }) .transpose()?; let fields_diagnostics: Vec = self .fields .iter_mut() - .map(|field| field.check_name_usages(symbol_table)) + .map(|field| field.check_name_usages(symbol_table, self.class_symbol.as_ref())) .filter_map(Result::err) .flatten() .collect(); @@ -139,13 +144,13 @@ impl Class { } if let Some(constructor) = &mut self.constructor { - constructor.check_name_usages(symbol_table)?; + constructor.check_name_usages(symbol_table, self.class_symbol.as_ref())?; } let functions_diagnostics: Vec = self .functions .iter_mut() - .map(|function| function.check_name_usages(symbol_table)) + .map(|function| function.check_name_usages(symbol_table, self.class_symbol.as_ref())) .filter_map(Result::err) .flatten() .collect(); @@ -253,7 +258,10 @@ impl Class { } for function in &self.functions { - ir_functions.push(function.to_ir(symbol_table)); + ir_functions.push(function.to_ir( + symbol_table, + Some(self.class_symbol.as_ref().unwrap().clone()), + )); } ir_functions @@ -321,9 +329,10 @@ mod tests { let mut ir_functions = compilation_unit.to_ir(&symbol_table); let mut constants_table = ConstantsTable::new(); for ir_function in &mut ir_functions { + println!("{}", ir_function); let (_, stack_size) = ir_function.assign_registers(8); - let vm_function = ir_function.assemble(stack_size, &mut constants_table); - println!("{}", vm_function) + // let vm_function = ir_function.assemble(stack_size, &mut constants_table); + // println!("{}", vm_function) } } } diff --git a/dmc-lib/src/ast/compilation_unit.rs b/dmc-lib/src/ast/compilation_unit.rs index ed30e21..c9cde06 100644 --- a/dmc-lib/src/ast/compilation_unit.rs +++ b/dmc-lib/src/ast/compilation_unit.rs @@ -45,7 +45,7 @@ impl CompilationUnit { let mut diagnostics: Vec = vec![]; self.functions .iter_mut() - .map(|f| f.gather_declared_names(symbol_table)) + .map(|f| f.gather_declared_names(symbol_table, None)) .filter_map(Result::err) .flatten() .for_each(|diagnostic| diagnostics.push(diagnostic)); @@ -78,14 +78,14 @@ impl CompilationUnit { self.functions .iter_mut() - .map(|f| f.check_name_usages(symbol_table)) + .map(|f| f.check_name_usages(symbol_table, None)) .filter_map(Result::err) .flatten() .for_each(|diagnostic| diagnostics.push(diagnostic)); self.extern_functions .iter_mut() - .map(|f| f.check_name_usages(symbol_table)) + .map(|f| f.check_name_usages(symbol_table, None)) .filter_map(Result::err) .flatten() .for_each(|diagnostic| diagnostics.push(diagnostic)); @@ -139,7 +139,7 @@ impl CompilationUnit { let mut functions: Vec = vec![]; self.functions .iter() - .map(|f| f.to_ir(symbol_table)) + .map(|f| f.to_ir(symbol_table, None)) .for_each(|f| functions.push(f)); self.classes .iter() diff --git a/dmc-lib/src/ast/constructor.rs b/dmc-lib/src/ast/constructor.rs index 7daf92c..bb4c5dd 100644 --- a/dmc-lib/src/ast/constructor.rs +++ b/dmc-lib/src/ast/constructor.rs @@ -116,11 +116,15 @@ impl Constructor { } } - pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { + pub fn check_name_usages( + &mut self, + symbol_table: &SymbolTable, + class_context: Option<&Rc>>, + ) -> Result<(), Vec> { let parameters_diagnostics: Vec = self .parameters .iter_mut() - .map(|param| param.check_name_usages(symbol_table)) + .map(|param| param.check_name_usages(symbol_table, class_context)) .filter_map(Result::err) .flatten() .collect(); diff --git a/dmc-lib/src/ast/expression.rs b/dmc-lib/src/ast/expression.rs index 94f0f00..49c2a24 100644 --- a/dmc-lib/src/ast/expression.rs +++ b/dmc-lib/src/ast/expression.rs @@ -149,7 +149,7 @@ impl Expression { } Expression::Identifier(identifier) => { let expressible_symbol = identifier.expressible_symbol(); - Some(expressible_symbol.ir_expression()) + Some(expressible_symbol.ir_expression(builder)) } Expression::Add(additive_expression) => { let ir_add = additive_expression.to_ir(builder, symbol_table); diff --git a/dmc-lib/src/ast/extern_function.rs b/dmc-lib/src/ast/extern_function.rs index 11ce302..6026b0f 100644 --- a/dmc-lib/src/ast/extern_function.rs +++ b/dmc-lib/src/ast/extern_function.rs @@ -2,6 +2,7 @@ use crate::ast::parameter::Parameter; use crate::ast::type_use::TypeUse; use crate::diagnostic::Diagnostic; use crate::source_range::SourceRange; +use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::function_symbol::FunctionSymbol; use crate::symbol_table::{SymbolInsertError, SymbolTable}; use std::cell::RefCell; @@ -104,16 +105,23 @@ impl ExternFunction { } } - pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { + pub fn check_name_usages( + &mut self, + symbol_table: &SymbolTable, + class_context: Option<&Rc>>, + ) -> Result<(), Vec> { let mut diagnostics: Vec = self .parameters .iter_mut() - .map(|parameter| parameter.check_name_usages(symbol_table)) + .map(|parameter| parameter.check_name_usages(symbol_table, class_context)) .filter_map(Result::err) .flatten() .collect(); - match self.return_type.check_name_usages(symbol_table) { + match self + .return_type + .check_name_usages(symbol_table, class_context) + { Ok(_) => {} Err(mut return_type_diagnostics) => { diagnostics.append(&mut return_type_diagnostics); @@ -126,7 +134,7 @@ impl ExternFunction { .as_mut() .unwrap() .borrow_mut() - .set_return_type_info(self.return_type.to_type_info()); + .set_return_type_info(self.return_type.type_info().clone()); Ok(()) } else { diff --git a/dmc-lib/src/ast/field.rs b/dmc-lib/src/ast/field.rs index 357850e..96f9825 100644 --- a/dmc-lib/src/ast/field.rs +++ b/dmc-lib/src/ast/field.rs @@ -2,6 +2,7 @@ use crate::ast::expression::Expression; use crate::ast::type_use::TypeUse; use crate::diagnostic::Diagnostic; use crate::source_range::SourceRange; +use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::field_symbol::FieldSymbol; use crate::symbol_table::{SymbolInsertError, SymbolTable}; use std::cell::RefCell; @@ -95,9 +96,13 @@ impl Field { Ok(()) } - pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { + pub fn check_name_usages( + &mut self, + symbol_table: &SymbolTable, + class_context: Option<&Rc>>, + ) -> Result<(), Vec> { if let Some(type_use) = &mut self.declared_type { - type_use.check_name_usages(symbol_table)?; + type_use.check_name_usages(symbol_table, class_context)?; } // This is going to get hairy, because users might attempt to use a field in an initializer @@ -137,7 +142,7 @@ impl Field { match self.initializer.as_ref() { Some(initializer) => { let initializer_type_info = initializer.type_info(); - let declared_type_info = type_use.to_type_info(); + let declared_type_info = type_use.type_info(); if declared_type_info.is_assignable_from(initializer_type_info) { declared_type_info } else { @@ -156,14 +161,14 @@ impl Field { } None => { // easy: the declared type - type_use.to_type_info() + type_use.type_info() } } } None => { // type is the initializer match self.initializer.as_ref() { - Some(initializer) => initializer.type_info().clone(), + Some(initializer) => initializer.type_info(), None => { // this is an error return Err(vec![Diagnostic::new( @@ -181,7 +186,7 @@ impl Field { .as_mut() .unwrap() .borrow_mut() - .set_type_info(field_type_info); + .set_type_info(field_type_info.clone()); if diagnostics.is_empty() { Ok(()) diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index 94b2ac2..4ba6ee0 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -3,10 +3,16 @@ use crate::ast::parameter::Parameter; use crate::ast::statement::Statement; use crate::ast::type_use::TypeUse; use crate::diagnostic::Diagnostic; +use crate::ir::ir_assign::IrAssign; +use crate::ir::ir_expression::IrExpression; use crate::ir::ir_function::IrFunction; +use crate::ir::ir_operation::IrOperation; use crate::ir::ir_parameter::IrParameter; +use crate::ir::ir_statement::IrStatement; +use crate::ir::ir_variable::IrVariable; use crate::source_range::SourceRange; use crate::symbol::Symbol; +use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::function_symbol::FunctionSymbol; use crate::symbol_table::{SymbolInsertError, SymbolTable}; use crate::type_info::TypeInfo; @@ -55,6 +61,7 @@ impl Function { pub fn gather_declared_names( &mut self, symbol_table: &mut SymbolTable, + class_context: Option<&Rc>>, ) -> Result<(), Vec> { let mut diagnostics = vec![]; @@ -94,6 +101,20 @@ impl Function { // handle parameters symbol_table.push_function_scope(&format!("function_scope({})", self.declared_name)); + + // first, if we are in a class context, insert a "fake" self parameter + if let Some(class_symbol) = class_context { + self.parameters.insert( + 0, + Parameter::new( + "self", + SourceRange::new(0, 0), + TypeUse::new("Self", SourceRange::new(0, 0)), + ), + ); + } + + // now gather all names for the params let mut parameter_symbols = vec![]; for parameter in &mut self.parameters { match parameter.gather_declared_names(symbol_table) { @@ -105,6 +126,8 @@ impl Function { } } } + + // set params on function symbol function_symbol .borrow_mut() .set_parameters(parameter_symbols); @@ -138,7 +161,11 @@ impl Function { } } - pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { + pub fn check_name_usages( + &mut self, + symbol_table: &SymbolTable, + class_context: Option<&Rc>>, + ) -> Result<(), Vec> { let mut diagnostics = vec![]; // parameters @@ -146,7 +173,7 @@ impl Function { &mut self .parameters .iter_mut() - .map(|parameter| parameter.check_name_usages(symbol_table)) + .map(|parameter| parameter.check_name_usages(symbol_table, class_context)) .filter_map(|result| result.err()) .flatten() .collect(), @@ -154,14 +181,14 @@ impl Function { // return type if let Some(type_use) = &mut self.return_type { - match type_use.check_name_usages(symbol_table) { + match type_use.check_name_usages(symbol_table, class_context) { Ok(_) => { // set return type info on function symbol self.function_symbol .as_mut() .unwrap() .borrow_mut() - .set_return_type_info(type_use.to_type_info()); + .set_return_type_info(type_use.type_info().clone()); } Err(mut type_use_diagnostics) => { diagnostics.append(&mut type_use_diagnostics); @@ -237,7 +264,11 @@ impl Function { } } - pub fn to_ir(&self, symbol_table: &SymbolTable) -> IrFunction { + pub fn to_ir( + &self, + symbol_table: &SymbolTable, + class_context: Option>>, + ) -> IrFunction { let mut builder = IrBuilder::new(); // parameters @@ -256,6 +287,26 @@ impl Function { let entry_block_id = builder.new_block(); + // preamble + // if we are a method, we need to put parameter 0 in a register + if let Some(class_symbol) = class_context { + let self_variable = IrVariable::new_vr( + "__self".into(), + entry_block_id, + &TypeInfo::ClassInstance(class_symbol.clone()), + ); + let as_rc = Rc::new(RefCell::new(self_variable)); + let parameter_0 = builder.parameters()[0].clone(); + // put it in the self variable + builder + .current_block_mut() + .add_statement(IrStatement::Assign(IrAssign::new( + as_rc.clone(), + IrOperation::Load(IrExpression::Parameter(parameter_0)), + ))); + builder.set_self_variable(as_rc); + } + let function_symbol = self.function_symbol.as_ref().unwrap().borrow(); let return_type_info = function_symbol.return_type_info(); diff --git a/dmc-lib/src/ast/ir_builder.rs b/dmc-lib/src/ast/ir_builder.rs index da2cfb4..a6483bb 100644 --- a/dmc-lib/src/ast/ir_builder.rs +++ b/dmc-lib/src/ast/ir_builder.rs @@ -1,6 +1,7 @@ use crate::ir::ir_block::IrBlock; use crate::ir::ir_parameter::IrParameter; use crate::ir::ir_statement::IrStatement; +use crate::ir::ir_variable::IrVariable; use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; @@ -11,6 +12,7 @@ pub struct IrBuilder { t_var_counter: usize, blocks: HashMap>>, current_block_builder: Option, + self_variable: Option>>, } impl IrBuilder { @@ -21,6 +23,7 @@ impl IrBuilder { t_var_counter: 0, blocks: HashMap::new(), current_block_builder: None, + self_variable: None, } } @@ -72,6 +75,14 @@ impl IrBuilder { self.t_var_counter += 1; format!("t{}", id) } + + pub fn set_self_variable(&mut self, self_variable: Rc>) { + self.self_variable = Some(self_variable); + } + + pub fn self_variable(&self) -> &Rc> { + self.self_variable.as_ref().unwrap() + } } pub struct IrBlockBuilder { diff --git a/dmc-lib/src/ast/let_statement.rs b/dmc-lib/src/ast/let_statement.rs index 5c2292f..fd8f56f 100644 --- a/dmc-lib/src/ast/let_statement.rs +++ b/dmc-lib/src/ast/let_statement.rs @@ -114,7 +114,7 @@ impl LetStatement { IrOperation::Load(IrExpression::String(string_literal.content().into())) } Expression::Identifier(identifier) => { - IrOperation::Load(identifier.expressible_symbol().ir_expression()) + IrOperation::Load(identifier.expressible_symbol().ir_expression(builder)) } Expression::Add(additive_expression) => { IrOperation::Add(additive_expression.to_ir(builder, symbol_table)) diff --git a/dmc-lib/src/ast/parameter.rs b/dmc-lib/src/ast/parameter.rs index 09cf77c..5a92514 100644 --- a/dmc-lib/src/ast/parameter.rs +++ b/dmc-lib/src/ast/parameter.rs @@ -1,9 +1,9 @@ use crate::ast::type_use::TypeUse; use crate::diagnostic::Diagnostic; use crate::source_range::SourceRange; +use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::parameter_symbol::ParameterSymbol; use crate::symbol_table::{SymbolInsertError, SymbolTable}; -use crate::type_info::TypeInfo; use std::cell::RefCell; use std::rc::Rc; @@ -36,7 +36,6 @@ impl Parameter { let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new( &self.declared_name, self.declared_name_source_range.clone(), - TypeInfo::from_declared_name(self.type_use.declared_name()), // todo: this will blow up if type is a Class )); match insert_result { Ok(parameter_symbol) => { @@ -64,8 +63,21 @@ impl Parameter { Ok(self.parameter_symbol.clone().unwrap()) } - pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { - self.type_use.check_name_usages(symbol_table)?; + pub fn check_name_usages( + &mut self, + symbol_table: &SymbolTable, + class_context: Option<&Rc>>, + ) -> Result<(), Vec> { + // check the type use + self.type_use + .check_name_usages(symbol_table, class_context)?; + + // set type on parameter symbol + self.parameter_symbol + .as_mut() + .unwrap() + .borrow_mut() + .set_type_info(self.type_use.type_info().clone()); Ok(()) } diff --git a/dmc-lib/src/ast/type_use.rs b/dmc-lib/src/ast/type_use.rs index 5588f95..92b77b1 100644 --- a/dmc-lib/src/ast/type_use.rs +++ b/dmc-lib/src/ast/type_use.rs @@ -1,14 +1,16 @@ use crate::diagnostic::Diagnostic; use crate::source_range::SourceRange; -use crate::symbol::type_symbol::{PrimitiveTypeSymbol, TypeSymbol}; +use crate::symbol::class_symbol::ClassSymbol; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; +use std::cell::RefCell; +use std::rc::Rc; pub struct TypeUse { declared_name: String, declared_name_source_range: SourceRange, scope_id: Option, - type_symbol: Option, + type_info: Option, } impl TypeUse { @@ -17,7 +19,7 @@ impl TypeUse { declared_name: declared_name.into(), declared_name_source_range, scope_id: None, - type_symbol: None, + type_info: None, } } @@ -33,16 +35,18 @@ impl TypeUse { Ok(()) } - pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec> { - let maybe_type_symbol = - symbol_table.find_type_symbol(self.scope_id.unwrap(), &self.declared_name); - if let Some(type_symbol) = maybe_type_symbol { - self.type_symbol = Some(type_symbol); - Ok(()) - } else if let Some(primitive_type_symbol) = - PrimitiveTypeSymbol::try_from_declared_name(self.declared_name()) - { - self.type_symbol = Some(TypeSymbol::Primitive(primitive_type_symbol)); + pub fn check_name_usages( + &mut self, + symbol_table: &SymbolTable, + class_context: Option<&Rc>>, + ) -> Result<(), Vec> { + if let Some(type_info) = TypeInfo::from_declared_name( + &self.declared_name, + self.scope_id.unwrap(), + symbol_table, + class_context, + ) { + self.type_info = Some(type_info); Ok(()) } else { Err(vec![ @@ -60,16 +64,7 @@ impl TypeUse { Ok(()) // no-op, for now } - pub fn to_type_info(&self) -> TypeInfo { - match self.type_symbol.as_ref().unwrap() { - TypeSymbol::Class(class_symbol) => TypeInfo::ClassInstance(class_symbol.clone()), - TypeSymbol::Primitive(primitive_type) => match primitive_type { - PrimitiveTypeSymbol::Any => TypeInfo::Any, - PrimitiveTypeSymbol::Int => TypeInfo::Integer, - PrimitiveTypeSymbol::Double => TypeInfo::Double, - PrimitiveTypeSymbol::String => TypeInfo::String, - PrimitiveTypeSymbol::Void => TypeInfo::Void, - }, - } + pub fn type_info(&self) -> &TypeInfo { + self.type_info.as_ref().unwrap() } } diff --git a/dmc-lib/src/ir/ir_block.rs b/dmc-lib/src/ir/ir_block.rs index d177e3b..937cb52 100644 --- a/dmc-lib/src/ir/ir_block.rs +++ b/dmc-lib/src/ir/ir_block.rs @@ -154,7 +154,7 @@ mod tests { .find(|f| f.declared_name() == "main") .unwrap(); - let mut main_ir = main.to_ir(&symbol_table); + let mut main_ir = main.to_ir(&symbol_table, None); let (register_assignments, _) = main_ir.assign_registers(2); assert_eq!(register_assignments.len(), 4); } diff --git a/dmc-lib/src/ir/ir_call.rs b/dmc-lib/src/ir/ir_call.rs index b6a23ba..93710d8 100644 --- a/dmc-lib/src/ir/ir_call.rs +++ b/dmc-lib/src/ir/ir_call.rs @@ -3,10 +3,7 @@ use crate::ir::assemble::{Assemble, InstructionsBuilder}; use crate::ir::ir_expression::IrExpression; use crate::ir::ir_variable::IrVrVariableDescriptor; use crate::ir::register_allocation::{OffsetCounter, VrUser}; -use crate::symbol::Symbol; -use crate::symbol::function_symbol::FunctionSymbol; use dvm_lib::instruction::Instruction; -use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::fmt::{Display, Formatter}; use std::rc::Rc; @@ -14,19 +11,15 @@ use std::rc::Rc; pub struct IrCall { function_name: Rc, arguments: Vec, - function_symbol: Rc>, + is_extern: bool, } impl IrCall { - pub fn new( - function_name: Rc, - arguments: Vec, - function_symbol: Rc>, - ) -> Self { + pub fn new(function_name: Rc, arguments: Vec, is_extern: bool) -> Self { Self { function_name, arguments, - function_symbol, + is_extern, } } } @@ -67,16 +60,15 @@ impl Assemble for IrCall { .iter() .map(|ir_expression| ir_expression.push_operand(constants_table)) .for_each(|push_operand| builder.push(Instruction::Push(push_operand))); - let symbol = self.function_symbol.borrow(); - if symbol.is_extern() { + if self.is_extern { builder.push(Instruction::InvokePlatformStatic( - symbol.declared_name_owned(), - symbol.parameters().len(), + self.function_name.clone(), + self.arguments.len(), )); } else { builder.push(Instruction::InvokeStatic( - symbol.declared_name_owned(), - symbol.parameters().len(), + self.function_name.clone(), + self.arguments.len(), )); } } diff --git a/dmc-lib/src/ir/ir_expression.rs b/dmc-lib/src/ir/ir_expression.rs index ab87b95..3da22f2 100644 --- a/dmc-lib/src/ir/ir_expression.rs +++ b/dmc-lib/src/ir/ir_expression.rs @@ -1,4 +1,5 @@ use crate::constants_table::ConstantsTable; +use crate::ir::assemble::InstructionsBuilder; use crate::ir::ir_parameter::IrParameter; use crate::ir::ir_variable::{ IrStackVariableDescriptor, IrVariable, IrVariableDescriptor, IrVrVariableDescriptor, @@ -179,7 +180,7 @@ impl IrExpression { pub fn return_operand(&self, constants_table: &mut ConstantsTable) -> ReturnOperand { match self { - IrExpression::Field(self_variable, _) => { + IrExpression::Field(self_variable, field_index) => { todo!() } IrExpression::Parameter(ir_parameter) => { diff --git a/dmc-lib/src/ir/ir_return.rs b/dmc-lib/src/ir/ir_return.rs index 907602f..f2faca2 100644 --- a/dmc-lib/src/ir/ir_return.rs +++ b/dmc-lib/src/ir/ir_return.rs @@ -53,9 +53,8 @@ impl VrUser for IrReturn { impl Assemble for IrReturn { fn assemble(&self, builder: &mut InstructionsBuilder, constants_table: &mut ConstantsTable) { if let Some(ir_expression) = self.value.as_ref() { - builder.push(Instruction::SetReturnValue( - ir_expression.return_operand(constants_table), - )); + let return_operand = ir_expression.return_operand(constants_table); + builder.push(Instruction::SetReturnValue(return_operand)); } builder.push(Instruction::Return); } diff --git a/dmc-lib/src/symbol/callable_symbol.rs b/dmc-lib/src/symbol/callable_symbol.rs index 458af71..9fa0bfd 100644 --- a/dmc-lib/src/symbol/callable_symbol.rs +++ b/dmc-lib/src/symbol/callable_symbol.rs @@ -14,10 +14,7 @@ impl CallableSymbol { pub fn return_type_info(&self) -> TypeInfo { match self { CallableSymbol::Function(function) => function.borrow().return_type_info().clone(), - CallableSymbol::Class(class_symbol) => { - // At the language level, constructors "return" an instance of their type - TypeInfo::ClassInstance(class_symbol.clone()) - } + CallableSymbol::Class(class_symbol) => TypeInfo::ClassInstance(class_symbol.clone()), } } diff --git a/dmc-lib/src/symbol/expressible_symbol.rs b/dmc-lib/src/symbol/expressible_symbol.rs index fb90f06..46e9302 100644 --- a/dmc-lib/src/symbol/expressible_symbol.rs +++ b/dmc-lib/src/symbol/expressible_symbol.rs @@ -1,3 +1,4 @@ +use crate::ast::ir_builder::IrBuilder; use crate::ir::ir_expression::IrExpression; use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::field_symbol::FieldSymbol; @@ -33,16 +34,15 @@ impl ExpressibleSymbol { } } - pub fn ir_expression(&self) -> IrExpression { + pub fn ir_expression(&self, builder: &mut IrBuilder) -> IrExpression { match self { ExpressibleSymbol::Class(class_symbol) => { todo!() } - ExpressibleSymbol::Field(field_symbol) => { - // this, unfortunately, is going to need more context, because fields live longer - // than function calls - todo!() - } + ExpressibleSymbol::Field(field_symbol) => IrExpression::Field( + builder.self_variable().clone(), + field_symbol.borrow().field_index(), + ), ExpressibleSymbol::Function(_) => { panic!("Cannot get ir_variable for FunctionSymbol"); } diff --git a/dmc-lib/src/symbol/parameter_symbol.rs b/dmc-lib/src/symbol/parameter_symbol.rs index aa8b480..2259e4f 100644 --- a/dmc-lib/src/symbol/parameter_symbol.rs +++ b/dmc-lib/src/symbol/parameter_symbol.rs @@ -7,26 +7,26 @@ use std::rc::Rc; pub struct ParameterSymbol { declared_name: Rc, declared_name_source_range: SourceRange, - type_info: TypeInfo, + type_info: Option, ir_parameter: Option>, } impl ParameterSymbol { - pub fn new( - declared_name: &Rc, - declared_name_source_range: SourceRange, - type_info: TypeInfo, - ) -> Self { + pub fn new(declared_name: &Rc, declared_name_source_range: SourceRange) -> Self { Self { declared_name: declared_name.clone(), declared_name_source_range, - type_info, + type_info: None, ir_parameter: None, } } + pub fn set_type_info(&mut self, type_info: TypeInfo) { + self.type_info = Some(type_info); + } + pub fn type_info(&self) -> &TypeInfo { - &self.type_info + self.type_info.as_ref().unwrap() } pub fn set_ir_parameter(&mut self, ir_parameter: Rc) { diff --git a/dmc-lib/src/symbol/type_symbol.rs b/dmc-lib/src/symbol/type_symbol.rs index 5a0e59f..c150891 100644 --- a/dmc-lib/src/symbol/type_symbol.rs +++ b/dmc-lib/src/symbol/type_symbol.rs @@ -4,26 +4,4 @@ use std::rc::Rc; pub enum TypeSymbol { Class(Rc>), - Primitive(PrimitiveTypeSymbol), -} - -pub enum PrimitiveTypeSymbol { - Any, - Int, - Double, - String, - Void, -} - -impl PrimitiveTypeSymbol { - pub fn try_from_declared_name(declared_name: &str) -> Option { - match declared_name { - "Any" => Some(PrimitiveTypeSymbol::Any), - "Int" => Some(PrimitiveTypeSymbol::Int), - "Double" => Some(PrimitiveTypeSymbol::Double), - "String" => Some(PrimitiveTypeSymbol::String), - "Void" => Some(PrimitiveTypeSymbol::Void), - _ => None, - } - } } diff --git a/dmc-lib/src/type_info.rs b/dmc-lib/src/type_info.rs index 39b3686..80ddd34 100644 --- a/dmc-lib/src/type_info.rs +++ b/dmc-lib/src/type_info.rs @@ -1,6 +1,8 @@ use crate::symbol::Symbol; use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::function_symbol::FunctionSymbol; +use crate::symbol::type_symbol::TypeSymbol; +use crate::symbol_table::SymbolTable; use std::cell::RefCell; use std::fmt::{Display, Formatter}; use std::rc::Rc; @@ -39,16 +41,25 @@ impl Display for TypeInfo { } impl TypeInfo { - // This is very naive but works for now - #[deprecated] - pub fn from_declared_name(declared_name: &str) -> Self { + pub fn from_declared_name( + declared_name: &str, + scope_id: usize, + symbol_table: &SymbolTable, + class_context: Option<&Rc>>, + ) -> Option { match declared_name { - "Any" => TypeInfo::Any, - "Int" => TypeInfo::Integer, - "Double" => TypeInfo::Double, - "String" => TypeInfo::String, - "Void" => TypeInfo::Void, - _ => panic!("Unknown type: {}", declared_name), + "Any" => Some(TypeInfo::Any), + "Int" => Some(TypeInfo::Integer), + "Double" => Some(TypeInfo::Double), + "String" => Some(TypeInfo::String), + "Void" => Some(TypeInfo::Void), + "Self" => Some(TypeInfo::ClassInstance(class_context.unwrap().clone())), + _ => match symbol_table.find_type_symbol(scope_id, declared_name) { + None => None, + Some(type_symbol) => match type_symbol { + TypeSymbol::Class(class_symbol) => Some(TypeInfo::ClassInstance(class_symbol)), + }, + }, } }