Refactor scopes and symbol table for more resiliency and classes/fields.
This commit is contained in:
parent
9790ec6ca6
commit
89f519c45f
@ -6,7 +6,8 @@ use dmc_lib::ir::ir_return::IrReturn;
|
|||||||
use dmc_lib::ir::ir_statement::IrStatement;
|
use dmc_lib::ir::ir_statement::IrStatement;
|
||||||
use dmc_lib::lexer::Lexer;
|
use dmc_lib::lexer::Lexer;
|
||||||
use dmc_lib::parser::parse_expression;
|
use dmc_lib::parser::parse_expression;
|
||||||
use dmc_lib::symbol::FunctionSymbol;
|
use dmc_lib::source_range::SourceRange;
|
||||||
|
use dmc_lib::symbol::function_symbol::FunctionSymbol;
|
||||||
use dmc_lib::symbol_table::SymbolTable;
|
use dmc_lib::symbol_table::SymbolTable;
|
||||||
use dmc_lib::token::TokenKind;
|
use dmc_lib::token::TokenKind;
|
||||||
use dvm_lib::vm::constant::{Constant, StringConstant};
|
use dvm_lib::vm::constant::{Constant, StringConstant};
|
||||||
@ -100,10 +101,15 @@ fn compile_expression(
|
|||||||
let mut expression = parse_result?;
|
let mut expression = parse_result?;
|
||||||
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
// "fake" scope
|
|
||||||
symbol_table.push_scope("__repl_enter");
|
// "fake" scopes
|
||||||
|
symbol_table.push_module_scope("__repl_module");
|
||||||
|
symbol_table.push_function_scope("__repl_function");
|
||||||
|
|
||||||
expression.gather_declared_names(&mut symbol_table)?;
|
expression.gather_declared_names(&mut symbol_table)?;
|
||||||
symbol_table.pop_scope();
|
|
||||||
|
symbol_table.pop_scope(); // function
|
||||||
|
symbol_table.pop_scope(); // module
|
||||||
|
|
||||||
expression.check_name_usages(&symbol_table)?;
|
expression.check_name_usages(&symbol_table)?;
|
||||||
expression.type_check(&symbol_table)?;
|
expression.type_check(&symbol_table)?;
|
||||||
@ -125,6 +131,7 @@ fn compile_expression(
|
|||||||
// synthesize symbol
|
// synthesize symbol
|
||||||
let fake_function_symbol = Rc::new(RefCell::new(FunctionSymbol::new(
|
let fake_function_symbol = Rc::new(RefCell::new(FunctionSymbol::new(
|
||||||
"__repl",
|
"__repl",
|
||||||
|
SourceRange::new(0, 0),
|
||||||
false,
|
false,
|
||||||
expression.type_info().clone(), // dubious
|
expression.type_info().clone(), // dubious
|
||||||
)));
|
)));
|
||||||
|
|||||||
@ -4,7 +4,9 @@ use crate::diagnostic::Diagnostic;
|
|||||||
use crate::ir::ir_call::IrCall;
|
use crate::ir::ir_call::IrCall;
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::{ExpressibleSymbol, FunctionSymbol};
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||||
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -178,7 +180,7 @@ impl Call {
|
|||||||
.collect();
|
.collect();
|
||||||
let function_symbol = self.get_callee_symbol();
|
let function_symbol = self.get_callee_symbol();
|
||||||
IrCall::new(
|
IrCall::new(
|
||||||
function_symbol.borrow().name_owned(),
|
function_symbol.borrow().declared_name_owned(),
|
||||||
arguments,
|
arguments,
|
||||||
function_symbol.clone(),
|
function_symbol.clone(),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -31,6 +31,9 @@ impl Class {
|
|||||||
&mut self,
|
&mut self,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
) -> Result<(), Vec<Diagnostic>> {
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
// 1. insert class symbol
|
||||||
|
// 2. gather fields
|
||||||
|
// 3. gather functions
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,7 +40,7 @@ impl CompilationUnit {
|
|||||||
&mut self,
|
&mut self,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
) -> Result<(), Vec<Diagnostic>> {
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
symbol_table.push_scope("compilation_unit_scope");
|
symbol_table.push_module_scope("compilation_unit_scope");
|
||||||
|
|
||||||
let mut diagnostics: Vec<Diagnostic> = vec![];
|
let mut diagnostics: Vec<Diagnostic> = vec![];
|
||||||
self.functions
|
self.functions
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use crate::ast::ir_builder::IrBuilder;
|
|||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::ir::ir_return::IrReturn;
|
use crate::ir::ir_return::IrReturn;
|
||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::ast::parameter::Parameter;
|
|||||||
use crate::ast::type_use::TypeUse;
|
use crate::ast::type_use::TypeUse;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
|
|
||||||
pub struct ExternFunction {
|
pub struct ExternFunction {
|
||||||
@ -39,6 +39,7 @@ impl ExternFunction {
|
|||||||
|
|
||||||
let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new(
|
let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new(
|
||||||
&self.declared_name,
|
&self.declared_name,
|
||||||
|
self.declared_name_source_range.clone(),
|
||||||
true,
|
true,
|
||||||
self.return_type.to_type_info(),
|
self.return_type.to_type_info(),
|
||||||
));
|
));
|
||||||
@ -51,7 +52,7 @@ impl ExternFunction {
|
|||||||
diagnostics.push(Diagnostic::new(
|
diagnostics.push(Diagnostic::new(
|
||||||
&format!(
|
&format!(
|
||||||
"Function {} already declared in current scope.",
|
"Function {} already declared in current scope.",
|
||||||
already_declared.name()
|
already_declared.symbol().borrow().declared_name()
|
||||||
),
|
),
|
||||||
self.declared_name_source_range.start(),
|
self.declared_name_source_range.start(),
|
||||||
self.declared_name_source_range.end(),
|
self.declared_name_source_range.end(),
|
||||||
@ -62,7 +63,8 @@ impl ExternFunction {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
symbol_table.push_scope(&format!("extern_function_scope({})", &self.declared_name));
|
symbol_table
|
||||||
|
.push_function_scope(&format!("extern_function_scope({})", &self.declared_name));
|
||||||
|
|
||||||
let mut parameter_symbols = vec![];
|
let mut parameter_symbols = vec![];
|
||||||
for parameter in &mut self.parameters {
|
for parameter in &mut self.parameters {
|
||||||
@ -80,7 +82,7 @@ impl ExternFunction {
|
|||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_parameters(parameter_symbols);
|
.set_parameters(parameter_symbols);
|
||||||
|
|
||||||
symbol_table.pop_scope();
|
symbol_table.pop_scope(); // function scope
|
||||||
|
|
||||||
if diagnostics.is_empty() {
|
if diagnostics.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -6,7 +6,8 @@ use crate::diagnostic::Diagnostic;
|
|||||||
use crate::ir::ir_function::IrFunction;
|
use crate::ir::ir_function::IrFunction;
|
||||||
use crate::ir::ir_parameter::IrParameter;
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -60,6 +61,7 @@ impl Function {
|
|||||||
// insert function symbol
|
// insert function symbol
|
||||||
let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new(
|
let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new(
|
||||||
self.declared_name(),
|
self.declared_name(),
|
||||||
|
self.declared_name_source_range.clone(),
|
||||||
false,
|
false,
|
||||||
self.return_type
|
self.return_type
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -76,7 +78,7 @@ impl Function {
|
|||||||
diagnostics.push(Diagnostic::new(
|
diagnostics.push(Diagnostic::new(
|
||||||
&format!(
|
&format!(
|
||||||
"Function {} already declared in current scope",
|
"Function {} already declared in current scope",
|
||||||
already_declared.name()
|
already_declared.symbol().borrow().declared_name()
|
||||||
),
|
),
|
||||||
self.declared_name_source_range.start(),
|
self.declared_name_source_range.start(),
|
||||||
self.declared_name_source_range.end(),
|
self.declared_name_source_range.end(),
|
||||||
@ -91,7 +93,7 @@ impl Function {
|
|||||||
self.function_symbol = Some(function_symbol.clone());
|
self.function_symbol = Some(function_symbol.clone());
|
||||||
|
|
||||||
// handle parameters
|
// handle parameters
|
||||||
symbol_table.push_scope(&format!("parameter_scope({})", self.declared_name));
|
symbol_table.push_function_scope(&format!("function_scope({})", self.declared_name));
|
||||||
let mut parameter_symbols = vec![];
|
let mut parameter_symbols = vec![];
|
||||||
for parameter in &mut self.parameters {
|
for parameter in &mut self.parameters {
|
||||||
match parameter.gather_declared_names(symbol_table) {
|
match parameter.gather_declared_names(symbol_table) {
|
||||||
@ -107,7 +109,7 @@ impl Function {
|
|||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_parameters(parameter_symbols);
|
.set_parameters(parameter_symbols);
|
||||||
|
|
||||||
symbol_table.push_scope(&format!("body_scope({})", self.declared_name));
|
symbol_table.push_block_scope(&format!("main_block_scope({})", self.declared_name));
|
||||||
for statement in &mut self.statements {
|
for statement in &mut self.statements {
|
||||||
match statement.gather_declared_names(symbol_table) {
|
match statement.gather_declared_names(symbol_table) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
@ -116,8 +118,8 @@ impl Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
symbol_table.pop_scope(); // body
|
symbol_table.pop_scope(); // main block scope
|
||||||
symbol_table.pop_scope(); // params
|
symbol_table.pop_scope(); // function scope
|
||||||
|
|
||||||
if diagnostics.is_empty() {
|
if diagnostics.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -204,7 +206,7 @@ impl Function {
|
|||||||
let parameter_symbol = parameter.parameter_symbol();
|
let parameter_symbol = parameter.parameter_symbol();
|
||||||
let stack_offset = (self.parameters.len() as isize).neg() + (i as isize);
|
let stack_offset = (self.parameters.len() as isize).neg() + (i as isize);
|
||||||
let ir_parameter = IrParameter::new(
|
let ir_parameter = IrParameter::new(
|
||||||
parameter_symbol.borrow().name(),
|
parameter_symbol.borrow().declared_name(),
|
||||||
parameter_symbol.borrow().type_info().clone(),
|
parameter_symbol.borrow().type_info().clone(),
|
||||||
stack_offset,
|
stack_offset,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::ExpressibleSymbol;
|
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
|
|
||||||
|
|||||||
@ -7,13 +7,13 @@ use crate::ir::ir_operation::IrOperation;
|
|||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
use crate::ir::ir_variable::IrVariable;
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::VariableSymbol;
|
use crate::symbol::variable_symbol::VariableSymbol;
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct LetStatement {
|
pub struct LetStatement {
|
||||||
declared_name: String,
|
declared_name: Rc<str>,
|
||||||
declared_name_source_range: SourceRange,
|
declared_name_source_range: SourceRange,
|
||||||
initializer: Box<Expression>,
|
initializer: Box<Expression>,
|
||||||
scope_id: Option<usize>,
|
scope_id: Option<usize>,
|
||||||
@ -26,7 +26,7 @@ impl LetStatement {
|
|||||||
initializer: Expression,
|
initializer: Expression,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
declared_name: declared_name.to_string(),
|
declared_name: declared_name.into(),
|
||||||
declared_name_source_range,
|
declared_name_source_range,
|
||||||
initializer: initializer.into(),
|
initializer: initializer.into(),
|
||||||
scope_id: None,
|
scope_id: None,
|
||||||
@ -58,15 +58,17 @@ impl LetStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let insert_result =
|
let insert_result = symbol_table.insert_variable_symbol(VariableSymbol::new(
|
||||||
symbol_table.insert_variable_symbol(VariableSymbol::new(self.declared_name()));
|
&self.declared_name,
|
||||||
|
self.declared_name_source_range.clone(),
|
||||||
|
));
|
||||||
if let Err(symbol_insert_error) = insert_result {
|
if let Err(symbol_insert_error) = insert_result {
|
||||||
match symbol_insert_error {
|
match symbol_insert_error {
|
||||||
SymbolInsertError::AlreadyDeclared(already_declared) => {
|
SymbolInsertError::AlreadyDeclared(already_declared) => {
|
||||||
diagnostics.push(Diagnostic::new(
|
diagnostics.push(Diagnostic::new(
|
||||||
&format!(
|
&format!(
|
||||||
"Symbol {} already declared in current scope",
|
"Symbol {} already declared in current scope",
|
||||||
already_declared.name()
|
already_declared.symbol().borrow().declared_name()
|
||||||
),
|
),
|
||||||
self.declared_name_source_range.start(),
|
self.declared_name_source_range.start(),
|
||||||
self.declared_name_source_range.end(),
|
self.declared_name_source_range.end(),
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
use crate::ast::type_use::TypeUse;
|
use crate::ast::type_use::TypeUse;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::ParameterSymbol;
|
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Parameter {
|
pub struct Parameter {
|
||||||
declared_name: String,
|
declared_name: Rc<str>,
|
||||||
declared_name_source_range: SourceRange,
|
declared_name_source_range: SourceRange,
|
||||||
type_use: TypeUse,
|
type_use: TypeUse,
|
||||||
parameter_symbol: Option<Rc<RefCell<ParameterSymbol>>>,
|
parameter_symbol: Option<Rc<RefCell<ParameterSymbol>>>,
|
||||||
@ -34,6 +34,7 @@ impl Parameter {
|
|||||||
) -> Result<Rc<RefCell<ParameterSymbol>>, Vec<Diagnostic>> {
|
) -> Result<Rc<RefCell<ParameterSymbol>>, Vec<Diagnostic>> {
|
||||||
let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
|
let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
|
||||||
&self.declared_name,
|
&self.declared_name,
|
||||||
|
self.declared_name_source_range.clone(),
|
||||||
TypeInfo::from_declared_name(self.type_use.declared_name()),
|
TypeInfo::from_declared_name(self.type_use.declared_name()),
|
||||||
));
|
));
|
||||||
match insert_result {
|
match insert_result {
|
||||||
@ -43,7 +44,10 @@ impl Parameter {
|
|||||||
}
|
}
|
||||||
Err(symbol_insert_error) => match symbol_insert_error {
|
Err(symbol_insert_error) => match symbol_insert_error {
|
||||||
SymbolInsertError::AlreadyDeclared(already_declared) => Err(vec![Diagnostic::new(
|
SymbolInsertError::AlreadyDeclared(already_declared) => Err(vec![Diagnostic::new(
|
||||||
&format!("Parameter {} already declared.", already_declared.name()),
|
&format!(
|
||||||
|
"Parameter {} already declared.",
|
||||||
|
already_declared.symbol().borrow().declared_name()
|
||||||
|
),
|
||||||
self.declared_name_source_range.start(),
|
self.declared_name_source_range.start(),
|
||||||
self.declared_name_source_range.end(),
|
self.declared_name_source_range.end(),
|
||||||
)]),
|
)]),
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::ast::expression_statement::ExpressionStatement;
|
|||||||
use crate::ast::ir_builder::IrBuilder;
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|||||||
@ -3,7 +3,8 @@ use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
|||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
use dvm_lib::instruction::Instruction;
|
use dvm_lib::instruction::Instruction;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
@ -67,14 +68,14 @@ impl Assemble for IrCall {
|
|||||||
.map(|ir_expression| ir_expression.push_operand(constants_table))
|
.map(|ir_expression| ir_expression.push_operand(constants_table))
|
||||||
.for_each(|push_operand| builder.push(Instruction::Push(push_operand)));
|
.for_each(|push_operand| builder.push(Instruction::Push(push_operand)));
|
||||||
let symbol = self.function_symbol.borrow();
|
let symbol = self.function_symbol.borrow();
|
||||||
if symbol.is_platform() {
|
if symbol.is_extern() {
|
||||||
builder.push(Instruction::InvokePlatformStatic(
|
builder.push(Instruction::InvokePlatformStatic(
|
||||||
symbol.name_owned(),
|
symbol.declared_name_owned(),
|
||||||
symbol.parameters().len(),
|
symbol.parameters().len(),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
builder.push(Instruction::InvokeStatic(
|
builder.push(Instruction::InvokeStatic(
|
||||||
symbol.name_owned(),
|
symbol.declared_name_owned(),
|
||||||
symbol.parameters().len(),
|
symbol.parameters().len(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,8 @@ use crate::ir::ir_block::IrBlock;
|
|||||||
use crate::ir::ir_parameter::IrParameter;
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::HasVrUsers;
|
use crate::ir::register_allocation::HasVrUsers;
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use dvm_lib::vm::function::Function;
|
use dvm_lib::vm::function::Function;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -46,7 +47,7 @@ impl IrFunction {
|
|||||||
self.entry.borrow().assemble(&mut builder, constants_table);
|
self.entry.borrow().assemble(&mut builder, constants_table);
|
||||||
let instructions = builder.take_instructions();
|
let instructions = builder.take_instructions();
|
||||||
Function::new(
|
Function::new(
|
||||||
self.function_symbol.borrow().name_owned(),
|
self.function_symbol.borrow().declared_name_owned(),
|
||||||
self.parameters.len(),
|
self.parameters.len(),
|
||||||
stack_size,
|
stack_size,
|
||||||
instructions,
|
instructions,
|
||||||
@ -56,7 +57,7 @@ impl IrFunction {
|
|||||||
|
|
||||||
impl Display for IrFunction {
|
impl Display for IrFunction {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "fn {}(", self.function_symbol.borrow().name())?;
|
write!(f, "fn {}(", self.function_symbol.borrow().declared_name())?;
|
||||||
for (i, parameter) in self.parameters.iter().enumerate() {
|
for (i, parameter) in self.parameters.iter().enumerate() {
|
||||||
write!(f, "{}: {}", parameter, parameter.type_info())?;
|
write!(f, "{}: {}", parameter, parameter.type_info())?;
|
||||||
if i < self.parameters.len() - 1 {
|
if i < self.parameters.len() - 1 {
|
||||||
|
|||||||
@ -4,7 +4,7 @@ pub mod diagnostic;
|
|||||||
pub mod ir;
|
pub mod ir;
|
||||||
pub mod lexer;
|
pub mod lexer;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod scope;
|
mod scope;
|
||||||
pub mod source_range;
|
pub mod source_range;
|
||||||
pub mod symbol;
|
pub mod symbol;
|
||||||
pub mod symbol_table;
|
pub mod symbol_table;
|
||||||
|
|||||||
@ -1,52 +0,0 @@
|
|||||||
use crate::symbol::{FunctionSymbol, ParameterSymbol, VariableSymbol};
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub struct Scope {
|
|
||||||
debug_name: String,
|
|
||||||
parent_id: Option<usize>,
|
|
||||||
function_symbols: HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>>,
|
|
||||||
parameter_symbols: HashMap<Rc<str>, Rc<RefCell<ParameterSymbol>>>,
|
|
||||||
variable_symbols: HashMap<Rc<str>, Rc<RefCell<VariableSymbol>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Scope {
|
|
||||||
pub fn new(debug_name: &str, parent_id: Option<usize>) -> Self {
|
|
||||||
Self {
|
|
||||||
debug_name: debug_name.into(),
|
|
||||||
parent_id,
|
|
||||||
function_symbols: HashMap::new(),
|
|
||||||
parameter_symbols: HashMap::new(),
|
|
||||||
variable_symbols: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn function_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>> {
|
|
||||||
&self.function_symbols
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn function_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>> {
|
|
||||||
&mut self.function_symbols
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parameter_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<ParameterSymbol>>> {
|
|
||||||
&self.parameter_symbols
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parameter_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<ParameterSymbol>>> {
|
|
||||||
&mut self.parameter_symbols
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variable_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<VariableSymbol>>> {
|
|
||||||
&self.variable_symbols
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variable_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<VariableSymbol>>> {
|
|
||||||
&mut self.variable_symbols
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parent_id(&self) -> Option<usize> {
|
|
||||||
self.parent_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
32
dmc-lib/src/scope/block_scope.rs
Normal file
32
dmc-lib/src/scope/block_scope.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use crate::symbol::variable_symbol::VariableSymbol;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct BlockScope {
|
||||||
|
debug_name: String,
|
||||||
|
parent_id: usize,
|
||||||
|
variable_symbols: HashMap<Rc<str>, Rc<RefCell<VariableSymbol>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockScope {
|
||||||
|
pub fn new(debug_name: &str, parent_id: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
debug_name: debug_name.into(),
|
||||||
|
parent_id,
|
||||||
|
variable_symbols: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn variable_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<VariableSymbol>>> {
|
||||||
|
&self.variable_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn variable_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<VariableSymbol>>> {
|
||||||
|
&mut self.variable_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parent_id(&self) -> usize {
|
||||||
|
self.parent_id
|
||||||
|
}
|
||||||
|
}
|
||||||
54
dmc-lib/src/scope/class_scope.rs
Normal file
54
dmc-lib/src/scope/class_scope.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use crate::symbol::class_symbol::ClassSymbol;
|
||||||
|
use crate::symbol::field_symbol::FieldSymbol;
|
||||||
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct ClassScope {
|
||||||
|
debug_name: String,
|
||||||
|
parent_id: usize,
|
||||||
|
class_symbols: HashMap<Rc<str>, Rc<RefCell<ClassSymbol>>>,
|
||||||
|
field_symbols: HashMap<Rc<str>, Rc<RefCell<FieldSymbol>>>,
|
||||||
|
function_symbols: HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClassScope {
|
||||||
|
pub fn new(debug_name: &str, parent_id: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
debug_name: debug_name.into(),
|
||||||
|
parent_id,
|
||||||
|
class_symbols: HashMap::new(),
|
||||||
|
field_symbols: HashMap::new(),
|
||||||
|
function_symbols: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<ClassSymbol>>> {
|
||||||
|
&self.class_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<ClassSymbol>>> {
|
||||||
|
&mut self.class_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn field_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<FieldSymbol>>> {
|
||||||
|
&self.field_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn field_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<FieldSymbol>>> {
|
||||||
|
&mut self.field_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>> {
|
||||||
|
&self.function_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>> {
|
||||||
|
&mut self.function_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parent_id(&self) -> usize {
|
||||||
|
self.parent_id
|
||||||
|
}
|
||||||
|
}
|
||||||
32
dmc-lib/src/scope/function_scope.rs
Normal file
32
dmc-lib/src/scope/function_scope.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct FunctionScope {
|
||||||
|
debug_name: String,
|
||||||
|
parent_id: usize,
|
||||||
|
parameter_symbols: HashMap<Rc<str>, Rc<RefCell<ParameterSymbol>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionScope {
|
||||||
|
pub fn new(debug_name: &str, parent_id: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
debug_name: debug_name.into(),
|
||||||
|
parent_id,
|
||||||
|
parameter_symbols: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameter_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<ParameterSymbol>>> {
|
||||||
|
&self.parameter_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameter_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<ParameterSymbol>>> {
|
||||||
|
&mut self.parameter_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parent_id(&self) -> usize {
|
||||||
|
self.parent_id
|
||||||
|
}
|
||||||
|
}
|
||||||
27
dmc-lib/src/scope/mod.rs
Normal file
27
dmc-lib/src/scope/mod.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use crate::scope::block_scope::BlockScope;
|
||||||
|
use crate::scope::class_scope::ClassScope;
|
||||||
|
use crate::scope::function_scope::FunctionScope;
|
||||||
|
use crate::scope::module_scope::ModuleScope;
|
||||||
|
|
||||||
|
pub mod block_scope;
|
||||||
|
pub mod class_scope;
|
||||||
|
pub mod function_scope;
|
||||||
|
pub mod module_scope;
|
||||||
|
|
||||||
|
pub enum Scope {
|
||||||
|
Module(ModuleScope),
|
||||||
|
Class(ClassScope),
|
||||||
|
Function(FunctionScope),
|
||||||
|
Block(BlockScope),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scope {
|
||||||
|
pub fn parent_id(&self) -> Option<usize> {
|
||||||
|
match self {
|
||||||
|
Scope::Module(module_scope) => module_scope.parent_id(),
|
||||||
|
Scope::Class(class_scope) => Some(class_scope.parent_id()),
|
||||||
|
Scope::Function(function_scope) => Some(function_scope.parent_id()),
|
||||||
|
Scope::Block(block_scope) => Some(block_scope.parent_id()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
dmc-lib/src/scope/module_scope.rs
Normal file
43
dmc-lib/src/scope/module_scope.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use crate::symbol::class_symbol::ClassSymbol;
|
||||||
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct ModuleScope {
|
||||||
|
debug_name: String,
|
||||||
|
parent_id: Option<usize>,
|
||||||
|
class_symbols: HashMap<Rc<str>, Rc<RefCell<ClassSymbol>>>,
|
||||||
|
function_symbols: HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModuleScope {
|
||||||
|
pub fn new(debug_name: &str, parent_id: Option<usize>) -> Self {
|
||||||
|
Self {
|
||||||
|
debug_name: debug_name.into(),
|
||||||
|
parent_id,
|
||||||
|
class_symbols: HashMap::new(),
|
||||||
|
function_symbols: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<ClassSymbol>>> {
|
||||||
|
&self.class_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn class_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<ClassSymbol>>> {
|
||||||
|
&mut self.class_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_symbols(&self) -> &HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>> {
|
||||||
|
&self.function_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>> {
|
||||||
|
&mut self.function_symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parent_id(&self) -> Option<usize> {
|
||||||
|
self.parent_id
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,164 +0,0 @@
|
|||||||
use crate::ir::ir_expression::IrExpression;
|
|
||||||
use crate::ir::ir_parameter::IrParameter;
|
|
||||||
use crate::ir::ir_variable::IrVariable;
|
|
||||||
use crate::type_info::TypeInfo;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub struct FunctionSymbol {
|
|
||||||
name: Rc<str>,
|
|
||||||
is_platform: bool,
|
|
||||||
parameters: Option<Vec<Rc<RefCell<ParameterSymbol>>>>,
|
|
||||||
return_type: TypeInfo,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FunctionSymbol {
|
|
||||||
pub fn new(name: &str, is_platform: bool, return_type: TypeInfo) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.into(),
|
|
||||||
is_platform,
|
|
||||||
parameters: None,
|
|
||||||
return_type,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name_owned(&self) -> Rc<str> {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_parameters(&mut self, parameters: Vec<Rc<RefCell<ParameterSymbol>>>) {
|
|
||||||
self.parameters = Some(parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parameters(&self) -> &[Rc<RefCell<ParameterSymbol>>] {
|
|
||||||
self.parameters.as_ref().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn return_type_info(&self) -> &TypeInfo {
|
|
||||||
&self.return_type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_platform(&self) -> bool {
|
|
||||||
self.is_platform
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ParameterSymbol {
|
|
||||||
name: Rc<str>,
|
|
||||||
type_info: TypeInfo,
|
|
||||||
ir_parameter: Option<Rc<IrParameter>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ParameterSymbol {
|
|
||||||
pub fn new(name: &str, type_info: TypeInfo) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.into(),
|
|
||||||
type_info,
|
|
||||||
ir_parameter: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name_owned(&self) -> Rc<str> {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_info(&self) -> &TypeInfo {
|
|
||||||
&self.type_info
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_ir_parameter(&mut self, ir_parameter: Rc<IrParameter>) {
|
|
||||||
self.ir_parameter = Some(ir_parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ir_parameter(&self) -> &Rc<IrParameter> {
|
|
||||||
self.ir_parameter.as_ref().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VariableSymbol {
|
|
||||||
name: Rc<str>,
|
|
||||||
type_info: Option<TypeInfo>,
|
|
||||||
vr_variable: Option<Rc<RefCell<IrVariable>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VariableSymbol {
|
|
||||||
pub fn new(name: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: name.into(),
|
|
||||||
type_info: None,
|
|
||||||
vr_variable: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name_owned(&self) -> Rc<str> {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_type_info(&mut self, type_info: TypeInfo) {
|
|
||||||
self.type_info = Some(type_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_info(&self) -> &TypeInfo {
|
|
||||||
self.type_info
|
|
||||||
.as_ref()
|
|
||||||
.expect("TypeInfo not initialized. Did you type check?")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_vr_variable(&mut self, ir_variable: Rc<RefCell<IrVariable>>) {
|
|
||||||
self.vr_variable = Some(ir_variable);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn vr_variable(&self) -> &Rc<RefCell<IrVariable>> {
|
|
||||||
self.vr_variable
|
|
||||||
.as_ref()
|
|
||||||
.expect("ir_variable not yet initialized")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ExpressibleSymbol {
|
|
||||||
Function(Rc<RefCell<FunctionSymbol>>),
|
|
||||||
Parameter(Rc<RefCell<ParameterSymbol>>),
|
|
||||||
Variable(Rc<RefCell<VariableSymbol>>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpressibleSymbol {
|
|
||||||
pub fn type_info(&self) -> TypeInfo {
|
|
||||||
match self {
|
|
||||||
ExpressibleSymbol::Function(function_symbol) => {
|
|
||||||
TypeInfo::Function(function_symbol.clone()) // n.b. not the return type!
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
|
||||||
parameter_symbol.borrow().type_info().clone()
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
|
||||||
variable_symbol.borrow().type_info().clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ir_expression(&self) -> IrExpression {
|
|
||||||
match self {
|
|
||||||
ExpressibleSymbol::Function(_) => {
|
|
||||||
panic!("Cannot get ir_variable for FunctionSymbol");
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
|
||||||
IrExpression::Parameter(parameter_symbol.borrow().ir_parameter().clone())
|
|
||||||
}
|
|
||||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
|
||||||
IrExpression::Variable(variable_symbol.borrow().vr_variable().clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
45
dmc-lib/src/symbol/class_symbol.rs
Normal file
45
dmc-lib/src/symbol/class_symbol.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::field_symbol::FieldSymbol;
|
||||||
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct ClassSymbol {
|
||||||
|
declared_name: Rc<str>,
|
||||||
|
declared_name_source_range: SourceRange,
|
||||||
|
is_extern: bool,
|
||||||
|
fields: HashMap<Rc<str>, Rc<RefCell<FieldSymbol>>>,
|
||||||
|
functions: HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClassSymbol {
|
||||||
|
pub fn new(
|
||||||
|
declared_name: &Rc<str>,
|
||||||
|
declared_name_source_range: SourceRange,
|
||||||
|
is_extern: bool,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
declared_name: declared_name.clone(),
|
||||||
|
declared_name_source_range,
|
||||||
|
is_extern,
|
||||||
|
fields: HashMap::new(),
|
||||||
|
functions: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Symbol for ClassSymbol {
|
||||||
|
fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_owned(&self) -> Rc<str> {
|
||||||
|
self.declared_name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_source_range(&self) -> &SourceRange {
|
||||||
|
&self.declared_name_source_range
|
||||||
|
}
|
||||||
|
}
|
||||||
59
dmc-lib/src/symbol/expressible_symbol.rs
Normal file
59
dmc-lib/src/symbol/expressible_symbol.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::symbol::class_symbol::ClassSymbol;
|
||||||
|
use crate::symbol::field_symbol::FieldSymbol;
|
||||||
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
|
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||||
|
use crate::symbol::variable_symbol::VariableSymbol;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub enum ExpressibleSymbol {
|
||||||
|
Class(Rc<RefCell<ClassSymbol>>),
|
||||||
|
Field(Rc<RefCell<FieldSymbol>>),
|
||||||
|
Function(Rc<RefCell<FunctionSymbol>>),
|
||||||
|
Parameter(Rc<RefCell<ParameterSymbol>>),
|
||||||
|
Variable(Rc<RefCell<VariableSymbol>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExpressibleSymbol {
|
||||||
|
pub fn type_info(&self) -> TypeInfo {
|
||||||
|
match self {
|
||||||
|
ExpressibleSymbol::Class(class_symbol) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
ExpressibleSymbol::Field(field_symbol) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
ExpressibleSymbol::Function(function_symbol) => {
|
||||||
|
TypeInfo::Function(function_symbol.clone()) // n.b. not the return type!
|
||||||
|
}
|
||||||
|
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
||||||
|
parameter_symbol.borrow().type_info().clone()
|
||||||
|
}
|
||||||
|
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||||
|
variable_symbol.borrow().type_info().clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ir_expression(&self) -> IrExpression {
|
||||||
|
match self {
|
||||||
|
ExpressibleSymbol::Class(class_symbol) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
ExpressibleSymbol::Field(field_symbol) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
ExpressibleSymbol::Function(_) => {
|
||||||
|
panic!("Cannot get ir_variable for FunctionSymbol");
|
||||||
|
}
|
||||||
|
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
||||||
|
IrExpression::Parameter(parameter_symbol.borrow().ir_parameter().clone())
|
||||||
|
}
|
||||||
|
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||||
|
IrExpression::Variable(variable_symbol.borrow().vr_variable().clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
dmc-lib/src/symbol/field_symbol.rs
Normal file
34
dmc-lib/src/symbol/field_symbol.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct FieldSymbol {
|
||||||
|
declared_name: Rc<str>,
|
||||||
|
declared_name_source_range: SourceRange,
|
||||||
|
type_info: Option<TypeInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FieldSymbol {
|
||||||
|
pub fn new(declared_name: &Rc<str>, declared_name_source_range: SourceRange) -> Self {
|
||||||
|
Self {
|
||||||
|
declared_name: declared_name.clone(),
|
||||||
|
declared_name_source_range,
|
||||||
|
type_info: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Symbol for FieldSymbol {
|
||||||
|
fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_owned(&self) -> Rc<str> {
|
||||||
|
self.declared_name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_source_range(&self) -> &SourceRange {
|
||||||
|
&self.declared_name_source_range
|
||||||
|
}
|
||||||
|
}
|
||||||
71
dmc-lib/src/symbol/function_symbol.rs
Normal file
71
dmc-lib/src/symbol/function_symbol.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct FunctionSymbol {
|
||||||
|
declared_name: Rc<str>,
|
||||||
|
declared_name_source_range: SourceRange,
|
||||||
|
is_extern: bool,
|
||||||
|
parameters: Option<Vec<Rc<RefCell<ParameterSymbol>>>>,
|
||||||
|
return_type: TypeInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionSymbol {
|
||||||
|
pub fn new(
|
||||||
|
declared_name: &str,
|
||||||
|
declared_name_source_range: SourceRange,
|
||||||
|
is_extern: bool,
|
||||||
|
return_type: TypeInfo,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
declared_name: declared_name.into(),
|
||||||
|
declared_name_source_range,
|
||||||
|
is_extern,
|
||||||
|
parameters: None,
|
||||||
|
return_type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(note = "use declared_name")]
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(note = "use declared_name_owned")]
|
||||||
|
pub fn name_owned(&self) -> Rc<str> {
|
||||||
|
self.declared_name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_parameters(&mut self, parameters: Vec<Rc<RefCell<ParameterSymbol>>>) {
|
||||||
|
self.parameters = Some(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameters(&self) -> &[Rc<RefCell<ParameterSymbol>>] {
|
||||||
|
self.parameters.as_ref().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_type_info(&self) -> &TypeInfo {
|
||||||
|
&self.return_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_extern(&self) -> bool {
|
||||||
|
self.is_extern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Symbol for FunctionSymbol {
|
||||||
|
fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_owned(&self) -> Rc<str> {
|
||||||
|
self.declared_name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_source_range(&self) -> &SourceRange {
|
||||||
|
&self.declared_name_source_range
|
||||||
|
}
|
||||||
|
}
|
||||||
15
dmc-lib/src/symbol/mod.rs
Normal file
15
dmc-lib/src/symbol/mod.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use crate::source_range::SourceRange;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub mod class_symbol;
|
||||||
|
pub mod expressible_symbol;
|
||||||
|
pub mod field_symbol;
|
||||||
|
pub mod function_symbol;
|
||||||
|
pub mod parameter_symbol;
|
||||||
|
pub mod variable_symbol;
|
||||||
|
|
||||||
|
pub trait Symbol {
|
||||||
|
fn declared_name(&self) -> &str;
|
||||||
|
fn declared_name_owned(&self) -> Rc<str>;
|
||||||
|
fn declared_name_source_range(&self) -> &SourceRange;
|
||||||
|
}
|
||||||
53
dmc-lib/src/symbol/parameter_symbol.rs
Normal file
53
dmc-lib/src/symbol/parameter_symbol.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct ParameterSymbol {
|
||||||
|
declared_name: Rc<str>,
|
||||||
|
declared_name_source_range: SourceRange,
|
||||||
|
type_info: TypeInfo,
|
||||||
|
ir_parameter: Option<Rc<IrParameter>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParameterSymbol {
|
||||||
|
pub fn new(
|
||||||
|
declared_name: &Rc<str>,
|
||||||
|
declared_name_source_range: SourceRange,
|
||||||
|
type_info: TypeInfo,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
declared_name: declared_name.clone(),
|
||||||
|
declared_name_source_range,
|
||||||
|
type_info,
|
||||||
|
ir_parameter: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_info(&self) -> &TypeInfo {
|
||||||
|
&self.type_info
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ir_parameter(&mut self, ir_parameter: Rc<IrParameter>) {
|
||||||
|
self.ir_parameter = Some(ir_parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ir_parameter(&self) -> &Rc<IrParameter> {
|
||||||
|
self.ir_parameter.as_ref().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Symbol for ParameterSymbol {
|
||||||
|
fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_owned(&self) -> Rc<str> {
|
||||||
|
self.declared_name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_source_range(&self) -> &SourceRange {
|
||||||
|
&self.declared_name_source_range
|
||||||
|
}
|
||||||
|
}
|
||||||
58
dmc-lib/src/symbol/variable_symbol.rs
Normal file
58
dmc-lib/src/symbol/variable_symbol.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct VariableSymbol {
|
||||||
|
declared_name: Rc<str>,
|
||||||
|
declared_name_source_range: SourceRange,
|
||||||
|
type_info: Option<TypeInfo>,
|
||||||
|
vr_variable: Option<Rc<RefCell<IrVariable>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VariableSymbol {
|
||||||
|
pub fn new(name: &Rc<str>, declared_name_source_range: SourceRange) -> Self {
|
||||||
|
Self {
|
||||||
|
declared_name: name.clone(),
|
||||||
|
declared_name_source_range,
|
||||||
|
type_info: None,
|
||||||
|
vr_variable: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_type_info(&mut self, type_info: TypeInfo) {
|
||||||
|
self.type_info = Some(type_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_info(&self) -> &TypeInfo {
|
||||||
|
self.type_info
|
||||||
|
.as_ref()
|
||||||
|
.expect("TypeInfo not initialized. Did you type check?")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_vr_variable(&mut self, ir_variable: Rc<RefCell<IrVariable>>) {
|
||||||
|
self.vr_variable = Some(ir_variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vr_variable(&self) -> &Rc<RefCell<IrVariable>> {
|
||||||
|
self.vr_variable
|
||||||
|
.as_ref()
|
||||||
|
.expect("ir_variable not yet initialized")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Symbol for VariableSymbol {
|
||||||
|
fn declared_name(&self) -> &str {
|
||||||
|
&self.declared_name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_owned(&self) -> Rc<str> {
|
||||||
|
self.declared_name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declared_name_source_range(&self) -> &SourceRange {
|
||||||
|
&self.declared_name_source_range
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,157 +0,0 @@
|
|||||||
use crate::scope::Scope;
|
|
||||||
use crate::symbol::{ExpressibleSymbol, FunctionSymbol, ParameterSymbol, VariableSymbol};
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub struct SymbolTable {
|
|
||||||
scopes: Vec<Scope>,
|
|
||||||
current_scope_id: Option<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolTable {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
scopes: vec![],
|
|
||||||
current_scope_id: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_scope(&mut self, debug_name: &str) -> usize {
|
|
||||||
let scope_id = self.scopes.len();
|
|
||||||
let parent_id = self.current_scope_id;
|
|
||||||
let scope = Scope::new(debug_name, parent_id);
|
|
||||||
self.scopes.push(scope);
|
|
||||||
self.current_scope_id = Some(scope_id);
|
|
||||||
scope_id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop_scope(&mut self) {
|
|
||||||
self.current_scope_id = self.current_scope().parent_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_scope_id(&self) -> usize {
|
|
||||||
self.current_scope_id.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn current_scope(&self) -> &Scope {
|
|
||||||
&self.scopes[self.current_scope_id.unwrap()]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn current_scope_mut(&mut self) -> &mut Scope {
|
|
||||||
&mut self.scopes[self.current_scope_id.unwrap()]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn current_scope_has_name(&self, name: &str) -> bool {
|
|
||||||
let current_scope = self.current_scope();
|
|
||||||
current_scope.function_symbols().contains_key(name)
|
|
||||||
|| current_scope.parameter_symbols().contains_key(name)
|
|
||||||
|| current_scope.variable_symbols().contains_key(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_function_symbol(
|
|
||||||
&mut self,
|
|
||||||
function_symbol: FunctionSymbol,
|
|
||||||
) -> Result<Rc<RefCell<FunctionSymbol>>, SymbolInsertError> {
|
|
||||||
if self.current_scope_has_name(function_symbol.name()) {
|
|
||||||
return Err(SymbolInsertError::AlreadyDeclared(AlreadyDeclared::new(
|
|
||||||
function_symbol.name(),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
let name = function_symbol.name_owned();
|
|
||||||
let as_rc = Rc::new(RefCell::new(function_symbol));
|
|
||||||
|
|
||||||
self.current_scope_mut()
|
|
||||||
.function_symbols_mut()
|
|
||||||
.insert(name, as_rc.clone());
|
|
||||||
Ok(as_rc)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_parameter_symbol(
|
|
||||||
&mut self,
|
|
||||||
parameter_symbol: ParameterSymbol,
|
|
||||||
) -> Result<Rc<RefCell<ParameterSymbol>>, SymbolInsertError> {
|
|
||||||
if self.current_scope_has_name(parameter_symbol.name()) {
|
|
||||||
return Err(SymbolInsertError::AlreadyDeclared(AlreadyDeclared::new(
|
|
||||||
parameter_symbol.name(),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
let as_rc = Rc::new(RefCell::new(parameter_symbol));
|
|
||||||
self.current_scope_mut()
|
|
||||||
.parameter_symbols_mut()
|
|
||||||
.insert(as_rc.borrow().name_owned(), as_rc.clone());
|
|
||||||
Ok(as_rc)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_variable_symbol(
|
|
||||||
&mut self,
|
|
||||||
variable_symbol: VariableSymbol,
|
|
||||||
) -> Result<(), SymbolInsertError> {
|
|
||||||
if self.current_scope_has_name(variable_symbol.name()) {
|
|
||||||
return Err(SymbolInsertError::AlreadyDeclared(AlreadyDeclared::new(
|
|
||||||
variable_symbol.name(),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
self.current_scope_mut().variable_symbols_mut().insert(
|
|
||||||
variable_symbol.name_owned(),
|
|
||||||
Rc::new(RefCell::new(variable_symbol)),
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_expressible_symbol(
|
|
||||||
&self,
|
|
||||||
scope_id: usize,
|
|
||||||
name: &str,
|
|
||||||
) -> Option<ExpressibleSymbol> {
|
|
||||||
let mut maybe_scope = self.scopes.get(scope_id);
|
|
||||||
if maybe_scope.is_none() {
|
|
||||||
panic!("Invalid scope_id: {}", scope_id);
|
|
||||||
}
|
|
||||||
while let Some(scope) = maybe_scope {
|
|
||||||
let maybe_expressible_symbol = scope
|
|
||||||
.variable_symbols()
|
|
||||||
.get(name)
|
|
||||||
.map(|variable_symbol| ExpressibleSymbol::Variable(variable_symbol.clone()))
|
|
||||||
.or_else(|| {
|
|
||||||
scope
|
|
||||||
.function_symbols()
|
|
||||||
.get(name)
|
|
||||||
.map(|function_symbol| ExpressibleSymbol::Function(function_symbol.clone()))
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
scope.parameter_symbols().get(name).map(|parameter_symbol| {
|
|
||||||
ExpressibleSymbol::Parameter(parameter_symbol.clone())
|
|
||||||
})
|
|
||||||
});
|
|
||||||
if maybe_expressible_symbol.is_some() {
|
|
||||||
return maybe_expressible_symbol;
|
|
||||||
} else {
|
|
||||||
maybe_scope = scope.parent_id().map(|id| &self.scopes[id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_variable_symbol(&self, scope_id: usize, name: &str) -> Rc<RefCell<VariableSymbol>> {
|
|
||||||
let scope = self.scopes.get(scope_id).unwrap();
|
|
||||||
scope.variable_symbols().get(name).unwrap().clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum SymbolInsertError {
|
|
||||||
AlreadyDeclared(AlreadyDeclared),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AlreadyDeclared {
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AlreadyDeclared {
|
|
||||||
pub fn new(name: &str) -> Self {
|
|
||||||
Self { name: name.into() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
136
dmc-lib/src/symbol_table/helpers.rs
Normal file
136
dmc-lib/src/symbol_table/helpers.rs
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
use crate::scope::Scope;
|
||||||
|
use crate::scope::block_scope::BlockScope;
|
||||||
|
use crate::scope::class_scope::ClassScope;
|
||||||
|
use crate::scope::function_scope::FunctionScope;
|
||||||
|
use crate::scope::module_scope::ModuleScope;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub fn find_in_module_by_name(
|
||||||
|
module_scope: &ModuleScope,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<Rc<RefCell<dyn Symbol>>> {
|
||||||
|
module_scope
|
||||||
|
.function_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|symbol| symbol.clone() as Rc<RefCell<dyn Symbol>>)
|
||||||
|
.or_else(|| {
|
||||||
|
module_scope
|
||||||
|
.class_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|symbol| symbol.clone() as Rc<RefCell<dyn Symbol>>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_in_class_by_name(
|
||||||
|
class_scope: &ClassScope,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<Rc<RefCell<dyn Symbol>>> {
|
||||||
|
class_scope
|
||||||
|
.class_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|symbol| symbol.clone() as Rc<RefCell<dyn Symbol>>)
|
||||||
|
.or_else(|| {
|
||||||
|
class_scope
|
||||||
|
.function_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|symbol| symbol.clone() as Rc<RefCell<dyn Symbol>>)
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
class_scope
|
||||||
|
.field_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|symbol| symbol.clone() as Rc<RefCell<dyn Symbol>>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_in_function_by_name(
|
||||||
|
function_scope: &FunctionScope,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<Rc<RefCell<dyn Symbol>>> {
|
||||||
|
function_scope
|
||||||
|
.parameter_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|symbol| symbol.clone() as Rc<RefCell<dyn Symbol>>)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_in_block_by_name(
|
||||||
|
block_scope: &BlockScope,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<Rc<RefCell<dyn Symbol>>> {
|
||||||
|
block_scope
|
||||||
|
.variable_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|symbol| symbol.clone() as Rc<RefCell<dyn Symbol>>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_expressible_in_module_by_name(
|
||||||
|
module_scope: &ModuleScope,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<ExpressibleSymbol> {
|
||||||
|
module_scope
|
||||||
|
.class_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|class_symbol| ExpressibleSymbol::Class(class_symbol.clone()))
|
||||||
|
.or_else(|| {
|
||||||
|
module_scope
|
||||||
|
.function_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|function_symbol| ExpressibleSymbol::Function(function_symbol.clone()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_expressible_in_class_by_name(
|
||||||
|
class_scope: &ClassScope,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<ExpressibleSymbol> {
|
||||||
|
class_scope
|
||||||
|
.class_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|symbol| ExpressibleSymbol::Class(symbol.clone()))
|
||||||
|
.or_else(|| {
|
||||||
|
class_scope
|
||||||
|
.function_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|function_symbol| ExpressibleSymbol::Function(function_symbol.clone()))
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
class_scope
|
||||||
|
.field_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|field_symbol| ExpressibleSymbol::Field(field_symbol.clone()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_expressible_in_function_by_name(
|
||||||
|
function_scope: &FunctionScope,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<ExpressibleSymbol> {
|
||||||
|
function_scope
|
||||||
|
.parameter_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|parameter_symbol| ExpressibleSymbol::Parameter(parameter_symbol.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_expressible_in_block_by_name(
|
||||||
|
block_scope: &BlockScope,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<ExpressibleSymbol> {
|
||||||
|
block_scope
|
||||||
|
.variable_symbols()
|
||||||
|
.get(name)
|
||||||
|
.map(|variable_symbol| ExpressibleSymbol::Variable(variable_symbol.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_expressible_symbol(scope: &Scope, name: &str) -> Option<ExpressibleSymbol> {
|
||||||
|
match scope {
|
||||||
|
Scope::Module(module_scope) => find_expressible_in_module_by_name(module_scope, name),
|
||||||
|
Scope::Class(class_scope) => find_expressible_in_class_by_name(class_scope, name),
|
||||||
|
Scope::Function(function_scope) => {
|
||||||
|
find_expressible_in_function_by_name(function_scope, name)
|
||||||
|
}
|
||||||
|
Scope::Block(block_scope) => find_expressible_in_block_by_name(block_scope, name),
|
||||||
|
}
|
||||||
|
}
|
||||||
225
dmc-lib/src/symbol_table/mod.rs
Normal file
225
dmc-lib/src/symbol_table/mod.rs
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
mod helpers;
|
||||||
|
|
||||||
|
use crate::scope::Scope;
|
||||||
|
use crate::scope::block_scope::BlockScope;
|
||||||
|
use crate::scope::class_scope::ClassScope;
|
||||||
|
use crate::scope::function_scope::FunctionScope;
|
||||||
|
use crate::scope::module_scope::ModuleScope;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||||
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
|
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||||
|
use crate::symbol::variable_symbol::VariableSymbol;
|
||||||
|
use crate::symbol_table::helpers::{
|
||||||
|
find_expressible_symbol, find_in_block_by_name, find_in_class_by_name,
|
||||||
|
find_in_function_by_name, find_in_module_by_name,
|
||||||
|
};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct SymbolTable {
|
||||||
|
scopes: Vec<Scope>,
|
||||||
|
current_scope_id: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SymbolTable {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
scopes: vec![],
|
||||||
|
current_scope_id: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_scope_id(&self) -> usize {
|
||||||
|
self.scopes.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_scope(&mut self, scope: Scope) {
|
||||||
|
let scope_id = self.new_scope_id();
|
||||||
|
self.scopes.push(scope);
|
||||||
|
self.current_scope_id = Some(scope_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_module_scope(&mut self, debug_name: &str) {
|
||||||
|
self.push_scope(Scope::Module(ModuleScope::new(
|
||||||
|
debug_name,
|
||||||
|
self.current_scope_id,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_class_scope(&mut self, debug_name: &str) {
|
||||||
|
self.push_scope(Scope::Class(ClassScope::new(
|
||||||
|
debug_name,
|
||||||
|
self.current_scope_id.unwrap(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_function_scope(&mut self, debug_name: &str) {
|
||||||
|
self.push_scope(Scope::Function(FunctionScope::new(
|
||||||
|
debug_name,
|
||||||
|
self.current_scope_id.unwrap(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_block_scope(&mut self, debug_name: &str) {
|
||||||
|
self.push_scope(Scope::Block(BlockScope::new(
|
||||||
|
debug_name,
|
||||||
|
self.current_scope_id.unwrap(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_scope(&mut self) {
|
||||||
|
self.current_scope_id = self.current_scope().parent_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_scope_id(&self) -> usize {
|
||||||
|
self.current_scope_id.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_scope(&self) -> &Scope {
|
||||||
|
&self.scopes[self.current_scope_id.unwrap()]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_scope_mut(&mut self) -> &mut Scope {
|
||||||
|
&mut self.scopes[self.current_scope_id.unwrap()]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_function_symbol(
|
||||||
|
&mut self,
|
||||||
|
function_symbol: FunctionSymbol,
|
||||||
|
) -> Result<Rc<RefCell<FunctionSymbol>>, SymbolInsertError> {
|
||||||
|
let maybe_already_inserted = match self.current_scope() {
|
||||||
|
Scope::Module(module_scope) => {
|
||||||
|
find_in_module_by_name(module_scope, function_symbol.declared_name())
|
||||||
|
}
|
||||||
|
Scope::Class(class_scope) => {
|
||||||
|
find_in_class_by_name(class_scope, function_symbol.declared_name())
|
||||||
|
}
|
||||||
|
_ => panic!("Attempt to insert FunctionSymbol in incompatible scope"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(already_inserted) = maybe_already_inserted {
|
||||||
|
return Err(SymbolInsertError::AlreadyDeclared(AlreadyDeclared::new(
|
||||||
|
already_inserted,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = function_symbol.declared_name_owned();
|
||||||
|
let as_rc = Rc::new(RefCell::new(function_symbol));
|
||||||
|
let to_return = as_rc.clone();
|
||||||
|
|
||||||
|
match self.current_scope_mut() {
|
||||||
|
Scope::Module(module_scope) => {
|
||||||
|
module_scope.function_symbols_mut().insert(name, as_rc);
|
||||||
|
}
|
||||||
|
Scope::Class(class_scope) => {
|
||||||
|
class_scope.function_symbols_mut().insert(name, as_rc);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
Ok(to_return)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_parameter_symbol(
|
||||||
|
&mut self,
|
||||||
|
parameter_symbol: ParameterSymbol,
|
||||||
|
) -> Result<Rc<RefCell<ParameterSymbol>>, SymbolInsertError> {
|
||||||
|
let maybe_already_inserted = match self.current_scope() {
|
||||||
|
Scope::Function(function_scope) => {
|
||||||
|
find_in_function_by_name(function_scope, parameter_symbol.declared_name())
|
||||||
|
}
|
||||||
|
_ => panic!("Attempt to insert ParameterSymbol in incompatible scope"),
|
||||||
|
};
|
||||||
|
if let Some(already_inserted) = maybe_already_inserted {
|
||||||
|
return Err(SymbolInsertError::AlreadyDeclared(AlreadyDeclared::new(
|
||||||
|
already_inserted,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = parameter_symbol.declared_name_owned();
|
||||||
|
let as_rc = Rc::new(RefCell::new(parameter_symbol));
|
||||||
|
let to_return = as_rc.clone();
|
||||||
|
|
||||||
|
match self.current_scope_mut() {
|
||||||
|
Scope::Function(function_scope) => {
|
||||||
|
function_scope.parameter_symbols_mut().insert(name, as_rc);
|
||||||
|
}
|
||||||
|
_ => panic!("Attempt to insert ParameterSymbol in incompatible scope"),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(to_return)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_variable_symbol(
|
||||||
|
&mut self,
|
||||||
|
variable_symbol: VariableSymbol,
|
||||||
|
) -> Result<(), SymbolInsertError> {
|
||||||
|
let maybe_already_inserted = match self.current_scope() {
|
||||||
|
Scope::Block(block_scope) => {
|
||||||
|
find_in_block_by_name(block_scope, variable_symbol.declared_name())
|
||||||
|
}
|
||||||
|
_ => panic!("Attempt to insert VariableSymbol in incompatible scope"),
|
||||||
|
};
|
||||||
|
if let Some(already_inserted) = maybe_already_inserted {
|
||||||
|
return Err(SymbolInsertError::AlreadyDeclared(AlreadyDeclared::new(
|
||||||
|
already_inserted,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.current_scope_mut() {
|
||||||
|
Scope::Block(block_scope) => {
|
||||||
|
block_scope.variable_symbols_mut().insert(
|
||||||
|
variable_symbol.declared_name_owned(),
|
||||||
|
Rc::new(RefCell::new(variable_symbol)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_expressible_symbol(
|
||||||
|
&self,
|
||||||
|
scope_id: usize,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<ExpressibleSymbol> {
|
||||||
|
let mut maybe_scope = self.scopes.get(scope_id);
|
||||||
|
if maybe_scope.is_none() {
|
||||||
|
panic!("Invalid scope_id: {}", scope_id);
|
||||||
|
}
|
||||||
|
while let Some(scope) = maybe_scope {
|
||||||
|
let maybe_expressible_symbol = find_expressible_symbol(scope, name);
|
||||||
|
if maybe_expressible_symbol.is_some() {
|
||||||
|
return maybe_expressible_symbol;
|
||||||
|
} else {
|
||||||
|
maybe_scope = scope.parent_id().map(|id| &self.scopes[id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_variable_symbol(&self, scope_id: usize, name: &str) -> Rc<RefCell<VariableSymbol>> {
|
||||||
|
match &self.scopes[scope_id] {
|
||||||
|
Scope::Block(block_scope) => block_scope.variable_symbols().get(name).cloned().unwrap(),
|
||||||
|
_ => panic!("scope_id {} is not a BlockScope", scope_id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum SymbolInsertError {
|
||||||
|
AlreadyDeclared(AlreadyDeclared),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AlreadyDeclared {
|
||||||
|
symbol: Rc<RefCell<dyn Symbol>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AlreadyDeclared {
|
||||||
|
pub fn new(symbol: Rc<RefCell<dyn Symbol>>) -> Self {
|
||||||
|
Self { symbol }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbol(&self) -> &Rc<RefCell<dyn Symbol>> {
|
||||||
|
&self.symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::function_symbol::FunctionSymbol;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user