Add ability to call constructors.
This commit is contained in:
parent
8082f4c2e6
commit
93eb5eb204
@ -5,6 +5,7 @@ use crate::ir::ir_call::IrCall;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
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;
|
||||
@ -87,8 +88,11 @@ impl Call {
|
||||
.collect();
|
||||
|
||||
// check that callee is callable
|
||||
let function_symbol = match self.callee.type_info() {
|
||||
TypeInfo::Function(function_symbol) => function_symbol,
|
||||
let callable_symbol = match self.callee.type_info() {
|
||||
TypeInfo::Function(function_symbol) => {
|
||||
CallableSymbol::Function(function_symbol.clone())
|
||||
}
|
||||
TypeInfo::ClassInstance(class_symbol) => CallableSymbol::Class(class_symbol.clone()),
|
||||
_ => {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
&format!(
|
||||
@ -103,11 +107,10 @@ impl Call {
|
||||
};
|
||||
|
||||
// set return type
|
||||
self.return_type_info = Some(function_symbol.borrow().return_type_info().clone());
|
||||
self.return_type_info = Some(callable_symbol.return_type_info());
|
||||
|
||||
// check arguments length
|
||||
let function_symbol_ref = function_symbol.borrow();
|
||||
let parameters = function_symbol_ref.parameters();
|
||||
let parameters = callable_symbol.parameters();
|
||||
if parameters.len() != self.arguments.len() {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
&format!(
|
||||
|
||||
@ -44,7 +44,7 @@ impl Class {
|
||||
false,
|
||||
);
|
||||
|
||||
symbol_table
|
||||
let class_symbol = symbol_table
|
||||
.insert_class_symbol(to_insert)
|
||||
.map_err(|e| match e {
|
||||
SymbolInsertError::AlreadyDeclared(already_declared) => {
|
||||
@ -80,7 +80,10 @@ impl Class {
|
||||
|
||||
// 4. gather constructor
|
||||
if let Some(constructor) = &mut self.constructor {
|
||||
constructor.gather_declared_names(symbol_table)?;
|
||||
let constructor_symbol = constructor.gather_declared_names(symbol_table)?;
|
||||
class_symbol
|
||||
.borrow_mut()
|
||||
.set_constructor_symbol(Some(constructor_symbol));
|
||||
}
|
||||
|
||||
// 5. gather functions
|
||||
|
||||
@ -37,7 +37,7 @@ impl Constructor {
|
||||
pub fn gather_declared_names(
|
||||
&mut self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> Result<(), Vec<Diagnostic>> {
|
||||
) -> Result<Rc<RefCell<ConstructorSymbol>>, Vec<Diagnostic>> {
|
||||
// insert constructor symbol
|
||||
let to_insert = ConstructorSymbol::new(self.ctor_keyword_source_range.clone(), false);
|
||||
let constructor_symbol =
|
||||
@ -95,7 +95,7 @@ impl Constructor {
|
||||
symbol_table.pop_scope(); // function
|
||||
|
||||
if statements_diagnostics.is_empty() {
|
||||
Ok(())
|
||||
Ok(constructor_symbol)
|
||||
} else {
|
||||
Err(statements_diagnostics)
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ impl TypeUse {
|
||||
|
||||
pub fn to_type_info(&self) -> TypeInfo {
|
||||
match self.type_symbol.as_ref().unwrap() {
|
||||
TypeSymbol::Class(class_symbol) => TypeInfo::Class(class_symbol.clone()),
|
||||
TypeSymbol::Class(class_symbol) => TypeInfo::ClassInstance(class_symbol.clone()),
|
||||
TypeSymbol::Primitive(primitive_type) => match primitive_type {
|
||||
PrimitiveTypeSymbol::Any => TypeInfo::Any,
|
||||
PrimitiveTypeSymbol::Int => TypeInfo::Integer,
|
||||
|
||||
38
dmc-lib/src/symbol/callable_symbol.rs
Normal file
38
dmc-lib/src/symbol/callable_symbol.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol::function_symbol::FunctionSymbol;
|
||||
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::type_info::TypeInfo;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub enum CallableSymbol {
|
||||
Function(Rc<RefCell<FunctionSymbol>>),
|
||||
Class(Rc<RefCell<ClassSymbol>>),
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parameters(&self) -> Vec<Rc<RefCell<ParameterSymbol>>> {
|
||||
match self {
|
||||
CallableSymbol::Function(function_symbol) => {
|
||||
function_symbol.borrow().parameters().to_vec()
|
||||
}
|
||||
CallableSymbol::Class(class_symbol) => {
|
||||
if let Some(constructor_symbol) = class_symbol.borrow().constructor_symbol() {
|
||||
constructor_symbol.borrow().parameters().to_vec()
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::Symbol;
|
||||
use crate::symbol::constructor_symbol::ConstructorSymbol;
|
||||
use crate::symbol::field_symbol::FieldSymbol;
|
||||
use crate::symbol::function_symbol::FunctionSymbol;
|
||||
use std::cell::RefCell;
|
||||
@ -10,6 +11,7 @@ pub struct ClassSymbol {
|
||||
declared_name: Rc<str>,
|
||||
declared_name_source_range: SourceRange,
|
||||
is_extern: bool,
|
||||
constructor_symbol: Option<Rc<RefCell<ConstructorSymbol>>>,
|
||||
fields: HashMap<Rc<str>, Rc<RefCell<FieldSymbol>>>,
|
||||
functions: HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>>,
|
||||
}
|
||||
@ -24,10 +26,23 @@ impl ClassSymbol {
|
||||
declared_name: declared_name.clone(),
|
||||
declared_name_source_range,
|
||||
is_extern,
|
||||
constructor_symbol: None,
|
||||
fields: HashMap::new(),
|
||||
functions: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_constructor_symbol(
|
||||
&mut self,
|
||||
constructor_symbol: Option<Rc<RefCell<ConstructorSymbol>>>,
|
||||
) {
|
||||
self.constructor_symbol = constructor_symbol;
|
||||
}
|
||||
|
||||
/// A value of `None` indicates that there is no declared constructor for this class.
|
||||
pub fn constructor_symbol(&self) -> Option<&Rc<RefCell<ConstructorSymbol>>> {
|
||||
self.constructor_symbol.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Symbol for ClassSymbol {
|
||||
|
||||
@ -19,7 +19,7 @@ pub enum ExpressibleSymbol {
|
||||
impl ExpressibleSymbol {
|
||||
pub fn type_info(&self) -> TypeInfo {
|
||||
match self {
|
||||
ExpressibleSymbol::Class(class_symbol) => TypeInfo::Class(class_symbol.clone()),
|
||||
ExpressibleSymbol::Class(class_symbol) => TypeInfo::ClassInstance(class_symbol.clone()),
|
||||
ExpressibleSymbol::Field(field_symbol) => field_symbol.borrow().type_info().clone(),
|
||||
ExpressibleSymbol::Function(function_symbol) => {
|
||||
TypeInfo::Function(function_symbol.clone()) // n.b. not the return type!
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::source_range::SourceRange;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub mod callable_symbol;
|
||||
pub mod class_symbol;
|
||||
pub mod constructor_symbol;
|
||||
pub mod expressible_symbol;
|
||||
|
||||
@ -12,7 +12,7 @@ pub enum TypeInfo {
|
||||
Double,
|
||||
String,
|
||||
Function(Rc<RefCell<FunctionSymbol>>),
|
||||
Class(Rc<RefCell<ClassSymbol>>),
|
||||
ClassInstance(Rc<RefCell<ClassSymbol>>),
|
||||
Void,
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ impl Display for TypeInfo {
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
TypeInfo::Class(class_symbol) => {
|
||||
TypeInfo::ClassInstance(class_symbol) => {
|
||||
write!(f, "{}", class_symbol.borrow().declared_name())
|
||||
}
|
||||
TypeInfo::Void => write!(f, "Void"),
|
||||
@ -67,9 +67,9 @@ impl TypeInfo {
|
||||
TypeInfo::Function(_) => {
|
||||
unimplemented!("Type matching on Functions not yet supported.")
|
||||
}
|
||||
TypeInfo::Class(class_symbol) => {
|
||||
TypeInfo::ClassInstance(class_symbol) => {
|
||||
match other {
|
||||
TypeInfo::Class(other_class_symbol) => {
|
||||
TypeInfo::ClassInstance(other_class_symbol) => {
|
||||
class_symbol.borrow().declared_name()
|
||||
== other_class_symbol.borrow().declared_name() // good enough for now
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user