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