Work on new compile pipeline and semantic analysis flow WIP.
This commit is contained in:
parent
96ea0c5e50
commit
4ae4f7e9e6
@ -1,13 +1,17 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::helpers::{insert_resolved_names_into, insert_resolved_types_into};
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::ir_util::get_or_init_mut_field_pointer_variable;
|
||||
use crate::ast::{NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics, SecondaryLabel};
|
||||
use crate::diagnostic_factories::{
|
||||
destination_must_be_mutable, mismatched_assign_types, must_be_l_value,
|
||||
};
|
||||
use crate::error_codes::{ASSIGN_LHS_IMMUTABLE, ASSIGN_MISMATCHED_TYPES, ASSIGN_NO_L_VALUE};
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_set_field::IrSetField;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
@ -37,9 +41,12 @@ impl AssignStatement {
|
||||
self.value.init_scopes(symbol_table, container_scope);
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for expression in [self.destination.as_ref(), self.value.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_static(symbol_table);
|
||||
@ -57,9 +64,9 @@ impl AssignStatement {
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
initialized_fields: &mut HashSet<Rc<str>>,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
@ -84,6 +91,24 @@ impl AssignStatement {
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for expression in [self.destination.as_ref(), self.value.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_method(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -100,6 +125,7 @@ impl AssignStatement {
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_method_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -116,6 +142,7 @@ impl AssignStatement {
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
[
|
||||
self.destination.check_static_fn_local_names(symbol_table),
|
||||
@ -126,6 +153,79 @@ impl AssignStatement {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
nodes_to_symbols: &NodesToSymbols,
|
||||
symbols_to_types: &SymbolsToTypes,
|
||||
) -> (NodesToTypes, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut nodes_to_types = NodesToTypes::new();
|
||||
|
||||
{
|
||||
let (nts, mut ds) = self.value.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
insert_resolved_types_into(nts, &mut nodes_to_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
{
|
||||
let (nts, mut ds) = self
|
||||
.destination
|
||||
.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
insert_resolved_types_into(nts, &mut nodes_to_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
// check that destination is L value, mutable, and assignable
|
||||
match &*self.destination {
|
||||
// must be identifier (for now)
|
||||
Expression::Identifier(identifier) => {
|
||||
let expressible_symbol = nodes_to_symbols
|
||||
.get(&identifier.node_id())
|
||||
.unwrap()
|
||||
.unwrap_expressible_symbol();
|
||||
let is_mut = match &expressible_symbol {
|
||||
ExpressibleSymbol::Field(field_symbol) => field_symbol.is_mut(),
|
||||
ExpressibleSymbol::Variable(variable_symbol) => variable_symbol.is_mut(),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
// check mut
|
||||
if !is_mut {
|
||||
diagnostics.push(destination_must_be_mutable(
|
||||
self.destination.source_range(),
|
||||
expressible_symbol.source_range(),
|
||||
));
|
||||
}
|
||||
|
||||
let maybe_expressible_symbol_source_range =
|
||||
expressible_symbol.source_range().cloned();
|
||||
|
||||
let lhs_type = symbols_to_types
|
||||
.get(&expressible_symbol.into_symbol())
|
||||
.unwrap();
|
||||
let rhs_type = nodes_to_types.get(&self.value.node_id()).unwrap();
|
||||
|
||||
// check assignable
|
||||
if !lhs_type.is_assignable_from(rhs_type) {
|
||||
diagnostics.push(mismatched_assign_types(
|
||||
rhs_type,
|
||||
lhs_type,
|
||||
&SourceRange::new(
|
||||
self.destination.source_range().start(),
|
||||
self.value.source_range().end(),
|
||||
),
|
||||
maybe_expressible_symbol_source_range.as_ref(),
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
diagnostics.push(must_be_l_value(self.destination.source_range()));
|
||||
}
|
||||
}
|
||||
|
||||
(nodes_to_types, diagnostics)
|
||||
}
|
||||
|
||||
pub fn type_check(
|
||||
&mut self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::helpers::{insert_resolved_names_into, insert_resolved_types_into};
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::error_codes::BINARY_INCOMPATIBLE_TYPES;
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
@ -33,6 +33,7 @@ pub enum BinaryOperation {
|
||||
}
|
||||
|
||||
pub struct BinaryExpression {
|
||||
node_id: NodeId,
|
||||
lhs: Box<Expression>,
|
||||
rhs: Box<Expression>,
|
||||
op: BinaryOperation,
|
||||
@ -42,12 +43,14 @@ pub struct BinaryExpression {
|
||||
|
||||
impl BinaryExpression {
|
||||
pub fn new(
|
||||
node_id: NodeId,
|
||||
lhs: Expression,
|
||||
rhs: Expression,
|
||||
op: BinaryOperation,
|
||||
source_range: SourceRange,
|
||||
) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
lhs: lhs.into(),
|
||||
rhs: rhs.into(),
|
||||
op,
|
||||
@ -56,6 +59,10 @@ impl BinaryExpression {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn lhs(&self) -> &Expression {
|
||||
&self.lhs
|
||||
}
|
||||
@ -81,9 +88,12 @@ impl BinaryExpression {
|
||||
self.rhs.init_scopes(symbol_table, container_scope);
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for expression in [self.lhs.as_ref(), self.rhs.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_static(symbol_table);
|
||||
@ -98,9 +108,9 @@ impl BinaryExpression {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for expression in [self.lhs.as_ref(), self.rhs.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_field_init(symbol_table, self_class_symbol);
|
||||
@ -115,9 +125,9 @@ impl BinaryExpression {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for expression in [self.lhs.as_ref(), self.rhs.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_ctor(symbol_table, self_class_symbol);
|
||||
@ -128,6 +138,24 @@ impl BinaryExpression {
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for expression in [self.lhs.as_ref(), self.rhs.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_method(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_field_initializer_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -144,6 +172,7 @@ impl BinaryExpression {
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -160,6 +189,7 @@ impl BinaryExpression {
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_method_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -176,6 +206,7 @@ impl BinaryExpression {
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
[
|
||||
self.lhs.check_static_fn_local_names(symbol_table),
|
||||
@ -186,6 +217,124 @@ impl BinaryExpression {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn resolve_op_result(
|
||||
&self,
|
||||
nodes_to_types: &NodesToTypes,
|
||||
op_compatibility_check: impl Fn(&TypeInfo, &TypeInfo) -> bool,
|
||||
get_op_result: impl Fn(&TypeInfo, &TypeInfo) -> TypeInfo,
|
||||
lazy_diagnostic_message: impl Fn(&TypeInfo, &TypeInfo) -> String,
|
||||
) -> (TypeInfo, Diagnostics) {
|
||||
let lhs_type_info = nodes_to_types.get(&self.lhs.node_id()).unwrap();
|
||||
let rhs_type_info = nodes_to_types.get(&self.rhs.node_id()).unwrap();
|
||||
|
||||
if op_compatibility_check(lhs_type_info, rhs_type_info) {
|
||||
let op_result = get_op_result(lhs_type_info, rhs_type_info);
|
||||
(op_result, Diagnostics::new())
|
||||
} else {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
diagnostics.push(
|
||||
Diagnostic::new(
|
||||
&lazy_diagnostic_message(lhs_type_info, rhs_type_info),
|
||||
self.source_range.start(),
|
||||
self.source_range.end(),
|
||||
)
|
||||
.with_error_code(BINARY_INCOMPATIBLE_TYPES),
|
||||
);
|
||||
(TypeInfo::PlaceholderError, diagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
nodes_to_symbols: &NodesToSymbols,
|
||||
symbols_to_types: &SymbolsToTypes,
|
||||
) -> (NodesToTypes, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut nodes_to_types = NodesToTypes::new();
|
||||
|
||||
{
|
||||
let (nts, mut ds) = self.lhs.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
insert_resolved_types_into(nts, &mut nodes_to_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
{
|
||||
let (nts, mut ds) = self.rhs.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
insert_resolved_types_into(nts, &mut nodes_to_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
{
|
||||
let (result_type_info, mut ds) = match &self.op {
|
||||
BinaryOperation::Multiply => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_multiply(rhs),
|
||||
|lhs, rhs| lhs.multiply_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot multiply {} by {}", lhs, rhs),
|
||||
),
|
||||
BinaryOperation::Divide => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_divide(rhs),
|
||||
|lhs, rhs| lhs.divide_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot divide {} by {}", lhs, rhs),
|
||||
),
|
||||
BinaryOperation::Modulo => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_modulo(rhs),
|
||||
|lhs, rhs| lhs.modulo_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot modulo {} by {}", lhs, rhs),
|
||||
),
|
||||
BinaryOperation::Add => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_add(rhs),
|
||||
|lhs, rhs| lhs.add_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot add {} and {}", lhs, rhs),
|
||||
),
|
||||
BinaryOperation::Subtract => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_subtract(rhs),
|
||||
|lhs, rhs| lhs.subtract_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot subtract {} from {}", rhs, lhs), // n.b. order
|
||||
),
|
||||
BinaryOperation::LeftShift => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_left_shift(rhs),
|
||||
|lhs, rhs| lhs.left_shift_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot left shift {} by {}", lhs, rhs),
|
||||
),
|
||||
BinaryOperation::RightShift => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_right_shift(rhs),
|
||||
|lhs, rhs| lhs.right_shift_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot right shift {} by {}", lhs, rhs),
|
||||
),
|
||||
BinaryOperation::BitwiseAnd => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_bitwise_and(rhs),
|
||||
|lhs, rhs| lhs.bitwise_and_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot bitwise-and {} by {}", lhs, rhs),
|
||||
),
|
||||
BinaryOperation::BitwiseXor => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_bitwise_xor(rhs),
|
||||
|lhs, rhs| lhs.bitwise_xor_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot bitwise-xor {} by {}", lhs, rhs),
|
||||
),
|
||||
BinaryOperation::BitwiseOr => self.resolve_op_result(
|
||||
&nodes_to_types,
|
||||
|lhs, rhs| lhs.can_bitwise_or(rhs),
|
||||
|lhs, rhs| lhs.bitwise_or_result(rhs),
|
||||
|lhs, rhs| format!("Incompatible types: cannot bitwise-or {} by {}", lhs, rhs),
|
||||
),
|
||||
};
|
||||
|
||||
nodes_to_types.insert(self.node_id, result_type_info);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(nodes_to_types, diagnostics)
|
||||
}
|
||||
|
||||
fn check_op(
|
||||
&mut self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::fqn_util::fqn_parts_to_string;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::helpers::{insert_resolved_names_into, insert_resolved_types_into};
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostic_factories::class_has_no_constructor;
|
||||
use crate::diagnostic_factories::{
|
||||
class_has_no_constructor, mismatched_types, receiver_not_callable, wrong_number_of_arguments,
|
||||
};
|
||||
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::class_symbol::ClassSymbol;
|
||||
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||
@ -16,20 +19,31 @@ use crate::type_info::TypeInfo;
|
||||
use crate::types_table::TypesTable;
|
||||
|
||||
pub struct Call {
|
||||
node_id: NodeId,
|
||||
callee: Box<Expression>,
|
||||
arguments: Vec<Expression>,
|
||||
source_range: SourceRange,
|
||||
}
|
||||
|
||||
impl Call {
|
||||
pub fn new(callee: Expression, arguments: Vec<Expression>, source_range: SourceRange) -> Self {
|
||||
pub fn new(
|
||||
node_id: NodeId,
|
||||
callee: Expression,
|
||||
arguments: Vec<Expression>,
|
||||
source_range: SourceRange,
|
||||
) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
callee: callee.into(),
|
||||
arguments,
|
||||
source_range,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn callee(&self) -> &Expression {
|
||||
&self.callee
|
||||
}
|
||||
@ -45,9 +59,12 @@ impl Call {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self.callee.resolve_names_static(symbol_table);
|
||||
@ -68,9 +85,9 @@ impl Call {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
@ -93,9 +110,9 @@ impl Call {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
@ -114,6 +131,32 @@ impl Call {
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut nodes_to_symbols = NodesToSymbols::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
.callee
|
||||
.resolve_names_method(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut nodes_to_symbols);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
for argument in &self.arguments {
|
||||
let (ns, mut ds) = argument.resolve_names_method(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut nodes_to_symbols);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(nodes_to_symbols, diagnostics)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_field_initializer_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -132,6 +175,7 @@ impl Call {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -150,6 +194,7 @@ impl Call {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_method_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -167,6 +212,7 @@ impl Call {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = Vec::new();
|
||||
for argument in &self.arguments {
|
||||
@ -176,6 +222,88 @@ impl Call {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
nodes_to_symbols: &NodesToSymbols,
|
||||
symbols_to_types: &SymbolsToTypes,
|
||||
) -> (NodesToTypes, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut nodes_to_types = NodesToTypes::new();
|
||||
|
||||
{
|
||||
let (nts, mut ds) = self
|
||||
.callee
|
||||
.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
insert_resolved_types_into(nts, &mut nodes_to_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
for argument in &self.arguments {
|
||||
let (nts, mut ds) = argument.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
insert_resolved_types_into(nts, &mut nodes_to_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
// get callee symbol and check that its callable
|
||||
let callee_symbol = nodes_to_symbols.get(&self.callee.node_id()).unwrap();
|
||||
let callable_symbol = match callee_symbol {
|
||||
Symbol::Class(class_symbol) => match class_symbol.constructor_symbol_owned() {
|
||||
None => {
|
||||
diagnostics.push(class_has_no_constructor(
|
||||
class_symbol.declared_name(),
|
||||
self.callee.source_range(),
|
||||
));
|
||||
CallableSymbol::ErrorPlaceholder
|
||||
}
|
||||
Some(constructor_symbol) => CallableSymbol::Constructor(constructor_symbol),
|
||||
},
|
||||
Symbol::Function(function_symbol) => CallableSymbol::Function(function_symbol.clone()),
|
||||
_ => {
|
||||
diagnostics.push(receiver_not_callable(
|
||||
symbols_to_types.get(&callee_symbol).unwrap(),
|
||||
self.callee.source_range(),
|
||||
));
|
||||
CallableSymbol::ErrorPlaceholder
|
||||
}
|
||||
};
|
||||
|
||||
let parameter_symbols = callable_symbol.parameters();
|
||||
|
||||
// check args length
|
||||
if parameter_symbols.len() != self.arguments().len() {
|
||||
diagnostics.push(wrong_number_of_arguments(
|
||||
self.source_range(),
|
||||
parameter_symbols.len(),
|
||||
self.arguments().len(),
|
||||
));
|
||||
}
|
||||
|
||||
// check arg types
|
||||
for i in 0..parameter_symbols.len() {
|
||||
let parameter_symbol = parameter_symbols[i].clone();
|
||||
let argument = if i < self.arguments.len() {
|
||||
&self.arguments[i]
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let parameter_type_info = symbols_to_types
|
||||
.get(&Symbol::Parameter(parameter_symbol))
|
||||
.unwrap();
|
||||
let argument_type_info = nodes_to_types.get(&argument.node_id()).unwrap();
|
||||
if !parameter_type_info.is_assignable_from(argument_type_info) {
|
||||
diagnostics.push(mismatched_types(
|
||||
parameter_type_info,
|
||||
argument_type_info,
|
||||
argument.source_range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: insert self type (i.e., the return type of the call)
|
||||
|
||||
(nodes_to_types, diagnostics)
|
||||
}
|
||||
|
||||
pub fn type_check(
|
||||
&mut self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -303,6 +431,7 @@ impl Call {
|
||||
.constructor_return_types()
|
||||
.get(&constructor_symbol)
|
||||
.unwrap(),
|
||||
CallableSymbol::ErrorPlaceholder => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,6 +464,7 @@ impl Call {
|
||||
arguments,
|
||||
false,
|
||||
),
|
||||
CallableSymbol::ErrorPlaceholder => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ use crate::ast::helpers::{
|
||||
resolve_ctor_name,
|
||||
};
|
||||
use crate::ast::statement::Statement;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::ast::{NodeId, NodesToSymbols};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::error_codes::{FIELD_MULTIPLE_INIT, FIELD_UNINIT};
|
||||
use crate::ir::ir_class::{IrClass, IrField};
|
||||
@ -94,7 +94,7 @@ impl Class {
|
||||
symbol_table.pop_scope();
|
||||
}
|
||||
|
||||
pub fn make_symbols(&self, fqn_context: &FqnContext) -> Vec<Symbol> {
|
||||
pub fn declared_symbols(&self, fqn_context: &FqnContext) -> Vec<Symbol> {
|
||||
let mut all_symbols: Vec<Symbol> = Vec::new();
|
||||
|
||||
let mut generic_parameter_symbols = Vec::new();
|
||||
@ -133,7 +133,7 @@ impl Class {
|
||||
let mut function_symbols = Vec::new();
|
||||
for function in &self.functions {
|
||||
let (function_symbol, mut symbols) =
|
||||
function.make_symbols(&class_body_fqn_context, true);
|
||||
function.declared_symbols(&class_body_fqn_context, true);
|
||||
all_symbols.append(&mut symbols);
|
||||
function_symbols.push(function_symbol);
|
||||
}
|
||||
@ -154,9 +154,9 @@ impl Class {
|
||||
all_symbols
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &mut SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names(&self, symbol_table: &mut SymbolTable) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for generic_parameter in &self.generic_parameters {
|
||||
let (ns, mut ds) = generic_parameter.resolve_names(symbol_table);
|
||||
|
||||
@ -2,15 +2,17 @@ use crate::ast::class::Class;
|
||||
use crate::ast::extern_function::ExternFunction;
|
||||
use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::function::Function;
|
||||
use crate::ast::helpers::{collect_diagnostics_into_mut, insert_resolved_types_into};
|
||||
use crate::ast::{NamesTable, ResolvedTypes};
|
||||
use crate::ast::helpers::{
|
||||
collect_diagnostics_into_mut, insert_declared_types_into, insert_resolved_types_into,
|
||||
};
|
||||
use crate::ast::{NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::compile_pipeline::FileId;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_class::IrClass;
|
||||
use crate::ir::ir_function::IrFunction;
|
||||
use crate::symbol::Symbol;
|
||||
use crate::symbol_table::util::try_insert_symbols_into;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
use crate::symbol_table::util::try_insert_symbols_into;
|
||||
use crate::types_table::TypesTable;
|
||||
use crate::{diagnostics_result, handle_diagnostics};
|
||||
|
||||
@ -62,20 +64,20 @@ impl CompilationUnit {
|
||||
symbol_table.pop_scope();
|
||||
}
|
||||
|
||||
pub fn gather_unordered_symbols(&self) -> Vec<Symbol> {
|
||||
pub fn declared_symbols(&self) -> Vec<Symbol> {
|
||||
let fqn_context = FqnContext::new();
|
||||
[
|
||||
self.classes
|
||||
.iter()
|
||||
.flat_map(|class| class.make_symbols(&fqn_context))
|
||||
.flat_map(|class| class.declared_symbols(&fqn_context))
|
||||
.collect::<Vec<_>>(),
|
||||
self.extern_functions
|
||||
.iter()
|
||||
.flat_map(|function| function.make_symbols(&fqn_context).1)
|
||||
.flat_map(|function| function.declared_symbols(&fqn_context).1)
|
||||
.collect(),
|
||||
self.functions
|
||||
.iter()
|
||||
.flat_map(|function| function.make_symbols(&fqn_context, false).1)
|
||||
.flat_map(|function| function.declared_symbols(&fqn_context, false).1)
|
||||
.collect(),
|
||||
]
|
||||
.into_iter()
|
||||
@ -92,24 +94,24 @@ impl CompilationUnit {
|
||||
let fqn_context = FqnContext::new();
|
||||
for class in &self.classes {
|
||||
handle_diagnostics!(
|
||||
try_insert_symbols_into(class.make_symbols(&fqn_context), symbol_table),
|
||||
try_insert_symbols_into(class.declared_symbols(&fqn_context), symbol_table),
|
||||
diagnostics
|
||||
);
|
||||
}
|
||||
for function in &self.functions {
|
||||
let (_, symbols) = function.make_symbols(&fqn_context, false);
|
||||
let (_, symbols) = function.declared_symbols(&fqn_context, false);
|
||||
handle_diagnostics!(try_insert_symbols_into(symbols, symbol_table), diagnostics);
|
||||
}
|
||||
for extern_function in &self.extern_functions {
|
||||
let (_, symbols) = extern_function.make_symbols(&fqn_context);
|
||||
let (_, symbols) = extern_function.declared_symbols(&fqn_context);
|
||||
handle_diagnostics!(try_insert_symbols_into(symbols, symbol_table), diagnostics);
|
||||
}
|
||||
diagnostics_result!(diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &mut SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names(&self, symbol_table: &mut SymbolTable) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for function in &self.functions {
|
||||
let (ns, mut ds) = function.resolve_names_static(symbol_table);
|
||||
@ -156,19 +158,41 @@ impl CompilationUnit {
|
||||
diagnostics_result!(diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_types(&self, names_table: &NamesTable) -> (ResolvedTypes, Diagnostics) {
|
||||
/// Associate each declared symbol with a TypeInfo.
|
||||
pub fn declared_types(&self, names_table: &NodesToSymbols) -> (SymbolsToTypes, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut resolved_types = ResolvedTypes::new();
|
||||
let mut declared_types = SymbolsToTypes::new();
|
||||
|
||||
for function in &self.functions {
|
||||
let (ts, mut ds) = todo!();
|
||||
insert_resolved_types_into(ts, &mut resolved_types);
|
||||
let (dts, mut ds) = function.declared_types(names_table);
|
||||
insert_declared_types_into(dts, &mut declared_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(resolved_types, diagnostics)
|
||||
|
||||
(declared_types, diagnostics)
|
||||
}
|
||||
|
||||
|
||||
/// Resolve types of all nodes that have an implicit (perhaps not declared) type, checking that
|
||||
/// things are assignable, etc., along the way.
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
names_table: &NodesToSymbols,
|
||||
symbols_to_types: &SymbolsToTypes,
|
||||
) -> (SymbolsToTypes, NodesToTypes, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut resolved_types = NodesToTypes::new();
|
||||
let mut symbols_to_types = symbols_to_types.clone();
|
||||
|
||||
for function in &self.functions {
|
||||
let (sts, nts, mut ds) = function.resolve_types(names_table, &symbols_to_types);
|
||||
insert_declared_types_into(sts, &mut symbols_to_types);
|
||||
insert_resolved_types_into(nts, &mut resolved_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(symbols_to_types, resolved_types, diagnostics)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn gather_types_into(
|
||||
&self,
|
||||
@ -192,6 +216,7 @@ impl CompilationUnit {
|
||||
diagnostics_result!(diagnostics)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn type_check(
|
||||
&mut self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -220,6 +245,10 @@ impl CompilationUnit {
|
||||
diagnostics_result!(diagnostics)
|
||||
}
|
||||
|
||||
pub fn lower(&self, resolved_types: &NodesToTypes) -> (Vec<IrClass>, Vec<IrFunction>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn to_ir(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::NodesToSymbols;
|
||||
use crate::ast::field::Field;
|
||||
use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::fqn_util::fqn_parts_to_string;
|
||||
@ -103,9 +103,9 @@ impl Constructor {
|
||||
symbol_table: &mut SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
initialized_fields: &mut HashSet<Rc<str>>,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for parameter in &self.parameters {
|
||||
let (ns, mut ds) = parameter.resolve_names(symbol_table);
|
||||
|
||||
@ -1,22 +1,29 @@
|
||||
use crate::ast::NodeId;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::type_info::TypeInfo;
|
||||
|
||||
pub struct DoubleLiteral {
|
||||
node_id: NodeId,
|
||||
value: f64,
|
||||
source_range: SourceRange,
|
||||
type_info: &'static TypeInfo,
|
||||
}
|
||||
|
||||
impl DoubleLiteral {
|
||||
pub fn new(value: f64, source_range: SourceRange) -> Self {
|
||||
pub fn new(node_id: NodeId, value: f64, source_range: SourceRange) -> Self {
|
||||
const TYPE_INFO: TypeInfo = TypeInfo::Double;
|
||||
Self {
|
||||
node_id,
|
||||
value,
|
||||
source_range,
|
||||
type_info: &TYPE_INFO,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn value(&self) -> f64 {
|
||||
self.value
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::binary_expression::BinaryExpression;
|
||||
use crate::ast::call::Call;
|
||||
use crate::ast::double_literal::DoubleLiteral;
|
||||
@ -7,6 +6,7 @@ use crate::ast::integer_literal::IntegerLiteral;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::negative_expression::NegativeExpression;
|
||||
use crate::ast::string_literal::StringLiteral;
|
||||
use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
@ -32,6 +32,18 @@ pub enum Expression {
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => binary_expression.node_id(),
|
||||
Expression::Negative(negative_expression) => negative_expression.node_id(),
|
||||
Expression::Call(call) => call.node_id(),
|
||||
Expression::Identifier(identifier) => identifier.node_id(),
|
||||
Expression::Integer(integer_literal) => integer_literal.node_id(),
|
||||
Expression::Double(double_literal) => double_literal.node_id(),
|
||||
Expression::String(string_literal) => string_literal.node_id(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
@ -50,7 +62,10 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
binary_expression.resolve_names_static(symbol_table)
|
||||
@ -60,7 +75,7 @@ impl Expression {
|
||||
}
|
||||
Expression::Call(call) => call.resolve_names_static(symbol_table),
|
||||
Expression::Identifier(identifier) => identifier.resolve_name_static(symbol_table),
|
||||
_ => (NamesTable::new(), Diagnostics::new()),
|
||||
_ => (NodesToSymbols::new(), Diagnostics::new()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +83,7 @@ impl Expression {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
binary_expression.resolve_names_field_init(symbol_table, self_class_symbol)
|
||||
@ -82,7 +97,7 @@ impl Expression {
|
||||
Expression::Identifier(identifier) => {
|
||||
identifier.resolve_name_field_init(symbol_table, self_class_symbol)
|
||||
}
|
||||
_ => (NamesTable::new(), Diagnostics::new()),
|
||||
_ => (NodesToSymbols::new(), Diagnostics::new()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +105,7 @@ impl Expression {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
binary_expression.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
@ -102,10 +117,31 @@ impl Expression {
|
||||
Expression::Identifier(identifier) => {
|
||||
identifier.resolve_name_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
_ => (NamesTable::new(), Diagnostics::new()),
|
||||
_ => (NodesToSymbols::new(), Diagnostics::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
binary_expression.resolve_names_method(symbol_table, self_class_symbol)
|
||||
}
|
||||
Expression::Negative(negative_expression) => {
|
||||
negative_expression.resolve_names_method(symbol_table, self_class_symbol)
|
||||
}
|
||||
Expression::Call(call) => call.resolve_names_method(symbol_table, self_class_symbol),
|
||||
Expression::Identifier(identifier) => {
|
||||
identifier.resolve_name_method(symbol_table, self_class_symbol)
|
||||
}
|
||||
_ => (NodesToSymbols::new(), Diagnostics::new()),
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_field_initializer_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -134,6 +170,7 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_constructor_destination_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -162,6 +199,7 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -190,6 +228,7 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_method_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -216,6 +255,7 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
@ -244,6 +284,43 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
nodes_to_symbols: &NodesToSymbols,
|
||||
symbols_to_types: &SymbolsToTypes,
|
||||
) -> (NodesToTypes, Diagnostics) {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
binary_expression.resolve_types(nodes_to_symbols, symbols_to_types)
|
||||
}
|
||||
Expression::Negative(negative_expression) => {
|
||||
negative_expression.resolve_types(nodes_to_symbols, symbols_to_types)
|
||||
}
|
||||
Expression::Call(call) => call.resolve_types(nodes_to_symbols, symbols_to_types),
|
||||
Expression::Identifier(identifier) => {
|
||||
identifier.resolve_type(nodes_to_symbols, symbols_to_types)
|
||||
}
|
||||
Expression::Integer(integer_literal) => {
|
||||
let mut resolved_types = NodesToTypes::new();
|
||||
resolved_types.insert(
|
||||
integer_literal.node_id(),
|
||||
integer_literal.type_info().clone(),
|
||||
);
|
||||
(resolved_types, Diagnostics::new())
|
||||
}
|
||||
Expression::Double(double_literal) => {
|
||||
let mut resolved_types = NodesToTypes::new();
|
||||
resolved_types.insert(double_literal.node_id(), double_literal.type_info().clone());
|
||||
(resolved_types, Diagnostics::new())
|
||||
}
|
||||
Expression::String(string_literal) => {
|
||||
let mut resolved_types = NodesToTypes::new();
|
||||
resolved_types.insert(string_literal.node_id(), string_literal.type_info().clone());
|
||||
(resolved_types, Diagnostics::new())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_check(
|
||||
&mut self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_return::IrReturn;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
@ -10,12 +10,14 @@ use crate::type_info::TypeInfo;
|
||||
use crate::types_table::TypesTable;
|
||||
|
||||
pub struct ExpressionStatement {
|
||||
node_id: NodeId,
|
||||
expression: Box<Expression>,
|
||||
}
|
||||
|
||||
impl ExpressionStatement {
|
||||
pub fn new(expression: Expression) -> Self {
|
||||
pub fn new(node_id: NodeId, expression: Expression) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
expression: expression.into(),
|
||||
}
|
||||
}
|
||||
@ -28,7 +30,10 @@ impl ExpressionStatement {
|
||||
self.expression.init_scopes(symbol_table, container_scope);
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
self.expression.resolve_names_static(symbol_table)
|
||||
}
|
||||
|
||||
@ -36,11 +41,21 @@ impl ExpressionStatement {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
self.expression
|
||||
.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
self.expression
|
||||
.resolve_names_method(symbol_table, self_class_symbol)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -50,6 +65,7 @@ impl ExpressionStatement {
|
||||
.check_constructor_local_names(symbol_table, class_symbol)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_method_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -59,10 +75,30 @@ impl ExpressionStatement {
|
||||
.check_method_local_names(symbol_table, class_symbol)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
self.expression.check_static_fn_local_names(symbol_table)
|
||||
}
|
||||
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
nodes_to_symbols: &NodesToSymbols,
|
||||
symbols_to_types: &SymbolsToTypes,
|
||||
) -> (NodesToTypes, Diagnostics) {
|
||||
let (mut nodes_to_types, diagnostics) = self
|
||||
.expression
|
||||
.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
|
||||
// add self for last-statement type checking
|
||||
let expression_type_info = nodes_to_types
|
||||
.get(&self.expression.node_id())
|
||||
.cloned()
|
||||
.unwrap();
|
||||
nodes_to_types.insert(self.node_id, expression_type_info);
|
||||
|
||||
(nodes_to_types, diagnostics)
|
||||
}
|
||||
|
||||
pub fn type_check(
|
||||
&mut self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -4,7 +4,7 @@ use crate::ast::helpers::{
|
||||
};
|
||||
use crate::ast::parameter::Parameter;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::ast::{NodeId, NodesToSymbols};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::Symbol;
|
||||
@ -60,7 +60,7 @@ impl ExternFunction {
|
||||
symbol_table.pop_scope();
|
||||
}
|
||||
|
||||
pub fn make_symbols(&self, fqn_context: &FqnContext) -> (Rc<FunctionSymbol>, Vec<Symbol>) {
|
||||
pub fn declared_symbols(&self, fqn_context: &FqnContext) -> (Rc<FunctionSymbol>, Vec<Symbol>) {
|
||||
let mut all_symbols: Vec<Symbol> = Vec::new();
|
||||
|
||||
let mut parameter_symbols = Vec::new();
|
||||
@ -80,9 +80,12 @@ impl ExternFunction {
|
||||
(function_symbol, all_symbols)
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
resolve_parameter_names_into(
|
||||
&self.parameters,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::NodesToSymbols;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
@ -85,8 +85,8 @@ impl Field {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut names_table = NamesTable::new();
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
if let Some(type_use) = &self.declared_type {
|
||||
|
||||
@ -2,13 +2,14 @@ use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::fqn_util::fqn_parts_to_string;
|
||||
use crate::ast::helpers::{
|
||||
collect_diagnostics_into_enumerated_mut, collect_diagnostics_into_mut,
|
||||
collect_parameter_symbols_into, resolve_parameter_names_into,
|
||||
collect_parameter_symbols_into, insert_declared_types_into, insert_resolved_names_into,
|
||||
insert_resolved_types_into, resolve_parameter_names_into,
|
||||
};
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::parameter::Parameter;
|
||||
use crate::ast::statement::Statement;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_function::IrFunction;
|
||||
use crate::ir::ir_parameter::IrParameter;
|
||||
@ -57,6 +58,10 @@ impl Function {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn declared_name(&self) -> &str {
|
||||
&self.declared_name
|
||||
}
|
||||
@ -88,7 +93,8 @@ impl Function {
|
||||
symbol_table.pop_scope(); // function
|
||||
}
|
||||
|
||||
pub fn make_symbols(
|
||||
/// Return value contains self FunctionSymbol followed by all symbols (including self symbol).
|
||||
pub fn declared_symbols(
|
||||
&self,
|
||||
fqn_context: &FqnContext,
|
||||
is_method: bool,
|
||||
@ -112,51 +118,58 @@ impl Function {
|
||||
(function_symbol, all_symbols)
|
||||
}
|
||||
|
||||
fn resolve_names_common(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
fn resolve_names_common(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut nodes_to_symbols = NodesToSymbols::new();
|
||||
|
||||
resolve_parameter_names_into(
|
||||
&self.parameters,
|
||||
symbol_table,
|
||||
&mut names_table,
|
||||
&mut nodes_to_symbols,
|
||||
&mut diagnostics,
|
||||
);
|
||||
|
||||
if let Some(type_use) = &self.return_type {
|
||||
let (ns, mut ds) = type_use.resolve_names(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
insert_resolved_names_into(ns, &mut nodes_to_symbols);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
(nodes_to_symbols, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let (mut names_table, mut diagnostics) = self.resolve_names_common(symbol_table);
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let (mut nodes_to_symbols, mut diagnostics) = self.resolve_names_common(symbol_table);
|
||||
|
||||
for statement in &self.statements {
|
||||
let (ns, mut ds) = statement.resolve_names_static(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
insert_resolved_names_into(ns, &mut nodes_to_symbols);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
(nodes_to_symbols, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let (names_table, diagnostics) = self.resolve_names_common(symbol_table);
|
||||
pub fn resolve_names_method(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let (mut nodes_to_symbols, mut diagnostics) = self.resolve_names_common(symbol_table);
|
||||
|
||||
(names_table, diagnostics)
|
||||
for statement in &self.statements {
|
||||
let (ns, mut ds) = statement.resolve_names_method(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut nodes_to_symbols);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(nodes_to_symbols, diagnostics)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics = Vec::new();
|
||||
for parameter in &self.parameters {
|
||||
@ -168,6 +181,7 @@ impl Function {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn analyze_method_local_names(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
@ -179,6 +193,7 @@ impl Function {
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn analyze_static_fn_local_names(&self, symbol_table: &mut SymbolTable) -> Vec<Diagnostic> {
|
||||
self.statements
|
||||
.iter()
|
||||
@ -186,6 +201,41 @@ impl Function {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn declared_types(&self, names_table: &NodesToSymbols) -> (SymbolsToTypes, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut declared_types = SymbolsToTypes::new();
|
||||
|
||||
for parameter in &self.parameters {
|
||||
let symbol = names_table.get(¶meter.node_id()).unwrap();
|
||||
let (type_info, mut ds) = parameter.declared_type(names_table);
|
||||
declared_types.insert(symbol.clone(), type_info);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(declared_types, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
nodes_to_symbols: &NodesToSymbols,
|
||||
symbols_to_types: &SymbolsToTypes,
|
||||
) -> (SymbolsToTypes, NodesToTypes, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut nodes_to_types = NodesToTypes::new();
|
||||
let mut symbols_to_types = symbols_to_types.clone();
|
||||
|
||||
for statement in &self.statements {
|
||||
let (sts, nts, mut ds) = statement.resolve_types(nodes_to_symbols, &symbols_to_types);
|
||||
insert_declared_types_into(sts, &mut symbols_to_types); // merge!
|
||||
insert_resolved_types_into(nts, &mut nodes_to_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
// todo: check last statement for return type
|
||||
|
||||
(symbols_to_types, nodes_to_types, diagnostics)
|
||||
}
|
||||
|
||||
pub fn gather_types(&self, symbol_table: &SymbolTable, types_table: &mut TypesTable) {
|
||||
let function_symbol = symbol_table
|
||||
.get_function_symbol_owned(self.scope_id.unwrap(), self.declared_name())
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::NodesToSymbols;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
@ -49,9 +49,9 @@ impl GenericParameter {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
for type_use in &self.extends {
|
||||
let (ns, mut ds) = type_use.resolve_names(symbol_table);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::ast::{NamesTable, ResolvedTypes};
|
||||
use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::parameter::Parameter;
|
||||
use crate::ast::{NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostics_result;
|
||||
use crate::symbol::Symbol;
|
||||
@ -110,25 +110,31 @@ pub fn collect_parameter_symbols_into(
|
||||
pub fn resolve_parameter_names_into(
|
||||
parameters: &[Parameter],
|
||||
symbol_table: &SymbolTable,
|
||||
names_table: &mut NamesTable,
|
||||
nodes_to_symbols: &mut NodesToSymbols,
|
||||
diagnostics: &mut Diagnostics,
|
||||
) {
|
||||
for parameter in parameters {
|
||||
let (ns, mut ds) = parameter.resolve_names(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
nodes_to_symbols.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_resolved_names_into(source: NamesTable, destination: &mut NamesTable) {
|
||||
pub fn insert_resolved_names_into(source: NodesToSymbols, destination: &mut NodesToSymbols) {
|
||||
for (node_id, symbol) in source {
|
||||
destination.insert(node_id, symbol);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_resolved_types_into(source: ResolvedTypes, destination: &mut ResolvedTypes) {
|
||||
pub fn insert_declared_types_into(source: SymbolsToTypes, destination: &mut SymbolsToTypes) {
|
||||
for (symbol, type_info) in source {
|
||||
destination.insert(symbol, type_info);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_resolved_types_into(source: NodesToTypes, destination: &mut NodesToTypes) {
|
||||
for (node_id, type_info) in source {
|
||||
destination.insert(node_id, type_info);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::ir_util::get_or_init_field_pointer_variable;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostic_factories::{
|
||||
cannot_reassign_immutable_field, not_assignable, outer_class_field_usage,
|
||||
@ -43,6 +43,10 @@ impl Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
@ -55,9 +59,9 @@ impl Identifier {
|
||||
self.scope_id.unwrap()
|
||||
}
|
||||
|
||||
pub fn resolve_name_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_name_static(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
match symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name) {
|
||||
None => {
|
||||
@ -75,9 +79,9 @@ impl Identifier {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name);
|
||||
if let Some(symbol) = symbol {
|
||||
@ -125,9 +129,9 @@ impl Identifier {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name);
|
||||
if let Some(symbol) = symbol {
|
||||
@ -173,9 +177,9 @@ impl Identifier {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
initialized_fields: &mut HashSet<Rc<str>>,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
|
||||
let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name);
|
||||
if let Some(symbol) = symbol {
|
||||
@ -217,11 +221,33 @@ impl Identifier {
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_name_method(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
_self_class_symbol: &ClassSymbol, // for future when we have paths?
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut nodes_to_symbols = NodesToSymbols::new();
|
||||
|
||||
let maybe_expressible_symbol =
|
||||
symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name);
|
||||
match maybe_expressible_symbol {
|
||||
None => {
|
||||
diagnostics.push(symbol_not_found(&self.name, &self.source_range));
|
||||
}
|
||||
Some(expressible_symbol) => {
|
||||
nodes_to_symbols.insert(self.node_id, expressible_symbol.into_symbol());
|
||||
}
|
||||
}
|
||||
|
||||
(nodes_to_symbols, diagnostics)
|
||||
}
|
||||
|
||||
fn init_referring_to_class(
|
||||
&self,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
class_symbol: &Rc<ClassSymbol>,
|
||||
names_table: &mut NamesTable,
|
||||
names_table: &mut NodesToSymbols,
|
||||
diagnostics: &mut Diagnostics,
|
||||
) {
|
||||
// Check against recursively constructing this class.
|
||||
@ -254,7 +280,7 @@ impl Identifier {
|
||||
&self,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
function_symbol: &Rc<FunctionSymbol>,
|
||||
names_table: &mut NamesTable,
|
||||
names_table: &mut NodesToSymbols,
|
||||
diagnostics: &mut Diagnostics,
|
||||
) {
|
||||
if self_class_symbol
|
||||
@ -356,6 +382,7 @@ impl Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_constructor_destination_name(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -390,6 +417,7 @@ impl Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_constructor_local_name(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -415,6 +443,7 @@ impl Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_method_local_name(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -462,6 +491,7 @@ impl Identifier {
|
||||
}
|
||||
|
||||
/// WARNING: this is not appropriate (yet) for class static functions.
|
||||
#[deprecated]
|
||||
pub fn check_static_fn_local_name(&self, symbol_table: &SymbolTable) -> Option<Diagnostic> {
|
||||
if symbol_table
|
||||
.find_expressible_symbol(self.scope_id.unwrap(), &self.name)
|
||||
@ -477,6 +507,20 @@ impl Identifier {
|
||||
&self.source_range
|
||||
}
|
||||
|
||||
pub fn resolve_type(
|
||||
&self,
|
||||
resolved_symbols: &NodesToSymbols,
|
||||
resolved_symbol_type_infos: &SymbolsToTypes,
|
||||
) -> (NodesToTypes, Diagnostics) {
|
||||
let self_symbol = resolved_symbols.get(&self.node_id).unwrap();
|
||||
let type_info = resolved_symbol_type_infos.get(self_symbol).unwrap();
|
||||
|
||||
let mut resolved_types = NodesToTypes::new();
|
||||
resolved_types.insert(self.node_id, type_info.clone());
|
||||
|
||||
(resolved_types, Diagnostics::new())
|
||||
}
|
||||
|
||||
pub fn type_info<'a>(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
use crate::ast::NodeId;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::type_info::TypeInfo;
|
||||
|
||||
pub struct IntegerLiteral {
|
||||
node_id: NodeId,
|
||||
value: i32,
|
||||
source_range: SourceRange,
|
||||
type_info: &'static TypeInfo,
|
||||
}
|
||||
|
||||
impl IntegerLiteral {
|
||||
pub fn new(value: i32, source_range: SourceRange) -> Self {
|
||||
pub fn new(node_id: NodeId, value: i32, source_range: SourceRange) -> Self {
|
||||
const TYPE_INFO: TypeInfo = TypeInfo::Integer;
|
||||
Self {
|
||||
node_id,
|
||||
value,
|
||||
source_range,
|
||||
type_info: &TYPE_INFO,
|
||||
@ -21,6 +24,10 @@ impl IntegerLiteral {
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn type_info(&self) -> &TypeInfo {
|
||||
&self.type_info
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::helpers::{insert_resolved_names_into, insert_resolved_types_into};
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
@ -18,6 +18,7 @@ use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct LetStatement {
|
||||
node_id: NodeId,
|
||||
declared_name: Rc<str>,
|
||||
declared_name_source_range: SourceRange,
|
||||
is_mut: bool,
|
||||
@ -27,12 +28,14 @@ pub struct LetStatement {
|
||||
|
||||
impl LetStatement {
|
||||
pub fn new(
|
||||
node_id: NodeId,
|
||||
declared_name: &str,
|
||||
declared_name_source_range: SourceRange,
|
||||
is_mut: bool,
|
||||
initializer: Expression,
|
||||
) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
declared_name: declared_name.into(),
|
||||
declared_name_source_range,
|
||||
is_mut,
|
||||
@ -78,8 +81,8 @@ impl LetStatement {
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut names_table = NamesTable::new();
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut names_table = NodesToSymbols::new();
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
{
|
||||
@ -99,15 +102,15 @@ impl LetStatement {
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut names_table = NamesTable::new();
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut nodes_to_symbols = NodesToSymbols::new();
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
.initializer
|
||||
.resolve_names_ctor(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
insert_resolved_names_into(ns, &mut nodes_to_symbols);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
@ -115,9 +118,33 @@ impl LetStatement {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
(nodes_to_symbols, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut nodes_to_symbols = NodesToSymbols::new();
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
.initializer
|
||||
.resolve_names_method(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut nodes_to_symbols);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
if let Some(diagnostic) = self.make_and_insert_variable_symbol(symbol_table) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
(nodes_to_symbols, diagnostics)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn analyze_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
@ -136,6 +163,7 @@ impl LetStatement {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn analyze_method_local_names(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
@ -153,6 +181,7 @@ impl LetStatement {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn analyze_static_fn_local_names(&self, symbol_table: &mut SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics = Vec::new();
|
||||
diagnostics.append(&mut self.initializer.check_static_fn_local_names(symbol_table));
|
||||
@ -162,17 +191,29 @@ impl LetStatement {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
pub fn gather_local_type(&self, symbol_table: &SymbolTable, types_table: &mut TypesTable) {
|
||||
let initializer_type_info = self
|
||||
.initializer
|
||||
.type_info(symbol_table, types_table)
|
||||
.clone();
|
||||
let variable_symbol = symbol_table
|
||||
.get_variable_symbol_owned(self.scope_id.unwrap(), &self.declared_name)
|
||||
.unwrap();
|
||||
types_table
|
||||
.variable_types_mut()
|
||||
.insert(variable_symbol, initializer_type_info);
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
resolved_symbols: &NodesToSymbols,
|
||||
resolved_symbol_type_infos: &SymbolsToTypes,
|
||||
) -> (SymbolsToTypes, NodesToTypes, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut resolved_types = NodesToTypes::new();
|
||||
|
||||
{
|
||||
let (rts, mut ds) = self
|
||||
.initializer
|
||||
.resolve_types(resolved_symbols, resolved_symbol_type_infos);
|
||||
insert_resolved_types_into(rts, &mut resolved_types);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
let initializer_resolved_type = resolved_types.get(&self.initializer.node_id()).unwrap();
|
||||
let self_symbol = resolved_symbols.get(&self.node_id).unwrap();
|
||||
|
||||
let mut resolved_symbol_type_infos = resolved_symbol_type_infos.clone();
|
||||
resolved_symbol_type_infos.insert(self_symbol.clone(), initializer_resolved_type.clone());
|
||||
|
||||
(resolved_symbol_type_infos, resolved_types, diagnostics)
|
||||
}
|
||||
|
||||
pub fn type_check(
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::symbol::Symbol;
|
||||
use std::collections::HashMap;
|
||||
use crate::type_info::TypeInfo;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub mod assign_statement;
|
||||
pub mod binary_expression;
|
||||
@ -31,5 +31,6 @@ pub mod string_literal;
|
||||
pub mod type_use;
|
||||
|
||||
pub type NodeId = usize;
|
||||
pub type NamesTable = HashMap<NodeId, Symbol>;
|
||||
pub type ResolvedTypes = HashMap<NodeId, TypeInfo>;
|
||||
pub type NodesToSymbols = HashMap<NodeId, Symbol>;
|
||||
pub type SymbolsToTypes = HashMap<Symbol, TypeInfo>;
|
||||
pub type NodesToTypes = HashMap<NodeId, TypeInfo>;
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::{NodeId, NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostic_factories::unary_incompatible_type;
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
@ -17,20 +18,26 @@ use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct NegativeExpression {
|
||||
node_id: NodeId,
|
||||
operand: Box<Expression>,
|
||||
source_range: SourceRange,
|
||||
type_info: Option<TypeInfo>,
|
||||
}
|
||||
|
||||
impl NegativeExpression {
|
||||
pub fn new(operand: Expression, source_range: SourceRange) -> Self {
|
||||
pub fn new(node_id: NodeId, operand: Expression, source_range: SourceRange) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
operand: operand.into(),
|
||||
source_range,
|
||||
type_info: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn source_range(&self) -> &SourceRange {
|
||||
&self.source_range
|
||||
}
|
||||
@ -47,7 +54,10 @@ impl NegativeExpression {
|
||||
self.operand.init_scopes(symbol_table, container_scope);
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
self.operand.resolve_names_static(symbol_table)
|
||||
}
|
||||
|
||||
@ -55,7 +65,7 @@ impl NegativeExpression {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
self.operand
|
||||
.resolve_names_field_init(symbol_table, self_class_symbol)
|
||||
}
|
||||
@ -64,11 +74,21 @@ impl NegativeExpression {
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
self.operand
|
||||
.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
self.operand
|
||||
.resolve_names_method(symbol_table, self_class_symbol)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_field_initializer_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -78,6 +98,7 @@ impl NegativeExpression {
|
||||
.check_field_initializer_names(symbol_table, class_symbol)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -87,6 +108,7 @@ impl NegativeExpression {
|
||||
.check_constructor_local_names(symbol_table, class_symbol)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_method_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -96,10 +118,35 @@ impl NegativeExpression {
|
||||
.check_method_local_names(symbol_table, class_symbol)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
self.operand.check_static_fn_local_names(symbol_table)
|
||||
}
|
||||
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
nodes_to_symbols: &NodesToSymbols,
|
||||
symbols_to_types: &SymbolsToTypes,
|
||||
) -> (NodesToTypes, Diagnostics) {
|
||||
let (mut nodes_to_types, mut diagnostics) = self
|
||||
.operand
|
||||
.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
|
||||
let type_info = nodes_to_types.get(&self.operand.node_id()).unwrap();
|
||||
if type_info.can_negate() {
|
||||
nodes_to_types.insert(self.node_id, type_info.negate_result());
|
||||
} else {
|
||||
diagnostics.push(unary_incompatible_type(
|
||||
&self.source_range,
|
||||
"negation",
|
||||
type_info,
|
||||
));
|
||||
nodes_to_types.insert(self.node_id, TypeInfo::PlaceholderError);
|
||||
}
|
||||
|
||||
(nodes_to_types, diagnostics)
|
||||
}
|
||||
|
||||
pub fn type_check(
|
||||
&mut self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::ast::{NodeId, NodesToSymbols};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
use crate::type_info::TypeInfo;
|
||||
use crate::types_table::TypesTable;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Parameter {
|
||||
node_id: NodeId,
|
||||
declared_name: Rc<str>,
|
||||
declared_name_source_range: SourceRange,
|
||||
type_use: TypeUse,
|
||||
@ -16,11 +18,13 @@ pub struct Parameter {
|
||||
|
||||
impl Parameter {
|
||||
pub fn new(
|
||||
node_id: NodeId,
|
||||
declared_name: &str,
|
||||
declared_name_source_range: SourceRange,
|
||||
type_use: TypeUse,
|
||||
) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
declared_name: declared_name.into(),
|
||||
declared_name_source_range,
|
||||
type_use,
|
||||
@ -28,6 +32,10 @@ impl Parameter {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn declared_name(&self) -> &str {
|
||||
&self.declared_name
|
||||
}
|
||||
@ -49,14 +57,16 @@ impl Parameter {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) {
|
||||
self.type_use.resolve_names(symbol_table)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
self.type_use.check_names(symbol_table)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn gather_types_into(&self, symbol_table: &SymbolTable, types_table: &mut TypesTable) {
|
||||
let type_info = self.type_use.type_info(symbol_table, types_table).clone();
|
||||
let parameter_symbol = symbol_table
|
||||
@ -67,6 +77,10 @@ impl Parameter {
|
||||
.insert(parameter_symbol, type_info);
|
||||
}
|
||||
|
||||
pub fn declared_type(&self, names_table: &NodesToSymbols) -> (TypeInfo, Diagnostics) {
|
||||
self.type_use.declared_type(names_table)
|
||||
}
|
||||
|
||||
pub fn type_check(
|
||||
&mut self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::assign_statement::AssignStatement;
|
||||
use crate::ast::expression_statement::ExpressionStatement;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::let_statement::LetStatement;
|
||||
use crate::ast::{NodesToSymbols, NodesToTypes, SymbolsToTypes};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
@ -35,7 +35,7 @@ impl Statement {
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
match self {
|
||||
Statement::Let(let_statement) => let_statement.resolve_names_static(symbol_table),
|
||||
Statement::Expression(expression_statement) => {
|
||||
@ -52,7 +52,7 @@ impl Statement {
|
||||
symbol_table: &mut SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
initialized_fields: &mut HashSet<Rc<str>>,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
match self {
|
||||
Statement::Let(let_statement) => {
|
||||
let_statement.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
@ -68,6 +68,25 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NodesToSymbols, Diagnostics) {
|
||||
match self {
|
||||
Statement::Let(let_statement) => {
|
||||
let_statement.resolve_names_method(symbol_table, self_class_symbol)
|
||||
}
|
||||
Statement::Expression(expression_statement) => {
|
||||
expression_statement.resolve_names_method(symbol_table, self_class_symbol)
|
||||
}
|
||||
Statement::Assign(assign_statement) => {
|
||||
assign_statement.resolve_names_method(symbol_table, self_class_symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn analyze_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
@ -86,6 +105,7 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn analyze_method_local_names(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
@ -104,6 +124,7 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn analyze_static_fn_local_names(&self, symbol_table: &mut SymbolTable) -> Vec<Diagnostic> {
|
||||
match self {
|
||||
Statement::Let(let_statement) => {
|
||||
@ -118,6 +139,27 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_types(
|
||||
&self,
|
||||
nodes_to_symbols: &NodesToSymbols,
|
||||
symbols_to_types: &SymbolsToTypes,
|
||||
) -> (SymbolsToTypes, NodesToTypes, Diagnostics) {
|
||||
match self {
|
||||
Statement::Let(let_statement) => {
|
||||
let_statement.resolve_types(nodes_to_symbols, symbols_to_types)
|
||||
}
|
||||
Statement::Expression(expression_statement) => {
|
||||
let (nts, ds) =
|
||||
expression_statement.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
(SymbolsToTypes::new(), nts, ds)
|
||||
}
|
||||
Statement::Assign(assign_statement) => {
|
||||
let (nts, ds) = assign_statement.resolve_types(nodes_to_symbols, symbols_to_types);
|
||||
(SymbolsToTypes::new(), nts, ds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_check(
|
||||
&mut self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,22 +1,29 @@
|
||||
use crate::ast::NodeId;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::type_info::TypeInfo;
|
||||
|
||||
pub struct StringLiteral {
|
||||
node_id: NodeId,
|
||||
content: String,
|
||||
source_range: SourceRange,
|
||||
type_info: &'static TypeInfo,
|
||||
}
|
||||
|
||||
impl StringLiteral {
|
||||
pub fn new(content: &str, source_range: SourceRange) -> Self {
|
||||
pub fn new(node_id: NodeId, content: &str, source_range: SourceRange) -> Self {
|
||||
const TYPE_INFO: TypeInfo = TypeInfo::String;
|
||||
Self {
|
||||
node_id,
|
||||
content: content.into(),
|
||||
source_range,
|
||||
type_info: &TYPE_INFO,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> NodeId {
|
||||
self.node_id
|
||||
}
|
||||
|
||||
pub fn content(&self) -> &str {
|
||||
&self.content
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::ast::{NodeId, NodesToSymbols};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostic_factories::symbol_not_found;
|
||||
use crate::diagnostic_factories::{cannot_provide_generic_args_generic_type, symbol_not_found};
|
||||
use crate::error_codes::INCORRECT_GENERIC_ARGUMENTS;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::type_symbol::TypeSymbol;
|
||||
@ -46,7 +46,7 @@ impl TypeUse {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) {
|
||||
let mut diagnostics = Vec::new();
|
||||
let mut resolved_names = HashMap::new();
|
||||
|
||||
@ -75,6 +75,7 @@ impl TypeUse {
|
||||
(resolved_names, diagnostics)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = Vec::new();
|
||||
|
||||
@ -96,6 +97,7 @@ impl TypeUse {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn gather_types(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
@ -111,6 +113,36 @@ impl TypeUse {
|
||||
diagnostics_result!(diagnostics)
|
||||
}
|
||||
|
||||
pub fn declared_type(&self, names_table: &NodesToSymbols) -> (TypeInfo, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
let mut generic_argument_type_infos = Vec::new();
|
||||
for type_use in &self.generic_arguments {
|
||||
let (type_info, mut ds) = type_use.declared_type(names_table);
|
||||
generic_argument_type_infos.push(type_info);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
let base_type_symbol = names_table.get(&self.node_id).unwrap().unwrap_type_symbol();
|
||||
|
||||
match base_type_symbol {
|
||||
TypeSymbol::Class(class_symbol) => (
|
||||
TypeInfo::ParameterizedClass(class_symbol, generic_argument_type_infos),
|
||||
diagnostics,
|
||||
),
|
||||
TypeSymbol::GenericParameter(generic_parameter_symbol) => {
|
||||
if generic_argument_type_infos.is_empty() {
|
||||
(TypeInfo::GenericType(generic_parameter_symbol), diagnostics)
|
||||
} else {
|
||||
diagnostics.push(cannot_provide_generic_args_generic_type(
|
||||
&self.declared_name_source_range,
|
||||
));
|
||||
(TypeInfo::PlaceholderError, diagnostics)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_info<'a>(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -39,18 +39,39 @@ pub fn compile_compilation_units(inputs: &HashMap<FileId, &str>) -> Result<(), D
|
||||
// gather unordered symbols
|
||||
let all_symbols = compilation_units
|
||||
.values()
|
||||
.flat_map(|compilation_unit| compilation_unit.gather_unordered_symbols())
|
||||
.flat_map(|compilation_unit| compilation_unit.declared_symbols())
|
||||
.collect::<Vec<_>>();
|
||||
try_insert_symbols_into(all_symbols, &mut symbol_table)?;
|
||||
|
||||
// now we can just finish each compilation unit, since we have the symbols
|
||||
let mut diagnostics = Vec::new();
|
||||
for compilation_unit in compilation_units.values() {
|
||||
let (resolved_names, mut ds) = compilation_unit.resolve_names(&mut symbol_table);
|
||||
let (nodes_to_symbols, mut ds) = compilation_unit.resolve_names(&mut symbol_table);
|
||||
|
||||
// in the future, we'll ideally be able to *actually* continue with the following steps
|
||||
// instead of aborting here, but this needs to be tested :)
|
||||
if !ds.is_empty() {
|
||||
diagnostics.append(&mut ds);
|
||||
continue;
|
||||
}
|
||||
|
||||
let (mut symbols_to_types, mut ds) = compilation_unit.declared_types(&nodes_to_symbols);
|
||||
if !ds.is_empty() {
|
||||
diagnostics.append(&mut ds);
|
||||
continue;
|
||||
}
|
||||
|
||||
let (sts, resolved_types, mut ds) =
|
||||
compilation_unit.resolve_types(&nodes_to_symbols, &symbols_to_types);
|
||||
if !ds.is_empty() {
|
||||
diagnostics.append(&mut ds);
|
||||
continue;
|
||||
}
|
||||
|
||||
// merge
|
||||
for (symbol, type_info) in sts {
|
||||
symbols_to_types.insert(symbol, type_info);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
use crate::diagnostic::{Diagnostic, SecondaryLabel};
|
||||
use crate::error_codes::{
|
||||
ASSIGN_LHS_IMMUTABLE, CLASS_NO_CONSTRUCTOR, FIELD_NO_TYPE_OR_INIT, NOT_ASSIGNABLE,
|
||||
OUTER_CLASS_FIELD_USED_IN_INIT, OUTER_CLASS_METHOD_USED_IN_INIT, SELF_CONSTRUCTOR_USED_IN_INIT,
|
||||
ASSIGN_LHS_IMMUTABLE, ASSIGN_MISMATCHED_TYPES, ASSIGN_NO_L_VALUE,
|
||||
CANNOT_PROVIDE_GENERIC_ARGS_GENERIC_TYPE, CLASS_NO_CONSTRUCTOR, FIELD_NO_TYPE_OR_INIT,
|
||||
MISMATCHED_TYPES, NOT_ASSIGNABLE, OUTER_CLASS_FIELD_USED_IN_INIT,
|
||||
OUTER_CLASS_METHOD_USED_IN_INIT, RECEIVER_NOT_CALLABLE, SELF_CONSTRUCTOR_USED_IN_INIT,
|
||||
SELF_FIELD_USED_IN_INIT, SELF_METHOD_USED_IN_INIT, SYMBOL_ALREADY_DECLARED, SYMBOL_NOT_FOUND,
|
||||
UNARY_INCOMPATIBLE_TYPE, WRONG_NUMBER_OF_ARGUMENTS,
|
||||
};
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::Symbol;
|
||||
use crate::type_info::TypeInfo;
|
||||
|
||||
pub fn symbol_not_found(name: &str, source_range: &SourceRange) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
@ -135,3 +139,135 @@ pub fn cannot_reassign_immutable_field(source_range: &SourceRange) -> Diagnostic
|
||||
)
|
||||
.with_error_code(ASSIGN_LHS_IMMUTABLE)
|
||||
}
|
||||
|
||||
pub fn cannot_provide_generic_args_generic_type(source_range: &SourceRange) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
"Cannot provide generic arguments to an already generic type.",
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(CANNOT_PROVIDE_GENERIC_ARGS_GENERIC_TYPE)
|
||||
}
|
||||
|
||||
pub fn must_be_l_value(source_range: &SourceRange) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
"Left-hand side of assign mut be an L value",
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(ASSIGN_NO_L_VALUE)
|
||||
}
|
||||
|
||||
pub fn destination_must_be_mutable(
|
||||
source_range: &SourceRange,
|
||||
secondary_source_range: Option<&SourceRange>,
|
||||
) -> Diagnostic {
|
||||
let secondary_label = secondary_source_range.map(|sr| {
|
||||
SecondaryLabel::new(
|
||||
sr.start(),
|
||||
sr.end(),
|
||||
Some("Destination declared here is immutable".to_string()),
|
||||
)
|
||||
});
|
||||
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
"Destination is immutable and cannot be reassigned.",
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(ASSIGN_LHS_IMMUTABLE);
|
||||
|
||||
if let Some(secondary_label) = secondary_label {
|
||||
diagnostic = diagnostic.with_secondary_labels(&[secondary_label])
|
||||
}
|
||||
|
||||
diagnostic
|
||||
}
|
||||
|
||||
pub fn mismatched_assign_types(
|
||||
rhs_type: &TypeInfo,
|
||||
lhs_type: &TypeInfo,
|
||||
source_range: &SourceRange,
|
||||
secondary_source_range: Option<&SourceRange>,
|
||||
) -> Diagnostic {
|
||||
let secondary_label = secondary_source_range.map(|sr| {
|
||||
SecondaryLabel::new(
|
||||
sr.start(),
|
||||
sr.end(),
|
||||
Some(format!(
|
||||
"Destination declared here is of type {}.",
|
||||
lhs_type
|
||||
)),
|
||||
)
|
||||
});
|
||||
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
&format!("Mismatched types: right-hand side of type {} is not assignable to left-hand side of type {}", rhs_type, lhs_type),
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(ASSIGN_MISMATCHED_TYPES);
|
||||
|
||||
if let Some(secondary_label) = secondary_label {
|
||||
diagnostic = diagnostic.with_secondary_labels(&[secondary_label])
|
||||
}
|
||||
|
||||
diagnostic
|
||||
}
|
||||
|
||||
pub fn receiver_not_callable(
|
||||
receiver_type_info: &TypeInfo,
|
||||
source_range: &SourceRange,
|
||||
) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
&format!("Receiver of type {} is not callable.", receiver_type_info),
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(RECEIVER_NOT_CALLABLE)
|
||||
}
|
||||
|
||||
pub fn wrong_number_of_arguments(
|
||||
source_range: &SourceRange,
|
||||
found: usize,
|
||||
expected: usize,
|
||||
) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
&format!(
|
||||
"Wrong number of arguments: expected {} but found {}",
|
||||
expected, found
|
||||
),
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(WRONG_NUMBER_OF_ARGUMENTS)
|
||||
}
|
||||
|
||||
pub fn mismatched_types(
|
||||
expected_type_info: &TypeInfo,
|
||||
found_type_info: &TypeInfo,
|
||||
source_range: &SourceRange,
|
||||
) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
&format!(
|
||||
"Mismatched types; expected {} but found {}",
|
||||
expected_type_info, found_type_info
|
||||
),
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(MISMATCHED_TYPES)
|
||||
}
|
||||
|
||||
pub fn unary_incompatible_type(
|
||||
source_range: &SourceRange,
|
||||
operator_name: &str,
|
||||
type_info: &TypeInfo,
|
||||
) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
&format!("Cannot apply {} to {}", operator_name, type_info),
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(UNARY_INCOMPATIBLE_TYPE)
|
||||
}
|
||||
|
||||
@ -20,3 +20,8 @@ pub const OUTER_CLASS_METHOD_USED_IN_INIT: ErrorCode = 27;
|
||||
pub const FIELD_NO_TYPE_OR_INIT: ErrorCode = 28;
|
||||
pub const CLASS_NO_CONSTRUCTOR: ErrorCode = 29;
|
||||
pub const NOT_ASSIGNABLE: ErrorCode = 30;
|
||||
pub const CANNOT_PROVIDE_GENERIC_ARGS_GENERIC_TYPE: ErrorCode = 31;
|
||||
pub const RECEIVER_NOT_CALLABLE: ErrorCode = 32;
|
||||
pub const WRONG_NUMBER_OF_ARGUMENTS: ErrorCode = 33;
|
||||
pub const MISMATCHED_TYPES: ErrorCode = 34;
|
||||
pub const UNARY_INCOMPATIBLE_TYPE: ErrorCode = 35;
|
||||
|
||||
@ -589,6 +589,7 @@ impl<'a> Parser<'a> {
|
||||
&& let Some(type_use) = maybe_type_use
|
||||
{
|
||||
let parameter = Parameter::new(
|
||||
self.next_node_id(),
|
||||
self.token_text(&identifier),
|
||||
SourceRange::new(identifier.start(), identifier.end()),
|
||||
type_use,
|
||||
@ -952,6 +953,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
if let Some(identifier) = maybe_identifier {
|
||||
let let_statement = LetStatement::new(
|
||||
self.next_node_id(),
|
||||
self.token_text(&identifier),
|
||||
SourceRange::new(identifier.start(), identifier.end()),
|
||||
is_mut,
|
||||
@ -974,7 +976,7 @@ impl<'a> Parser<'a> {
|
||||
(Statement::Assign(assign_statement), diagnostics)
|
||||
} else {
|
||||
(
|
||||
Statement::Expression(ExpressionStatement::new(base)),
|
||||
Statement::Expression(ExpressionStatement::new(self.next_node_id(), base)),
|
||||
diagnostics,
|
||||
)
|
||||
}
|
||||
@ -1008,6 +1010,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::BitwiseOr,
|
||||
@ -1030,6 +1033,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::BitwiseXor,
|
||||
@ -1053,6 +1057,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::BitwiseAnd,
|
||||
@ -1084,6 +1089,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::LeftShift,
|
||||
@ -1103,6 +1109,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::RightShift,
|
||||
@ -1133,6 +1140,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::Add,
|
||||
@ -1147,6 +1155,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::Subtract,
|
||||
@ -1176,6 +1185,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::Multiply,
|
||||
@ -1190,6 +1200,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::Divide,
|
||||
@ -1204,6 +1215,7 @@ impl<'a> Parser<'a> {
|
||||
let source_range =
|
||||
SourceRange::new(base.source_range().start(), rhs.source_range().end());
|
||||
base = Expression::Binary(BinaryExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
rhs,
|
||||
BinaryOperation::Modulo,
|
||||
@ -1242,7 +1254,11 @@ impl<'a> Parser<'a> {
|
||||
let source_range = SourceRange::new(operator_token.start(), base.source_range().end());
|
||||
match operator_token.kind() {
|
||||
TokenKind::Minus => {
|
||||
base = Expression::Negative(NegativeExpression::new(base, source_range));
|
||||
base = Expression::Negative(NegativeExpression::new(
|
||||
self.next_node_id(),
|
||||
base,
|
||||
source_range,
|
||||
));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@ -1281,6 +1297,7 @@ impl<'a> Parser<'a> {
|
||||
diagnostics.append(&mut self.advance());
|
||||
(
|
||||
Expression::Integer(IntegerLiteral::new(
|
||||
self.next_node_id(),
|
||||
i32::from_str(raw).unwrap(),
|
||||
source_range,
|
||||
)),
|
||||
@ -1293,6 +1310,7 @@ impl<'a> Parser<'a> {
|
||||
diagnostics.append(&mut self.advance());
|
||||
(
|
||||
Expression::Double(DoubleLiteral::new(
|
||||
self.next_node_id(),
|
||||
f64::from_str(raw).unwrap(),
|
||||
source_range,
|
||||
)),
|
||||
@ -1305,6 +1323,7 @@ impl<'a> Parser<'a> {
|
||||
diagnostics.append(&mut self.advance());
|
||||
(
|
||||
Expression::String(StringLiteral::new(
|
||||
self.next_node_id(),
|
||||
&with_quotes[1..with_quotes.len() - 1],
|
||||
source_range,
|
||||
)),
|
||||
@ -1352,7 +1371,10 @@ impl<'a> Parser<'a> {
|
||||
SourceRange::new(callee.source_range().start(), callee.source_range().end())
|
||||
};
|
||||
|
||||
(Call::new(callee, arguments, source_range), diagnostics)
|
||||
(
|
||||
Call::new(self.next_node_id(), callee, arguments, source_range),
|
||||
diagnostics,
|
||||
)
|
||||
}
|
||||
|
||||
fn expression_list(&mut self) -> ParseResult<Vec<Expression>> {
|
||||
|
||||
@ -6,6 +6,7 @@ use std::rc::Rc;
|
||||
pub enum CallableSymbol {
|
||||
Function(Rc<FunctionSymbol>),
|
||||
Constructor(Rc<ConstructorSymbol>),
|
||||
ErrorPlaceholder,
|
||||
}
|
||||
|
||||
impl CallableSymbol {
|
||||
@ -15,6 +16,7 @@ impl CallableSymbol {
|
||||
CallableSymbol::Constructor(constructor_symbol) => {
|
||||
constructor_symbol.parameters().to_vec()
|
||||
}
|
||||
CallableSymbol::ErrorPlaceholder => Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol::constructor_symbol::ConstructorSymbol;
|
||||
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||
use crate::symbol::field_symbol::FieldSymbol;
|
||||
use crate::symbol::function_symbol::FunctionSymbol;
|
||||
use crate::symbol::generic_parameter_symbol::GenericParameterSymbol;
|
||||
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::symbol::type_symbol::TypeSymbol;
|
||||
use crate::symbol::variable_symbol::VariableSymbol;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -19,7 +21,7 @@ pub mod parameter_symbol;
|
||||
pub mod type_symbol;
|
||||
pub mod variable_symbol;
|
||||
|
||||
#[derive(Eq, PartialEq, Hash)]
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Symbol {
|
||||
Class(Rc<ClassSymbol>),
|
||||
GenericParameter(Rc<GenericParameterSymbol>),
|
||||
@ -76,4 +78,38 @@ impl Symbol {
|
||||
Symbol::Variable(variable_symbol) => Some(variable_symbol.declared_name_source_range()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_type_symbol(&self) -> TypeSymbol {
|
||||
match self {
|
||||
Symbol::Class(class_symbol) => TypeSymbol::Class(class_symbol.clone()),
|
||||
Symbol::GenericParameter(generic_parameter_symbol) => {
|
||||
TypeSymbol::GenericParameter(generic_parameter_symbol.clone())
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_expressible_symbol(&self) -> ExpressibleSymbol {
|
||||
match self {
|
||||
Symbol::Class(class_symbol) => ExpressibleSymbol::Class(class_symbol.clone()),
|
||||
Symbol::Field(field_symbol) => ExpressibleSymbol::Field(field_symbol.clone()),
|
||||
Symbol::Function(function_symbol) => {
|
||||
ExpressibleSymbol::Function(function_symbol.clone())
|
||||
}
|
||||
Symbol::Parameter(parameter_symbol) => {
|
||||
ExpressibleSymbol::Parameter(parameter_symbol.clone())
|
||||
}
|
||||
Symbol::Variable(variable_symbol) => {
|
||||
ExpressibleSymbol::Variable(variable_symbol.clone())
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_function_symbol(&self) -> &Rc<FunctionSymbol> {
|
||||
match self {
|
||||
Symbol::Function(function_symbol) => function_symbol,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::Symbol;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
@ -11,9 +11,15 @@ pub enum TypeInfo {
|
||||
Double,
|
||||
String,
|
||||
Function(Rc<FunctionSymbol>),
|
||||
|
||||
#[deprecated]
|
||||
Class(Rc<ClassSymbol>),
|
||||
|
||||
ParameterizedClass(Rc<ClassSymbol>, Vec<TypeInfo>),
|
||||
GenericType(Rc<GenericParameterSymbol>),
|
||||
Void,
|
||||
|
||||
PlaceholderError,
|
||||
}
|
||||
|
||||
impl Display for TypeInfo {
|
||||
@ -36,10 +42,23 @@ impl Display for TypeInfo {
|
||||
TypeInfo::Class(class_symbol) => {
|
||||
write!(f, "Class({:?})", class_symbol)
|
||||
}
|
||||
TypeInfo::ParameterizedClass(class_symbol, arguments) => {
|
||||
write!(
|
||||
f,
|
||||
"ParameterizedClass({:?}<{}>)",
|
||||
class_symbol,
|
||||
arguments
|
||||
.iter()
|
||||
.map(|a| a.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
}
|
||||
TypeInfo::GenericType(generic_parameter_symbol) => {
|
||||
write!(f, "{}", generic_parameter_symbol.declared_name())
|
||||
}
|
||||
TypeInfo::Void => write!(f, "Void"),
|
||||
TypeInfo::PlaceholderError => write!(f, "<PlaceholderError>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,6 +91,16 @@ impl TypeInfo {
|
||||
TypeInfo::Class(other_class_symbol) => class_symbol == other_class_symbol,
|
||||
_ => false,
|
||||
},
|
||||
TypeInfo::ParameterizedClass(class_symbol, arguments) => match other {
|
||||
TypeInfo::ParameterizedClass(other_class_symbol, other_arguments) => {
|
||||
if arguments.is_empty() && other_arguments.is_empty() {
|
||||
class_symbol == other_class_symbol
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
TypeInfo::GenericType(generic_parameter_symbol) => {
|
||||
// if generic_parameter_symbol.extends().len() > 0 {
|
||||
// unimplemented!(
|
||||
@ -83,6 +112,7 @@ impl TypeInfo {
|
||||
TypeInfo::Void => {
|
||||
matches!(other, TypeInfo::Void)
|
||||
}
|
||||
TypeInfo::PlaceholderError => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user