Work on type resolution, WIP.
This commit is contained in:
parent
10579e2ad2
commit
a87b4efaf0
@ -36,4 +36,36 @@ impl Class {
|
|||||||
functions,
|
functions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn node_id(&self) -> NodeId {
|
||||||
|
self.node_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name_owned(&self) -> Rc<str> {
|
||||||
|
self.declared_name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declared_name_source_range(&self) -> &SourceRange {
|
||||||
|
&self.declared_name_source_range
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generic_parameters(&self) -> &[GenericParameter] {
|
||||||
|
&self.generic_parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn constructor(&self) -> Option<&Constructor> {
|
||||||
|
self.constructor.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fields(&self) -> &[Field] {
|
||||||
|
&self.fields
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn functions(&self) -> &[Function] {
|
||||||
|
&self.functions
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,11 +5,10 @@ use crate::source_range::SourceRange;
|
|||||||
|
|
||||||
pub struct Constructor {
|
pub struct Constructor {
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
is_public: bool,
|
|
||||||
ctor_keyword_source_range: SourceRange,
|
ctor_keyword_source_range: SourceRange,
|
||||||
|
is_public: bool,
|
||||||
parameters: Vec<Parameter>,
|
parameters: Vec<Parameter>,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
scope_id: Option<usize>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Constructor {
|
impl Constructor {
|
||||||
@ -22,14 +21,29 @@ impl Constructor {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
node_id,
|
node_id,
|
||||||
is_public,
|
|
||||||
ctor_keyword_source_range,
|
ctor_keyword_source_range,
|
||||||
|
is_public,
|
||||||
parameters,
|
parameters,
|
||||||
statements,
|
statements,
|
||||||
scope_id: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn node_id(&self) -> NodeId {
|
||||||
|
self.node_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ctor_keyword_source_range(&self) -> &SourceRange {
|
||||||
|
&self.ctor_keyword_source_range
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_public(&self) -> bool {
|
||||||
|
self.is_public
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameters(&self) -> &[Parameter] {
|
||||||
|
&self.parameters
|
||||||
|
}
|
||||||
|
|
||||||
pub fn statements(&self) -> &[Statement] {
|
pub fn statements(&self) -> &[Statement] {
|
||||||
&self.statements
|
&self.statements
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ use crate::ast::binary_expression::BinaryExpression;
|
|||||||
use crate::ast::call::Call;
|
use crate::ast::call::Call;
|
||||||
use crate::ast::double_literal::DoubleLiteral;
|
use crate::ast::double_literal::DoubleLiteral;
|
||||||
use crate::ast::identifier::Identifier;
|
use crate::ast::identifier::Identifier;
|
||||||
|
use crate::ast::instance_self::InstanceSelf;
|
||||||
use crate::ast::integer_literal::IntegerLiteral;
|
use crate::ast::integer_literal::IntegerLiteral;
|
||||||
use crate::ast::negative_expression::NegativeExpression;
|
use crate::ast::negative_expression::NegativeExpression;
|
||||||
use crate::ast::path::Path;
|
use crate::ast::path::Path;
|
||||||
@ -18,6 +19,7 @@ pub enum Expression {
|
|||||||
Integer(IntegerLiteral),
|
Integer(IntegerLiteral),
|
||||||
Double(DoubleLiteral),
|
Double(DoubleLiteral),
|
||||||
String(StringLiteral),
|
String(StringLiteral),
|
||||||
|
InstanceSelf(InstanceSelf),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
@ -31,6 +33,7 @@ impl Expression {
|
|||||||
Expression::Integer(integer_literal) => integer_literal.node_id(),
|
Expression::Integer(integer_literal) => integer_literal.node_id(),
|
||||||
Expression::Double(double_literal) => double_literal.node_id(),
|
Expression::Double(double_literal) => double_literal.node_id(),
|
||||||
Expression::String(string_literal) => string_literal.node_id(),
|
Expression::String(string_literal) => string_literal.node_id(),
|
||||||
|
Expression::InstanceSelf(instance_self) => instance_self.node_id(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +47,7 @@ impl Expression {
|
|||||||
Expression::Integer(integer_literal) => integer_literal.source_range(),
|
Expression::Integer(integer_literal) => integer_literal.source_range(),
|
||||||
Expression::Double(double_literal) => double_literal.source_range(),
|
Expression::Double(double_literal) => double_literal.source_range(),
|
||||||
Expression::String(string_literal) => string_literal.source_range(),
|
Expression::String(string_literal) => string_literal.source_range(),
|
||||||
|
Expression::InstanceSelf(instance_self) => instance_self.source_range(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,6 +51,10 @@ impl Field {
|
|||||||
&self.declared_name_source_range
|
&self.declared_name_source_range
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn declared_type(&self) -> Option<&TypeUse> {
|
||||||
|
self.declared_type.as_ref().map(|t| &**t)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn initializer(&self) -> Option<&Expression> {
|
pub fn initializer(&self) -> Option<&Expression> {
|
||||||
self.initializer.as_ref().map(Box::as_ref)
|
self.initializer.as_ref().map(Box::as_ref)
|
||||||
}
|
}
|
||||||
|
|||||||
24
dmc-lib/src/ast/instance_self.rs
Normal file
24
dmc-lib/src/ast/instance_self.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use crate::ast::NodeId;
|
||||||
|
use crate::source_range::SourceRange;
|
||||||
|
|
||||||
|
pub struct InstanceSelf {
|
||||||
|
node_id: NodeId,
|
||||||
|
source_range: SourceRange,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InstanceSelf {
|
||||||
|
pub fn new(node_id: NodeId, source_range: SourceRange) -> Self {
|
||||||
|
Self {
|
||||||
|
node_id,
|
||||||
|
source_range,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn node_id(&self) -> NodeId {
|
||||||
|
self.node_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_range(&self) -> &SourceRange {
|
||||||
|
&self.source_range
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ pub mod field;
|
|||||||
pub mod function;
|
pub mod function;
|
||||||
pub mod generic_parameter;
|
pub mod generic_parameter;
|
||||||
pub mod identifier;
|
pub mod identifier;
|
||||||
|
pub mod instance_self;
|
||||||
pub mod integer_literal;
|
pub mod integer_literal;
|
||||||
pub mod let_statement;
|
pub mod let_statement;
|
||||||
pub mod negative_expression;
|
pub mod negative_expression;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
||||||
use crate::semantic_analysis::scope::ScopeId;
|
use crate::semantic_analysis::scope::ScopeId;
|
||||||
use crate::semantic_analysis::symbol::{ClassSymbol, FunctionSymbol, Symbol};
|
use crate::semantic_analysis::symbol::{ClassSymbol, FunctionSymbol, FunctionType, Symbol};
|
||||||
use crate::semantic_analysis::type_info::{FunctionTypeInfo, InstanceTypeInfo, TypeInfo};
|
use crate::semantic_analysis::type_info::{FunctionTypeInfo, InstanceTypeInfo, TypeInfo};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ pub fn add_primitive_symbols_and_type_infos(ctx: &mut AnalysisContext, global_sc
|
|||||||
None,
|
None,
|
||||||
"core::String::len".into(),
|
"core::String::len".into(),
|
||||||
true,
|
true,
|
||||||
true,
|
FunctionType::InstanceMethod,
|
||||||
));
|
));
|
||||||
let string_len_symbol_id = ctx
|
let string_len_symbol_id = ctx
|
||||||
.try_insert_symbol_in_scope(string_len_symbol, global_scope_id)
|
.try_insert_symbol_in_scope(string_len_symbol, global_scope_id)
|
||||||
@ -24,6 +24,7 @@ pub fn add_primitive_symbols_and_type_infos(ctx: &mut AnalysisContext, global_sc
|
|||||||
None,
|
None,
|
||||||
"core::String".into(),
|
"core::String".into(),
|
||||||
true,
|
true,
|
||||||
|
None,
|
||||||
HashMap::new(),
|
HashMap::new(),
|
||||||
string_class_methods,
|
string_class_methods,
|
||||||
));
|
));
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use crate::ir::register_allocation::{VrCollector, VrUser};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -25,3 +26,7 @@ impl Display for IrAllocate {
|
|||||||
write!(f, "alloc {}", self.class_fqn)
|
write!(f, "alloc {}", self.class_fqn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VrUser for IrAllocate {
|
||||||
|
fn vr_uses(&self, _vrs: &mut VrCollector) {}
|
||||||
|
}
|
||||||
|
|||||||
@ -5,9 +5,7 @@ use crate::ir::ir_expression::IrExpression;
|
|||||||
use crate::ir::ir_get_field_ref::IrGetFieldRef;
|
use crate::ir::ir_get_field_ref::IrGetFieldRef;
|
||||||
use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut;
|
use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut;
|
||||||
use crate::ir::ir_read_field::IrReadField;
|
use crate::ir::ir_read_field::IrReadField;
|
||||||
use crate::ir::ir_variable::IrVariableId;
|
|
||||||
use crate::ir::register_allocation::{VrCollector, VrUser};
|
use crate::ir::register_allocation::{VrCollector, VrUser};
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -58,7 +56,7 @@ impl VrUser for IrOperation {
|
|||||||
IrOperation::Load(ir_expression) => ir_expression.vr_uses(vrs),
|
IrOperation::Load(ir_expression) => ir_expression.vr_uses(vrs),
|
||||||
IrOperation::Binary(ir_binary) => ir_binary.vr_uses(vrs),
|
IrOperation::Binary(ir_binary) => ir_binary.vr_uses(vrs),
|
||||||
IrOperation::Call(ir_call) => ir_call.vr_uses(vrs),
|
IrOperation::Call(ir_call) => ir_call.vr_uses(vrs),
|
||||||
IrOperation::Allocate(_) => {}
|
IrOperation::Allocate(ir_allocate) => ir_allocate.vr_uses(vrs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,7 @@ use crate::ir::ir_assign::IrAssign;
|
|||||||
use crate::ir::ir_call::IrCall;
|
use crate::ir::ir_call::IrCall;
|
||||||
use crate::ir::ir_return::IrReturn;
|
use crate::ir::ir_return::IrReturn;
|
||||||
use crate::ir::ir_set_field::IrSetField;
|
use crate::ir::ir_set_field::IrSetField;
|
||||||
use crate::ir::ir_variable::IrVariableId;
|
|
||||||
use crate::ir::register_allocation::{VrCollector, VrUser};
|
use crate::ir::register_allocation::{VrCollector, VrUser};
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum IrStatement {
|
pub enum IrStatement {
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub type IrTypeInfoId = usize;
|
pub type IrTypeInfoId = usize;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum IrTypeInfo {
|
pub enum IrTypeInfo {
|
||||||
|
Instance(IrInstanceTypeInfo),
|
||||||
String,
|
String,
|
||||||
Int,
|
Int,
|
||||||
Double,
|
Double,
|
||||||
@ -15,3 +17,14 @@ impl Display for IrTypeInfo {
|
|||||||
write!(f, "{:?}", self)
|
write!(f, "{:?}", self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct IrInstanceTypeInfo {
|
||||||
|
class_fqn: Rc<str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrInstanceTypeInfo {
|
||||||
|
pub fn new(class_fqn: Rc<str>) -> Self {
|
||||||
|
Self { class_fqn }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use crate::ast::expression_statement::ExpressionStatement;
|
|||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
|
use crate::ir::ir_allocate::IrAllocate;
|
||||||
use crate::ir::ir_assign::IrAssign;
|
use crate::ir::ir_assign::IrAssign;
|
||||||
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
|
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
|
||||||
use crate::ir::ir_block::{IrBlock, IrBlockId};
|
use crate::ir::ir_block::{IrBlock, IrBlockId};
|
||||||
@ -25,7 +26,7 @@ use crate::ir::ir_variable::IrVariable;
|
|||||||
use crate::ir::ir_variable::{IrFreeVariables, IrStackFrameVariables, IrVariableInfo};
|
use crate::ir::ir_variable::{IrFreeVariables, IrStackFrameVariables, IrVariableInfo};
|
||||||
use crate::lowering::util::{return_type_info_to_ir_type_info, to_ir_type_info};
|
use crate::lowering::util::{return_type_info_to_ir_type_info, to_ir_type_info};
|
||||||
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
||||||
use crate::semantic_analysis::symbol::{Symbol, SymbolId};
|
use crate::semantic_analysis::symbol::{FunctionType, Symbol, SymbolId};
|
||||||
use crate::semantic_analysis::type_info::TypeInfo;
|
use crate::semantic_analysis::type_info::TypeInfo;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
@ -458,6 +459,9 @@ fn lower_expression_to_ir_operation(
|
|||||||
Expression::String(string_literal) => {
|
Expression::String(string_literal) => {
|
||||||
IrOperation::Load(IrExpression::String(string_literal.content().into()))
|
IrOperation::Load(IrExpression::String(string_literal.content().into()))
|
||||||
}
|
}
|
||||||
|
Expression::InstanceSelf(instance_self) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,6 +563,7 @@ fn lower_expression_to_ir_expression(
|
|||||||
Expression::Integer(integer_literal) => IrExpression::Int(integer_literal.value()),
|
Expression::Integer(integer_literal) => IrExpression::Int(integer_literal.value()),
|
||||||
Expression::Double(double_literal) => IrExpression::Double(double_literal.value()),
|
Expression::Double(double_literal) => IrExpression::Double(double_literal.value()),
|
||||||
Expression::String(string_literal) => IrExpression::String(string_literal.content().into()),
|
Expression::String(string_literal) => IrExpression::String(string_literal.content().into()),
|
||||||
|
Expression::InstanceSelf(instance_self) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,9 +575,71 @@ fn lower_to_ir_call(
|
|||||||
let callee_symbol_id = ctx.nodes_to_symbols()[&call.callee().node_id()];
|
let callee_symbol_id = ctx.nodes_to_symbols()[&call.callee().node_id()];
|
||||||
let callee_symbol = &ctx.symbols()[callee_symbol_id];
|
let callee_symbol = &ctx.symbols()[callee_symbol_id];
|
||||||
match callee_symbol {
|
match callee_symbol {
|
||||||
|
Symbol::Class(class_symbol) => {
|
||||||
|
match class_symbol.constructor_symbol_id() {
|
||||||
|
Some(constructor_symbol_id) => {
|
||||||
|
let constructor_symbol = ctx
|
||||||
|
.symbols()
|
||||||
|
.get(constructor_symbol_id)
|
||||||
|
.expect(&format!(
|
||||||
|
"Could not get constructor symbol for class {}",
|
||||||
|
class_symbol.fqn()
|
||||||
|
))
|
||||||
|
.unwrap_function_symbol();
|
||||||
|
let constructor_type_info_id = ctx
|
||||||
|
.symbols_to_type_infos()
|
||||||
|
.get(&constructor_symbol_id)
|
||||||
|
.expect(&format!(
|
||||||
|
"Could not get constructor type info id for class {}",
|
||||||
|
class_symbol.fqn()
|
||||||
|
));
|
||||||
|
let constructor_type_info =
|
||||||
|
ctx.type_infos()[*constructor_type_info_id].unwrap_constructor();
|
||||||
|
|
||||||
|
// get instance type info
|
||||||
|
let instance_type_info = ctx
|
||||||
|
.type_infos()
|
||||||
|
.get(constructor_type_info.instance_self_type_id())
|
||||||
|
.expect(&format!(
|
||||||
|
"Could not get instance type info for class {}",
|
||||||
|
class_symbol.fqn()
|
||||||
|
));
|
||||||
|
let ir_type_info = to_ir_type_info(ctx, instance_type_info);
|
||||||
|
|
||||||
|
// allocate a new object of this class
|
||||||
|
let ir_allocate_operation =
|
||||||
|
IrOperation::Allocate(IrAllocate::new(class_symbol.fqn_owned()));
|
||||||
|
let object_destination = fn_ctx.storage_env_mut().new_t_var(ir_type_info);
|
||||||
|
let ir_assign =
|
||||||
|
IrAssign::new(object_destination.clone(), ir_allocate_operation);
|
||||||
|
fn_ctx
|
||||||
|
.current_block_statements
|
||||||
|
.push(IrStatement::Assign(ir_assign));
|
||||||
|
|
||||||
|
// arguments
|
||||||
|
let mut arguments = vec![IrExpression::Variable(object_destination)];
|
||||||
|
for argument in call.arguments() {
|
||||||
|
arguments.push(lower_expression_to_ir_expression(argument, ctx, fn_ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
// call constructor
|
||||||
|
IrCall::new(
|
||||||
|
constructor_symbol.fqn_owned(),
|
||||||
|
arguments,
|
||||||
|
constructor_symbol.is_extern(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Symbol::Function(function_symbol) => {
|
Symbol::Function(function_symbol) => {
|
||||||
let mut arguments = Vec::new();
|
let mut arguments = Vec::new();
|
||||||
if function_symbol.is_method() {
|
if matches!(
|
||||||
|
function_symbol.function_type(),
|
||||||
|
FunctionType::InstanceMethod
|
||||||
|
) {
|
||||||
let this = match call.callee() {
|
let this = match call.callee() {
|
||||||
Expression::Path(path) => {
|
Expression::Path(path) => {
|
||||||
lower_expression_to_ir_expression(path.base(), ctx, fn_ctx)
|
lower_expression_to_ir_expression(path.base(), ctx, fn_ctx)
|
||||||
@ -600,6 +667,6 @@ fn lower_to_ir_call(
|
|||||||
function_symbol.is_extern(),
|
function_symbol.is_extern(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => panic!("Expected function symbol"),
|
_ => panic!("Expected function symbol, found {:?}", callee_symbol),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
use crate::ir::ir_type_info::IrTypeInfo;
|
use crate::ir::ir_type_info::{IrInstanceTypeInfo, IrTypeInfo};
|
||||||
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
||||||
use crate::semantic_analysis::type_info::TypeInfo;
|
use crate::semantic_analysis::type_info::TypeInfo;
|
||||||
|
|
||||||
pub fn to_ir_type_info(ctx: &AnalysisContext, sa_type_info: &TypeInfo) -> IrTypeInfo {
|
pub fn to_ir_type_info(ctx: &AnalysisContext, sa_type_info: &TypeInfo) -> IrTypeInfo {
|
||||||
match sa_type_info {
|
match sa_type_info {
|
||||||
TypeInfo::Instance(instance_type_info) => {
|
TypeInfo::Instance(instance_type_info) => {
|
||||||
let symbol = &ctx.symbols()[instance_type_info.class_symbol_id()];
|
let class_symbol =
|
||||||
if symbol.unwrap_class_symbol().fqn() == "core::String" {
|
&ctx.symbols()[instance_type_info.class_symbol_id()].unwrap_class_symbol();
|
||||||
|
if class_symbol.fqn() == "core::String" {
|
||||||
IrTypeInfo::String
|
IrTypeInfo::String
|
||||||
} else {
|
} else {
|
||||||
todo!("Non-string Instance types")
|
IrTypeInfo::Instance(IrInstanceTypeInfo::new(class_symbol.fqn_owned()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeInfo::Int => IrTypeInfo::Int,
|
TypeInfo::Int => IrTypeInfo::Int,
|
||||||
|
|||||||
@ -14,6 +14,7 @@ use crate::ast::field::Field;
|
|||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::ast::generic_parameter::GenericParameter;
|
use crate::ast::generic_parameter::GenericParameter;
|
||||||
use crate::ast::identifier::Identifier;
|
use crate::ast::identifier::Identifier;
|
||||||
|
use crate::ast::instance_self::InstanceSelf;
|
||||||
use crate::ast::integer_literal::IntegerLiteral;
|
use crate::ast::integer_literal::IntegerLiteral;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::ast::negative_expression::NegativeExpression;
|
use crate::ast::negative_expression::NegativeExpression;
|
||||||
@ -1112,6 +1113,14 @@ impl<'a> Parser<'a> {
|
|||||||
source_range,
|
source_range,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
TokenKind::SelfKw => {
|
||||||
|
let source_range = SourceRange::new(current.start(), current.end());
|
||||||
|
self.advance();
|
||||||
|
Some(Expression::InstanceSelf(InstanceSelf::new(
|
||||||
|
self.next_node_id(),
|
||||||
|
source_range,
|
||||||
|
)))
|
||||||
|
}
|
||||||
_ => unreachable!("Unreachable token type found: {:?}", current.kind()),
|
_ => unreachable!("Unreachable token type found: {:?}", current.kind()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,12 +7,18 @@ pub fn get_name_for_type<'ctx>(type_info: &TypeInfo, ctx: &'ctx AnalysisContext)
|
|||||||
TypeInfo::Function(_function_type_info) => {
|
TypeInfo::Function(_function_type_info) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
TypeInfo::Constructor(_constructor_type_info) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
TypeInfo::TypeConstructor(type_constructor_info) => {
|
||||||
|
let class_symbol = &ctx.symbols()[type_constructor_info.class_symbol_id()];
|
||||||
|
class_symbol.declared_name()
|
||||||
|
}
|
||||||
TypeInfo::Instance(instance_type_info) => {
|
TypeInfo::Instance(instance_type_info) => {
|
||||||
let class_symbol_id = instance_type_info.class_symbol_id();
|
let class_symbol_id = instance_type_info.class_symbol_id();
|
||||||
let class_symbol = &ctx.symbols()[class_symbol_id];
|
let class_symbol = &ctx.symbols()[class_symbol_id];
|
||||||
class_symbol.declared_name()
|
class_symbol.declared_name()
|
||||||
}
|
}
|
||||||
TypeInfo::String => "String",
|
|
||||||
TypeInfo::Int => "Int",
|
TypeInfo::Int => "Int",
|
||||||
TypeInfo::Double => "Double",
|
TypeInfo::Double => "Double",
|
||||||
TypeInfo::Void => "Void",
|
TypeInfo::Void => "Void",
|
||||||
|
|||||||
@ -174,7 +174,7 @@ impl AnalysisContext {
|
|||||||
&mut self,
|
&mut self,
|
||||||
to_insert: Symbol,
|
to_insert: Symbol,
|
||||||
owner_node_id: NodeId,
|
owner_node_id: NodeId,
|
||||||
) -> Result<(), Diagnostic> {
|
) -> Result<SymbolId, Diagnostic> {
|
||||||
let node_scope_id = self.nodes_to_scopes.get(&owner_node_id).expect(&format!(
|
let node_scope_id = self.nodes_to_scopes.get(&owner_node_id).expect(&format!(
|
||||||
"owner_node_id {} is not in self.nodes_to_scopes",
|
"owner_node_id {} is not in self.nodes_to_scopes",
|
||||||
owner_node_id
|
owner_node_id
|
||||||
@ -187,7 +187,7 @@ impl AnalysisContext {
|
|||||||
} else {
|
} else {
|
||||||
let symbol_id = self.insert_symbol_in_scope(*node_scope_id, to_insert);
|
let symbol_id = self.insert_symbol_in_scope(*node_scope_id, to_insert);
|
||||||
self.associate_node_to_symbol(owner_node_id, symbol_id);
|
self.associate_node_to_symbol(owner_node_id, symbol_id);
|
||||||
Ok(())
|
Ok(symbol_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,10 +255,15 @@ impl AnalysisContext {
|
|||||||
self.type_infos.len() - 1
|
self.type_infos.len() - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_type_info_for_node(&mut self, type_info: TypeInfo, node_id: NodeId) {
|
pub fn insert_type_info_for_node(
|
||||||
|
&mut self,
|
||||||
|
type_info: TypeInfo,
|
||||||
|
node_id: NodeId,
|
||||||
|
) -> TypeInfoId {
|
||||||
self.type_infos.push(type_info);
|
self.type_infos.push(type_info);
|
||||||
self.nodes_to_type_infos
|
let type_info_id = self.type_infos.len() - 1;
|
||||||
.insert(node_id, self.type_infos.len() - 1);
|
self.nodes_to_type_infos.insert(node_id, type_info_id);
|
||||||
|
type_info_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn associate_symbol_to_type(&mut self, symbol_id: SymbolId, type_info_id: TypeInfoId) {
|
pub fn associate_symbol_to_type(&mut self, symbol_id: SymbolId, type_info_id: TypeInfoId) {
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
use crate::ast::assign_statement::AssignStatement;
|
use crate::ast::assign_statement::AssignStatement;
|
||||||
use crate::ast::binary_expression::BinaryExpression;
|
use crate::ast::binary_expression::BinaryExpression;
|
||||||
use crate::ast::call::Call;
|
use crate::ast::call::Call;
|
||||||
|
use crate::ast::class::Class;
|
||||||
use crate::ast::compilation_unit::CompilationUnit;
|
use crate::ast::compilation_unit::CompilationUnit;
|
||||||
|
use crate::ast::constructor::Constructor;
|
||||||
use crate::ast::expression::Expression;
|
use crate::ast::expression::Expression;
|
||||||
use crate::ast::expression_statement::ExpressionStatement;
|
use crate::ast::expression_statement::ExpressionStatement;
|
||||||
use crate::ast::extern_function::ExternFunction;
|
use crate::ast::extern_function::ExternFunction;
|
||||||
|
use crate::ast::field::Field;
|
||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::ast::identifier::Identifier;
|
use crate::ast::identifier::Identifier;
|
||||||
|
use crate::ast::instance_self::InstanceSelf;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::ast::negative_expression::NegativeExpression;
|
use crate::ast::negative_expression::NegativeExpression;
|
||||||
use crate::ast::path::Path;
|
use crate::ast::path::Path;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
|
use crate::ast::type_use::TypeUse;
|
||||||
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
||||||
|
|
||||||
pub fn collect_scopes_compilation_unit(
|
pub fn collect_scopes_compilation_unit(
|
||||||
@ -24,6 +29,9 @@ pub fn collect_scopes_compilation_unit(
|
|||||||
for extern_function in compilation_unit.extern_functions() {
|
for extern_function in compilation_unit.extern_functions() {
|
||||||
collect_scopes_extern_function(extern_function, ctx);
|
collect_scopes_extern_function(extern_function, ctx);
|
||||||
}
|
}
|
||||||
|
for class in compilation_unit.classes() {
|
||||||
|
collect_scopes_class(class, ctx);
|
||||||
|
}
|
||||||
ctx.pop_scope(); // compilation_unit
|
ctx.pop_scope(); // compilation_unit
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,13 +46,8 @@ fn collect_scopes_function(function: &Function, ctx: &mut AnalysisContext) {
|
|||||||
for parameter in function.parameters() {
|
for parameter in function.parameters() {
|
||||||
ctx.associate_node_to_current_scope(parameter.node_id());
|
ctx.associate_node_to_current_scope(parameter.node_id());
|
||||||
}
|
}
|
||||||
match function.return_type() {
|
if let Some(type_use) = function.return_type() {
|
||||||
None => {
|
collect_scopes_type_use(type_use, ctx);
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
Some(type_use) => {
|
|
||||||
ctx.associate_node_to_current_scope(type_use.node_id());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// push block scope for body
|
// push block scope for body
|
||||||
@ -67,10 +70,74 @@ fn collect_scopes_extern_function(extern_function: &ExternFunction, ctx: &mut An
|
|||||||
for parameter in extern_function.parameters() {
|
for parameter in extern_function.parameters() {
|
||||||
ctx.associate_node_to_current_scope(parameter.node_id());
|
ctx.associate_node_to_current_scope(parameter.node_id());
|
||||||
}
|
}
|
||||||
ctx.associate_node_to_current_scope(extern_function.return_type().node_id());
|
collect_scopes_type_use(extern_function.return_type(), ctx);
|
||||||
ctx.pop_scope(); // parameters
|
ctx.pop_scope(); // parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_scopes_class(class: &Class, ctx: &mut AnalysisContext) {
|
||||||
|
// associate class with current scope
|
||||||
|
ctx.associate_node_to_current_scope(class.node_id());
|
||||||
|
|
||||||
|
ctx.push_scope("class_scope");
|
||||||
|
|
||||||
|
if let Some(constructor) = class.constructor() {
|
||||||
|
collect_scopes_constructor(constructor, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
for field in class.fields() {
|
||||||
|
collect_scopes_field(field, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
for function in class.functions() {
|
||||||
|
collect_scopes_function(function, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.pop_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generally, this is very similar to the process for functions above
|
||||||
|
fn collect_scopes_constructor(constructor: &Constructor, ctx: &mut AnalysisContext) {
|
||||||
|
// associate constructor to current scope
|
||||||
|
ctx.associate_node_to_current_scope(constructor.node_id());
|
||||||
|
|
||||||
|
// push ctor params scope
|
||||||
|
ctx.push_scope("ctor_parameters");
|
||||||
|
|
||||||
|
// parameters' scope
|
||||||
|
for parameter in constructor.parameters() {
|
||||||
|
ctx.associate_node_to_current_scope(parameter.node_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
// block scope for body
|
||||||
|
ctx.push_scope("ctor_body");
|
||||||
|
|
||||||
|
for statement in constructor.statements() {
|
||||||
|
collect_scopes_statement(statement, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.pop_scope(); // body
|
||||||
|
ctx.pop_scope(); // parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_scopes_field(field: &Field, ctx: &mut AnalysisContext) {
|
||||||
|
// associate field with current scope
|
||||||
|
ctx.associate_node_to_current_scope(field.node_id());
|
||||||
|
|
||||||
|
// if typed, associate scope
|
||||||
|
if let Some(type_use) = field.declared_type() {
|
||||||
|
collect_scopes_type_use(type_use, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if initializer, associate scope
|
||||||
|
if let Some(initializer) = field.initializer() {
|
||||||
|
collect_scopes_expression(initializer, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_scopes_type_use(type_use: &TypeUse, ctx: &mut AnalysisContext) {
|
||||||
|
ctx.associate_node_to_current_scope(type_use.node_id());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn collect_scopes_statement(statement: &Statement, ctx: &mut AnalysisContext) {
|
pub fn collect_scopes_statement(statement: &Statement, ctx: &mut AnalysisContext) {
|
||||||
match statement {
|
match statement {
|
||||||
Statement::Let(let_statement) => collect_scopes_let_statement(let_statement, ctx),
|
Statement::Let(let_statement) => collect_scopes_let_statement(let_statement, ctx),
|
||||||
@ -120,6 +187,9 @@ fn collect_scopes_expression(expression: &Expression, ctx: &mut AnalysisContext)
|
|||||||
Expression::Integer(_) => {}
|
Expression::Integer(_) => {}
|
||||||
Expression::Double(_) => {}
|
Expression::Double(_) => {}
|
||||||
Expression::String(_) => {}
|
Expression::String(_) => {}
|
||||||
|
Expression::InstanceSelf(instance_self) => {
|
||||||
|
collect_scopes_instance_self(instance_self, ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,3 +223,7 @@ fn collect_scopes_path(path: &Path, ctx: &mut AnalysisContext) {
|
|||||||
fn collect_scopes_identifier(identifier: &Identifier, ctx: &mut AnalysisContext) {
|
fn collect_scopes_identifier(identifier: &Identifier, ctx: &mut AnalysisContext) {
|
||||||
ctx.associate_node_to_current_scope(identifier.node_id());
|
ctx.associate_node_to_current_scope(identifier.node_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_scopes_instance_self(instance_self: &InstanceSelf, ctx: &mut AnalysisContext) {
|
||||||
|
ctx.associate_node_to_current_scope(instance_self.node_id());
|
||||||
|
}
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
|
use crate::ast::class::Class;
|
||||||
use crate::ast::compilation_unit::CompilationUnit;
|
use crate::ast::compilation_unit::CompilationUnit;
|
||||||
|
use crate::ast::constructor::Constructor;
|
||||||
use crate::ast::extern_function::ExternFunction;
|
use crate::ast::extern_function::ExternFunction;
|
||||||
|
use crate::ast::field::Field;
|
||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::ast::parameter::Parameter;
|
use crate::ast::parameter::Parameter;
|
||||||
use crate::diagnostic::Diagnostics;
|
use crate::diagnostic::Diagnostics;
|
||||||
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
||||||
use crate::semantic_analysis::symbol::{FunctionSymbol, ParameterSymbol, Symbol};
|
use crate::semantic_analysis::symbol::{
|
||||||
|
ClassSymbol, FieldSymbol, FunctionSymbol, FunctionType, ParameterSymbol, Symbol, SymbolId,
|
||||||
|
};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub struct SymbolCollectionResult(pub Diagnostics);
|
pub struct SymbolCollectionResult(pub Diagnostics);
|
||||||
|
|
||||||
@ -15,13 +21,22 @@ pub fn collect_symbols_compilation_unit(
|
|||||||
let mut diagnostics = Diagnostics::new();
|
let mut diagnostics = Diagnostics::new();
|
||||||
|
|
||||||
for function in compilation_unit.functions() {
|
for function in compilation_unit.functions() {
|
||||||
collect_symbols_function(function, analysis_context, &mut diagnostics);
|
collect_symbols_function(
|
||||||
|
function,
|
||||||
|
analysis_context,
|
||||||
|
&mut diagnostics,
|
||||||
|
FunctionType::Function,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for extern_function in compilation_unit.extern_functions() {
|
for extern_function in compilation_unit.extern_functions() {
|
||||||
collect_symbols_extern_function(extern_function, analysis_context, &mut diagnostics);
|
collect_symbols_extern_function(extern_function, analysis_context, &mut diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for class in compilation_unit.classes() {
|
||||||
|
collect_symbols_class(class, analysis_context, &mut diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
SymbolCollectionResult(diagnostics)
|
SymbolCollectionResult(diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,6 +44,7 @@ fn collect_symbols_function(
|
|||||||
function: &Function,
|
function: &Function,
|
||||||
ctx: &mut AnalysisContext,
|
ctx: &mut AnalysisContext,
|
||||||
diagnostics: &mut Diagnostics,
|
diagnostics: &mut Diagnostics,
|
||||||
|
function_type: FunctionType,
|
||||||
) {
|
) {
|
||||||
let fqn = ctx.resolve_fqn(&function.declared_name()).into();
|
let fqn = ctx.resolve_fqn(&function.declared_name()).into();
|
||||||
|
|
||||||
@ -38,7 +54,7 @@ fn collect_symbols_function(
|
|||||||
Some(function.declared_name_source_range()),
|
Some(function.declared_name_source_range()),
|
||||||
fqn,
|
fqn,
|
||||||
false,
|
false,
|
||||||
false,
|
function_type,
|
||||||
));
|
));
|
||||||
|
|
||||||
// insert
|
// insert
|
||||||
@ -71,7 +87,7 @@ fn collect_symbols_extern_function(
|
|||||||
Some(extern_function.declared_name_source_range()),
|
Some(extern_function.declared_name_source_range()),
|
||||||
fqn,
|
fqn,
|
||||||
true,
|
true,
|
||||||
false,
|
FunctionType::Function,
|
||||||
));
|
));
|
||||||
|
|
||||||
// insert function symbol
|
// insert function symbol
|
||||||
@ -87,6 +103,102 @@ fn collect_symbols_extern_function(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_symbols_class(class: &Class, ctx: &mut AnalysisContext, diagnostics: &mut Diagnostics) {
|
||||||
|
// Symbols for fields
|
||||||
|
// Ctor symbol (maybe just a function symbol?)
|
||||||
|
// Recurse on methods
|
||||||
|
// Class symbol for self
|
||||||
|
|
||||||
|
let mut field_symbol_ids = HashMap::new();
|
||||||
|
for field in class.fields() {
|
||||||
|
collect_symbols_field(field, ctx, diagnostics);
|
||||||
|
let maybe_field_symbol_id = ctx.nodes_to_symbols().get(&field.node_id());
|
||||||
|
match maybe_field_symbol_id {
|
||||||
|
Some(field_symbol_id) => {
|
||||||
|
field_symbol_ids.insert(field.declared_name_owned(), *field_symbol_id);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let constructor_symbol_id = if let Some(constructor) = class.constructor() {
|
||||||
|
collect_symbols_constructor(constructor, ctx, diagnostics);
|
||||||
|
let maybe_constructor_symbol_id = ctx.nodes_to_symbols().get(&constructor.node_id());
|
||||||
|
match maybe_constructor_symbol_id {
|
||||||
|
Some(constructor_symbol_id) => Some(*constructor_symbol_id),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut method_symbol_ids = HashMap::new();
|
||||||
|
for function in class.functions() {
|
||||||
|
collect_symbols_function(function, ctx, diagnostics, FunctionType::InstanceMethod);
|
||||||
|
let maybe_method_symbol_id = ctx.nodes_to_symbols().get(&function.node_id());
|
||||||
|
match maybe_method_symbol_id {
|
||||||
|
Some(method_symbol_id) => {
|
||||||
|
method_symbol_ids.insert(function.declared_name_owned(), *method_symbol_id);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let class_symbol = Symbol::Class(ClassSymbol::new(
|
||||||
|
class.declared_name_owned(),
|
||||||
|
Some(class.declared_name_source_range().clone()),
|
||||||
|
ctx.resolve_fqn(&class.declared_name()).into(),
|
||||||
|
false,
|
||||||
|
constructor_symbol_id,
|
||||||
|
field_symbol_ids,
|
||||||
|
method_symbol_ids,
|
||||||
|
));
|
||||||
|
|
||||||
|
match ctx.try_insert_associate_symbol_in_node_scope(class_symbol, class.node_id()) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(diagnostic) => {
|
||||||
|
diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_symbols_field(field: &Field, ctx: &mut AnalysisContext, diagnostics: &mut Diagnostics) {
|
||||||
|
let field_symbol = Symbol::Field(FieldSymbol::new(
|
||||||
|
field.declared_name_owned(),
|
||||||
|
Some(field.declared_name_source_range().clone()),
|
||||||
|
));
|
||||||
|
match ctx.try_insert_associate_symbol_in_node_scope(field_symbol, field.node_id()) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(diagnostic) => {
|
||||||
|
diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_symbols_constructor(
|
||||||
|
constructor: &Constructor,
|
||||||
|
ctx: &mut AnalysisContext,
|
||||||
|
diagnostics: &mut Diagnostics,
|
||||||
|
) {
|
||||||
|
for parameter in constructor.parameters() {
|
||||||
|
collect_symbols_parameter(parameter, ctx, diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
|
let function_symbol = Symbol::Function(FunctionSymbol::new(
|
||||||
|
"__ctor__".into(),
|
||||||
|
Some(constructor.ctor_keyword_source_range().clone()),
|
||||||
|
ctx.resolve_fqn("__ctor__").into(),
|
||||||
|
false,
|
||||||
|
FunctionType::Constructor,
|
||||||
|
));
|
||||||
|
match ctx.try_insert_associate_symbol_in_node_scope(function_symbol, constructor.node_id()) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(diagnostic) => {
|
||||||
|
diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn collect_symbols_parameter(
|
fn collect_symbols_parameter(
|
||||||
parameter: &Parameter,
|
parameter: &Parameter,
|
||||||
ctx: &mut AnalysisContext,
|
ctx: &mut AnalysisContext,
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
|
use crate::ast::class::Class;
|
||||||
use crate::ast::compilation_unit::CompilationUnit;
|
use crate::ast::compilation_unit::CompilationUnit;
|
||||||
|
use crate::ast::constructor::Constructor;
|
||||||
use crate::ast::extern_function::ExternFunction;
|
use crate::ast::extern_function::ExternFunction;
|
||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::ast::parameter::Parameter;
|
use crate::ast::parameter::Parameter;
|
||||||
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
||||||
use crate::semantic_analysis::type_info::{FunctionTypeInfo, TypeInfo, TypeInfoId};
|
use crate::semantic_analysis::symbol::SymbolId;
|
||||||
|
use crate::semantic_analysis::type_info::{
|
||||||
|
ConstructorTypeInfo, FunctionTypeInfo, InstanceTypeInfo, TypeConstructorInfo, TypeInfo,
|
||||||
|
TypeInfoId,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn collect_types(compilation_unit: &CompilationUnit, ctx: &mut AnalysisContext) {
|
pub fn collect_types(compilation_unit: &CompilationUnit, ctx: &mut AnalysisContext) {
|
||||||
for function in compilation_unit.functions() {
|
for function in compilation_unit.functions() {
|
||||||
@ -13,6 +19,10 @@ pub fn collect_types(compilation_unit: &CompilationUnit, ctx: &mut AnalysisConte
|
|||||||
for extern_function in compilation_unit.extern_functions() {
|
for extern_function in compilation_unit.extern_functions() {
|
||||||
collect_types_extern_function(extern_function, ctx);
|
collect_types_extern_function(extern_function, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for class in compilation_unit.classes() {
|
||||||
|
collect_types_class(class, ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_types_function(function: &Function, ctx: &mut AnalysisContext) {
|
fn collect_types_function(function: &Function, ctx: &mut AnalysisContext) {
|
||||||
@ -21,7 +31,16 @@ fn collect_types_function(function: &Function, ctx: &mut AnalysisContext) {
|
|||||||
|
|
||||||
let return_type_info = match function.return_type() {
|
let return_type_info = match function.return_type() {
|
||||||
None => TypeInfo::Void,
|
None => TypeInfo::Void,
|
||||||
Some(type_use) => declared_name_to_type_info(ctx, type_use.declared_name()),
|
Some(type_use) => get_intrinsic_type(type_use.declared_name()).unwrap_or_else(|| {
|
||||||
|
let symbol_id = ctx
|
||||||
|
.nodes_to_symbols()
|
||||||
|
.get(&type_use.node_id())
|
||||||
|
.expect(&format!(
|
||||||
|
"Could not get symbol id for type_use {}",
|
||||||
|
type_use.declared_name()
|
||||||
|
));
|
||||||
|
resolve_type(ctx, *symbol_id)
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
let return_type_info_id = ctx.insert_type_info(return_type_info);
|
let return_type_info_id = ctx.insert_type_info(return_type_info);
|
||||||
|
|
||||||
@ -35,6 +54,21 @@ fn collect_types_function(function: &Function, ctx: &mut AnalysisContext) {
|
|||||||
ctx.associate_node_and_symbol_to_type(function.node_id(), function_type_info_id);
|
ctx.associate_node_and_symbol_to_type(function.node_id(), function_type_info_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_intrinsic_type(declared_name: &str) -> Option<TypeInfo> {
|
||||||
|
match declared_name {
|
||||||
|
"Any" => Some(TypeInfo::Any),
|
||||||
|
"Void" => Some(TypeInfo::Void),
|
||||||
|
"Int" => Some(TypeInfo::Int),
|
||||||
|
"Double" => Some(TypeInfo::Double),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_type(ctx: &AnalysisContext, symbol_id: SymbolId) -> TypeInfo {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated]
|
||||||
fn declared_name_to_type_info(ctx: &AnalysisContext, declared_name: &str) -> TypeInfo {
|
fn declared_name_to_type_info(ctx: &AnalysisContext, declared_name: &str) -> TypeInfo {
|
||||||
match declared_name {
|
match declared_name {
|
||||||
"Any" => TypeInfo::Any,
|
"Any" => TypeInfo::Any,
|
||||||
@ -48,7 +82,9 @@ fn declared_name_to_type_info(ctx: &AnalysisContext, declared_name: &str) -> Typ
|
|||||||
"Int" => TypeInfo::Int,
|
"Int" => TypeInfo::Int,
|
||||||
"Double" => TypeInfo::Double,
|
"Double" => TypeInfo::Double,
|
||||||
"Void" => TypeInfo::Void,
|
"Void" => TypeInfo::Void,
|
||||||
_ => TypeInfo::__Error,
|
_ => {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,3 +122,59 @@ fn collect_types_extern_function(extern_function: &ExternFunction, ctx: &mut Ana
|
|||||||
|
|
||||||
ctx.associate_node_and_symbol_to_type(extern_function.node_id(), function_type_info_id);
|
ctx.associate_node_and_symbol_to_type(extern_function.node_id(), function_type_info_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_types_class(class: &Class, ctx: &mut AnalysisContext) {
|
||||||
|
let self_instance_type_info = TypeInfo::Instance(InstanceTypeInfo::new(
|
||||||
|
*ctx.nodes_to_symbols()
|
||||||
|
.get(&class.node_id())
|
||||||
|
.expect(&format!(
|
||||||
|
"Could not find class symbol for {} {}",
|
||||||
|
class.node_id(),
|
||||||
|
class.declared_name()
|
||||||
|
)),
|
||||||
|
));
|
||||||
|
let self_instance_type_info_id = ctx.insert_type_info(self_instance_type_info);
|
||||||
|
|
||||||
|
let constructor_type_info_id = if let Some(constructor) = class.constructor() {
|
||||||
|
Some(collect_types_constructor(
|
||||||
|
constructor,
|
||||||
|
ctx,
|
||||||
|
self_instance_type_info_id,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo: fields, methods
|
||||||
|
|
||||||
|
// Self type constructor
|
||||||
|
let type_constructor_type_info = TypeInfo::TypeConstructor(TypeConstructorInfo::new(
|
||||||
|
ctx.nodes_to_symbols()[&class.node_id()],
|
||||||
|
constructor_type_info_id,
|
||||||
|
));
|
||||||
|
let type_constructor_type_info_id = ctx.insert_type_info(type_constructor_type_info);
|
||||||
|
ctx.associate_node_and_symbol_to_type(class.node_id(), type_constructor_type_info_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_types_constructor(
|
||||||
|
constructor: &Constructor,
|
||||||
|
ctx: &mut AnalysisContext,
|
||||||
|
self_type_info_id: TypeInfoId,
|
||||||
|
) -> TypeInfoId {
|
||||||
|
let mut parameter_type_info_ids: Vec<TypeInfoId> = Vec::new();
|
||||||
|
for parameter in constructor.parameters() {
|
||||||
|
let type_info = declared_name_to_type_info(ctx, parameter.type_use().declared_name());
|
||||||
|
let type_info_id = ctx.insert_type_info(type_info);
|
||||||
|
ctx.associate_node_and_symbol_to_type(parameter.node_id(), type_info_id);
|
||||||
|
parameter_type_info_ids.push(type_info_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let constructor_type_info = TypeInfo::Constructor(ConstructorTypeInfo::new(
|
||||||
|
self_type_info_id,
|
||||||
|
parameter_type_info_ids,
|
||||||
|
));
|
||||||
|
|
||||||
|
let constructor_type_info_id = ctx.insert_type_info(constructor_type_info);
|
||||||
|
ctx.associate_node_and_symbol_to_type(constructor.node_id(), constructor_type_info_id);
|
||||||
|
constructor_type_info_id
|
||||||
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ mod resolve_names;
|
|||||||
mod resolve_types;
|
mod resolve_types;
|
||||||
pub mod scope;
|
pub mod scope;
|
||||||
pub mod symbol;
|
pub mod symbol;
|
||||||
|
pub mod type_analysis;
|
||||||
pub mod type_info;
|
pub mod type_info;
|
||||||
|
|
||||||
pub fn analyze_compilation_unit(
|
pub fn analyze_compilation_unit(
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use crate::ast::expression_statement::ExpressionStatement;
|
|||||||
use crate::ast::extern_function::ExternFunction;
|
use crate::ast::extern_function::ExternFunction;
|
||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::ast::identifier::Identifier;
|
use crate::ast::identifier::Identifier;
|
||||||
|
use crate::ast::instance_self::InstanceSelf;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::ast::negative_expression::NegativeExpression;
|
use crate::ast::negative_expression::NegativeExpression;
|
||||||
use crate::ast::parameter::Parameter;
|
use crate::ast::parameter::Parameter;
|
||||||
@ -205,6 +206,9 @@ fn resolve_names_expression(
|
|||||||
Expression::Integer(_) => {}
|
Expression::Integer(_) => {}
|
||||||
Expression::Double(_) => {}
|
Expression::Double(_) => {}
|
||||||
Expression::String(_) => {}
|
Expression::String(_) => {}
|
||||||
|
Expression::InstanceSelf(instance_self) => {
|
||||||
|
resolve_names_instance_self(instance_self, ctx, diagnostics, phase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,3 +274,12 @@ fn resolve_names_identifier(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_names_instance_self(
|
||||||
|
instance_self: &InstanceSelf,
|
||||||
|
ctx: &mut AnalysisContext,
|
||||||
|
diagnostics: &mut Diagnostics,
|
||||||
|
phase: ExpressionResolutionPhase,
|
||||||
|
) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use crate::ast::compilation_unit::CompilationUnit;
|
|||||||
use crate::ast::expression::Expression;
|
use crate::ast::expression::Expression;
|
||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
use crate::ast::identifier::Identifier;
|
use crate::ast::identifier::Identifier;
|
||||||
|
use crate::ast::instance_self::InstanceSelf;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::ast::negative_expression::NegativeExpression;
|
use crate::ast::negative_expression::NegativeExpression;
|
||||||
use crate::ast::parameter::Parameter;
|
use crate::ast::parameter::Parameter;
|
||||||
@ -163,6 +164,9 @@ fn resolve_types_expression(
|
|||||||
string_literal.node_id(),
|
string_literal.node_id(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Expression::InstanceSelf(instance_self) => {
|
||||||
|
resolve_types_instance_self(instance_self, ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +255,70 @@ fn resolve_types_call(call: &Call, ctx: &mut AnalysisContext, diagnostics: &mut
|
|||||||
let callee_type_info = ctx.get_type_info_for_node(call.callee().node_id());
|
let callee_type_info = ctx.get_type_info_for_node(call.callee().node_id());
|
||||||
|
|
||||||
match callee_type_info {
|
match callee_type_info {
|
||||||
|
TypeInfo::TypeConstructor(type_constructor_info) => {
|
||||||
|
let class_symbol =
|
||||||
|
ctx.symbols()[type_constructor_info.class_symbol_id()].unwrap_class_symbol();
|
||||||
|
match class_symbol.constructor_symbol_id() {
|
||||||
|
Some(constructor_symbol_id) => {
|
||||||
|
let constructor_type_info_id =
|
||||||
|
ctx.symbols_to_type_infos()[&constructor_symbol_id];
|
||||||
|
let constructor_type_info = ctx
|
||||||
|
.type_infos()
|
||||||
|
.get(constructor_type_info_id)
|
||||||
|
.expect(&format!(
|
||||||
|
"Cannot get constructor type info for {}",
|
||||||
|
get_name_for_type(callee_type_info, ctx)
|
||||||
|
))
|
||||||
|
.unwrap_constructor();
|
||||||
|
|
||||||
|
// check arguments length
|
||||||
|
let arguments = call.arguments();
|
||||||
|
if arguments.len() != constructor_type_info.parameter_type_ids().len() {
|
||||||
|
todo!("Report wrong number of constructor args")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check each argument type
|
||||||
|
let parameter_type_ids = constructor_type_info.parameter_type_ids();
|
||||||
|
if arguments.len() == parameter_type_ids.len() {
|
||||||
|
for i in 0..parameter_type_ids.len() {
|
||||||
|
let argument_type_info =
|
||||||
|
ctx.get_type_info_for_node(arguments[i].node_id());
|
||||||
|
let parameter_type_info =
|
||||||
|
ctx.get_type_info_by_id(parameter_type_ids[i]);
|
||||||
|
if !can_assign_right_to_left(
|
||||||
|
parameter_type_info,
|
||||||
|
argument_type_info,
|
||||||
|
ctx,
|
||||||
|
) {
|
||||||
|
let parameter_type_name =
|
||||||
|
get_name_for_type(parameter_type_info, ctx);
|
||||||
|
let argument_type_name = get_name_for_type(argument_type_info, ctx);
|
||||||
|
let message = format!(
|
||||||
|
"Incompatible types: cannot assign {} to {}",
|
||||||
|
argument_type_name, parameter_type_name
|
||||||
|
);
|
||||||
|
let diagnostic = Diagnostic::new(
|
||||||
|
&message,
|
||||||
|
arguments[i].source_range().start(),
|
||||||
|
arguments[i].source_range().end(),
|
||||||
|
);
|
||||||
|
diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set return type of call to be the "return" type of the constructor
|
||||||
|
ctx.associate_node_to_type(
|
||||||
|
call.node_id(),
|
||||||
|
constructor_type_info.instance_self_type_id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// Default, no-arg constructor
|
||||||
|
// check zero args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
TypeInfo::Function(function_type_info) => {
|
TypeInfo::Function(function_type_info) => {
|
||||||
// check arguments length
|
// check arguments length
|
||||||
let arguments = call.arguments();
|
let arguments = call.arguments();
|
||||||
@ -389,3 +457,7 @@ fn resolve_types_identifier(identifier: &Identifier, ctx: &mut AnalysisContext)
|
|||||||
let type_info_id = ctx.lookup_type_for_node_via_symbol(identifier.node_id());
|
let type_info_id = ctx.lookup_type_for_node_via_symbol(identifier.node_id());
|
||||||
ctx.associate_node_to_type(identifier.node_id(), type_info_id);
|
ctx.associate_node_to_type(identifier.node_id(), type_info_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_types_instance_self(instance_self: &InstanceSelf, ctx: &mut AnalysisContext) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|||||||
@ -147,16 +147,18 @@ pub fn can_assign_right_to_left(left: &TypeInfo, right: &TypeInfo, ctx: &Analysi
|
|||||||
TypeInfo::Function(_) => {
|
TypeInfo::Function(_) => {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
TypeInfo::Constructor(_) => {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
TypeInfo::TypeConstructor(_) => {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
TypeInfo::Instance(left_instance_type_info) => match right {
|
TypeInfo::Instance(left_instance_type_info) => match right {
|
||||||
TypeInfo::Instance(right_instance_type_info) => {
|
TypeInfo::Instance(right_instance_type_info) => {
|
||||||
left_instance_type_info.can_assign_from(right_instance_type_info, ctx)
|
left_instance_type_info.can_assign_from(right_instance_type_info, ctx)
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
TypeInfo::String => match right {
|
|
||||||
TypeInfo::String => true,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
TypeInfo::Int => match right {
|
TypeInfo::Int => match right {
|
||||||
TypeInfo::Int => true,
|
TypeInfo::Int => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|||||||
@ -51,6 +51,13 @@ impl Symbol {
|
|||||||
_ => panic!("Attempt to unwrap {:?} as ClassSymbol", self),
|
_ => panic!("Attempt to unwrap {:?} as ClassSymbol", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unwrap_function_symbol(&self) -> &FunctionSymbol {
|
||||||
|
match self {
|
||||||
|
Symbol::Function(function_symbol) => function_symbol,
|
||||||
|
_ => panic!("Attempt to unwrap {:?} as FunctionSymbol", self),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -59,6 +66,7 @@ pub struct ClassSymbol {
|
|||||||
source_range: Option<SourceRange>,
|
source_range: Option<SourceRange>,
|
||||||
fqn: Rc<str>,
|
fqn: Rc<str>,
|
||||||
is_extern: bool,
|
is_extern: bool,
|
||||||
|
constructor_symbol_id: Option<SymbolId>,
|
||||||
field_symbol_ids: HashMap<Rc<str>, SymbolId>,
|
field_symbol_ids: HashMap<Rc<str>, SymbolId>,
|
||||||
method_symbol_ids: HashMap<Rc<str>, SymbolId>,
|
method_symbol_ids: HashMap<Rc<str>, SymbolId>,
|
||||||
}
|
}
|
||||||
@ -69,6 +77,7 @@ impl ClassSymbol {
|
|||||||
source_range: Option<SourceRange>,
|
source_range: Option<SourceRange>,
|
||||||
fqn: Rc<str>,
|
fqn: Rc<str>,
|
||||||
is_extern: bool,
|
is_extern: bool,
|
||||||
|
constructor_symbol_id: Option<SymbolId>,
|
||||||
field_symbol_ids: HashMap<Rc<str>, SymbolId>,
|
field_symbol_ids: HashMap<Rc<str>, SymbolId>,
|
||||||
method_symbol_ids: HashMap<Rc<str>, SymbolId>,
|
method_symbol_ids: HashMap<Rc<str>, SymbolId>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -77,6 +86,7 @@ impl ClassSymbol {
|
|||||||
source_range,
|
source_range,
|
||||||
fqn,
|
fqn,
|
||||||
is_extern,
|
is_extern,
|
||||||
|
constructor_symbol_id,
|
||||||
field_symbol_ids,
|
field_symbol_ids,
|
||||||
method_symbol_ids,
|
method_symbol_ids,
|
||||||
}
|
}
|
||||||
@ -98,10 +108,18 @@ impl ClassSymbol {
|
|||||||
&self.fqn
|
&self.fqn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fqn_owned(&self) -> Rc<str> {
|
||||||
|
self.fqn.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn can_assign_from(&self, right: &ClassSymbol, _ctx: &AnalysisContext) -> bool {
|
pub fn can_assign_from(&self, right: &ClassSymbol, _ctx: &AnalysisContext) -> bool {
|
||||||
self.fqn == right.fqn // eventually, this will check inheritance logic, etc.
|
self.fqn == right.fqn // eventually, this will check inheritance logic, etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn constructor_symbol_id(&self) -> Option<SymbolId> {
|
||||||
|
self.constructor_symbol_id
|
||||||
|
}
|
||||||
|
|
||||||
pub fn field_symbol_ids(&self) -> &HashMap<Rc<str>, SymbolId> {
|
pub fn field_symbol_ids(&self) -> &HashMap<Rc<str>, SymbolId> {
|
||||||
&self.field_symbol_ids
|
&self.field_symbol_ids
|
||||||
}
|
}
|
||||||
@ -138,13 +156,21 @@ impl FieldSymbol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum FunctionType {
|
||||||
|
Function,
|
||||||
|
Constructor,
|
||||||
|
InstanceMethod,
|
||||||
|
StaticMethod,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FunctionSymbol {
|
pub struct FunctionSymbol {
|
||||||
declared_name: Rc<str>,
|
declared_name: Rc<str>,
|
||||||
declared_name_source_range: Option<SourceRange>,
|
declared_name_source_range: Option<SourceRange>,
|
||||||
fqn: Rc<str>,
|
fqn: Rc<str>,
|
||||||
is_extern: bool,
|
is_extern: bool,
|
||||||
is_method: bool,
|
function_type: FunctionType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionSymbol {
|
impl FunctionSymbol {
|
||||||
@ -153,14 +179,14 @@ impl FunctionSymbol {
|
|||||||
declared_name_source_range: Option<SourceRange>,
|
declared_name_source_range: Option<SourceRange>,
|
||||||
fqn: Rc<str>,
|
fqn: Rc<str>,
|
||||||
is_extern: bool,
|
is_extern: bool,
|
||||||
is_method: bool,
|
function_type: FunctionType,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
declared_name,
|
declared_name,
|
||||||
declared_name_source_range,
|
declared_name_source_range,
|
||||||
fqn,
|
fqn,
|
||||||
is_extern,
|
is_extern,
|
||||||
is_method,
|
function_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,8 +214,8 @@ impl FunctionSymbol {
|
|||||||
self.is_extern
|
self.is_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_method(&self) -> bool {
|
pub fn function_type(&self) -> &FunctionType {
|
||||||
self.is_method
|
&self.function_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
25
dmc-lib/src/semantic_analysis/type_analysis/collect.rs
Normal file
25
dmc-lib/src/semantic_analysis/type_analysis/collect.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use crate::ast::class::Class;
|
||||||
|
use crate::ast::compilation_unit::CompilationUnit;
|
||||||
|
use crate::semantic_analysis::analysis_context::AnalysisContext;
|
||||||
|
use crate::semantic_analysis::type_info::{InstanceTypeInfo, TypeInfo};
|
||||||
|
|
||||||
|
pub fn collect_types(compilation_unit: &CompilationUnit, ctx: &mut AnalysisContext) {
|
||||||
|
for class in compilation_unit.classes() {
|
||||||
|
collect_types_class(class, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_types_class(class: &Class, ctx: &mut AnalysisContext) {
|
||||||
|
let class_symbol_id = *ctx
|
||||||
|
.nodes_to_symbols()
|
||||||
|
.get(&class.node_id())
|
||||||
|
.expect(&format!(
|
||||||
|
"Could not find class symbol for {} {}",
|
||||||
|
class.node_id(),
|
||||||
|
class.declared_name()
|
||||||
|
));
|
||||||
|
|
||||||
|
let self_instance_type_info = TypeInfo::Instance(InstanceTypeInfo::new(class_symbol_id));
|
||||||
|
let self_instance_type_info_id = ctx.insert_type_info(self_instance_type_info);
|
||||||
|
ctx.associate_symbol_to_type(class_symbol_id, self_instance_type_info_id)
|
||||||
|
}
|
||||||
1
dmc-lib/src/semantic_analysis/type_analysis/infer.rs
Normal file
1
dmc-lib/src/semantic_analysis/type_analysis/infer.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
3
dmc-lib/src/semantic_analysis/type_analysis/mod.rs
Normal file
3
dmc-lib/src/semantic_analysis/type_analysis/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod collect;
|
||||||
|
mod infer;
|
||||||
|
mod resolve;
|
||||||
1
dmc-lib/src/semantic_analysis/type_analysis/resolve.rs
Normal file
1
dmc-lib/src/semantic_analysis/type_analysis/resolve.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
@ -7,14 +7,31 @@ pub type TypeInfoId = usize;
|
|||||||
pub enum TypeInfo {
|
pub enum TypeInfo {
|
||||||
Any,
|
Any,
|
||||||
Function(FunctionTypeInfo),
|
Function(FunctionTypeInfo),
|
||||||
|
Constructor(ConstructorTypeInfo),
|
||||||
|
TypeConstructor(TypeConstructorInfo),
|
||||||
Instance(InstanceTypeInfo),
|
Instance(InstanceTypeInfo),
|
||||||
String,
|
|
||||||
Int,
|
Int,
|
||||||
Double,
|
Double,
|
||||||
Void,
|
Void,
|
||||||
__Error,
|
__Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypeInfo {
|
||||||
|
pub fn unwrap_constructor(&self) -> &ConstructorTypeInfo {
|
||||||
|
match self {
|
||||||
|
TypeInfo::Constructor(constructor_type_info) => constructor_type_info,
|
||||||
|
_ => panic!("Attempt to unwrap {:?} as Constructor", self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unwrap_type_constructor(&self) -> &TypeConstructorInfo {
|
||||||
|
match self {
|
||||||
|
TypeInfo::TypeConstructor(type_constructor_info) => type_constructor_info,
|
||||||
|
_ => panic!("Attempt to unwrap {:?} as TypeConstructor", self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct FunctionTypeInfo {
|
pub struct FunctionTypeInfo {
|
||||||
parameter_type_info_ids: Vec<TypeInfoId>,
|
parameter_type_info_ids: Vec<TypeInfoId>,
|
||||||
@ -48,6 +65,52 @@ impl FunctionTypeInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ConstructorTypeInfo {
|
||||||
|
instance_self_type_id: TypeInfoId,
|
||||||
|
parameter_type_ids: Vec<TypeInfoId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConstructorTypeInfo {
|
||||||
|
pub fn new(instance_self_type_id: TypeInfoId, parameter_type_ids: Vec<TypeInfoId>) -> Self {
|
||||||
|
Self {
|
||||||
|
instance_self_type_id,
|
||||||
|
parameter_type_ids,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn instance_self_type_id(&self) -> TypeInfoId {
|
||||||
|
self.instance_self_type_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameter_type_ids(&self) -> &[TypeInfoId] {
|
||||||
|
&self.parameter_type_ids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct TypeConstructorInfo {
|
||||||
|
class_symbol_id: SymbolId,
|
||||||
|
constructor_type_info_id: Option<TypeInfoId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeConstructorInfo {
|
||||||
|
pub fn new(class_symbol_id: SymbolId, constructor_type_info_id: Option<TypeInfoId>) -> Self {
|
||||||
|
Self {
|
||||||
|
class_symbol_id,
|
||||||
|
constructor_type_info_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_symbol_id(&self) -> SymbolId {
|
||||||
|
self.class_symbol_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn constructor_type_info_id(&self) -> Option<TypeInfoId> {
|
||||||
|
self.constructor_type_info_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct InstanceTypeInfo {
|
pub struct InstanceTypeInfo {
|
||||||
class_symbol_id: SymbolId,
|
class_symbol_id: SymbolId,
|
||||||
|
|||||||
@ -182,10 +182,10 @@ mod e2e_tests {
|
|||||||
let context = prepare_context(
|
let context = prepare_context(
|
||||||
"
|
"
|
||||||
class Foo
|
class Foo
|
||||||
mut bar = 21
|
bar: Int
|
||||||
|
|
||||||
ctor(_bar: Int)
|
pub ctor(bar: Int)
|
||||||
bar = _bar
|
self.bar = bar
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user