Assembling directly from AST.
This commit is contained in:
parent
e5e1647b70
commit
6593a1cfd1
@ -2,12 +2,15 @@ use crate::asm::asm_instruction::AsmInstruction;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AsmBlock {
|
||||
id: usize,
|
||||
name: String,
|
||||
instructions: Vec<AsmInstruction>,
|
||||
}
|
||||
|
||||
impl AsmBlock {
|
||||
pub fn new(id: usize, instructions: Vec<AsmInstruction>) -> Self {
|
||||
Self { id, instructions }
|
||||
pub fn new(name: &str, instructions: Vec<AsmInstruction>) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
instructions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ pub enum AsmInstruction {
|
||||
pub enum Operand {
|
||||
IntegerLiteral(i64),
|
||||
Register(usize),
|
||||
StackFrameOffset(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@ -5,8 +5,7 @@ pub mod asm_instruction;
|
||||
#[cfg(test)]
|
||||
mod smoke_tests {
|
||||
use crate::asm::asm_function::AsmFunction;
|
||||
use crate::ir::assemble_context::AssembleContext;
|
||||
use crate::ir::Ir;
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::parser::parse_compilation_unit;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
|
||||
@ -16,17 +15,7 @@ mod smoke_tests {
|
||||
compilation_unit.gather_declared_names(&mut symbol_table);
|
||||
compilation_unit.check_name_usages(&symbol_table);
|
||||
compilation_unit.type_check(&symbol_table);
|
||||
let irs = compilation_unit.lower_to_ir();
|
||||
let mut asm_functions = vec![];
|
||||
for ir in &irs {
|
||||
match ir {
|
||||
Ir::Function(ir_function) => {
|
||||
asm_functions.push(ir_function.assemble(&mut AssembleContext::new()));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
asm_functions
|
||||
compilation_unit.assemble(&symbol_table, &mut ConstantsTable::new())
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
114
dmc-lib/src/ast/assemble_context.rs
Normal file
114
dmc-lib/src/ast/assemble_context.rs
Normal file
@ -0,0 +1,114 @@
|
||||
use crate::asm::asm_block::AsmBlock;
|
||||
use crate::asm::asm_function::AsmFunction;
|
||||
use crate::asm::asm_instruction::AsmInstruction;
|
||||
use crate::source_range::SourceRange;
|
||||
|
||||
pub struct AssembleContext {
|
||||
functions: Vec<AsmFunction>,
|
||||
current_function: Option<FunctionAssembler>,
|
||||
}
|
||||
|
||||
impl AssembleContext {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
functions: vec![],
|
||||
current_function: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_functions(&mut self) -> Vec<AsmFunction> {
|
||||
std::mem::take(&mut self.functions)
|
||||
}
|
||||
|
||||
pub fn new_function(&mut self, name: &str, source_range: &SourceRange) {
|
||||
self.current_function = Some(FunctionAssembler::new(name, source_range));
|
||||
}
|
||||
|
||||
pub fn complete_function(&mut self) {
|
||||
let mut function_assembler = self.current_function.take().unwrap();
|
||||
function_assembler.complete_block();
|
||||
let asm_function = function_assembler.result();
|
||||
self.functions.push(asm_function);
|
||||
}
|
||||
|
||||
pub fn new_block(&mut self, name: &str) {
|
||||
self.current_function.as_mut().unwrap().new_block(name);
|
||||
}
|
||||
|
||||
pub fn new_local_register(&mut self) -> usize {
|
||||
self.current_function.as_mut().unwrap().new_local_register()
|
||||
}
|
||||
|
||||
pub fn instruction(&mut self, to_add: AsmInstruction) {
|
||||
self.current_function.as_mut().unwrap().instruction(to_add);
|
||||
}
|
||||
}
|
||||
|
||||
struct FunctionAssembler {
|
||||
name: String,
|
||||
source_range: SourceRange,
|
||||
blocks: Vec<AsmBlock>,
|
||||
current_block: Option<BlockAssembler>,
|
||||
local_register_counter: usize,
|
||||
}
|
||||
|
||||
impl FunctionAssembler {
|
||||
fn new(name: &str, source_range: &SourceRange) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
source_range: source_range.clone(),
|
||||
blocks: vec![],
|
||||
current_block: None,
|
||||
local_register_counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_block(&mut self, name: &str) {
|
||||
let maybe_block_assembler = self.current_block.take();
|
||||
if let Some(mut block_assembler) = maybe_block_assembler {
|
||||
self.blocks.push(block_assembler.result());
|
||||
}
|
||||
self.current_block = Some(BlockAssembler::new(name))
|
||||
}
|
||||
|
||||
fn complete_block(&mut self) {
|
||||
let mut block_assembler = self.current_block.take().unwrap();
|
||||
self.blocks.push(block_assembler.result());
|
||||
}
|
||||
|
||||
fn result(&mut self) -> AsmFunction {
|
||||
AsmFunction::new(&self.name, std::mem::take(&mut self.blocks))
|
||||
}
|
||||
|
||||
fn new_local_register(&mut self) -> usize {
|
||||
let register = self.local_register_counter;
|
||||
self.local_register_counter += 1;
|
||||
register
|
||||
}
|
||||
|
||||
fn instruction(&mut self, to_add: AsmInstruction) {
|
||||
self.current_block.as_mut().unwrap().instruction(to_add);
|
||||
}
|
||||
}
|
||||
|
||||
struct BlockAssembler {
|
||||
name: String,
|
||||
instructions: Vec<AsmInstruction>,
|
||||
}
|
||||
|
||||
impl BlockAssembler {
|
||||
fn new(name: &str) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
instructions: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn instruction(&mut self, to_add: AsmInstruction) {
|
||||
self.instructions.push(to_add);
|
||||
}
|
||||
|
||||
fn result(&mut self) -> AsmBlock {
|
||||
AsmBlock::new(&self.name, std::mem::take(&mut self.instructions))
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,15 @@
|
||||
use crate::asm::asm_instruction::{
|
||||
AsmInstruction, InvokePlatformStatic, LoadConstant, Operand, Push,
|
||||
};
|
||||
use crate::ast::assemble_context::AssembleContext;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::function::FunctionLoweringContext;
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ir::ir_call::IrCall;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::ExpressibleSymbol;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
use crate::type_info::TypeInfo;
|
||||
|
||||
@ -90,6 +96,63 @@ impl Call {
|
||||
IrExpression::Call(IrCall::new(function_name, arguments))
|
||||
}
|
||||
|
||||
pub fn assemble(
|
||||
&self,
|
||||
context: &mut AssembleContext,
|
||||
symbol_table: &SymbolTable,
|
||||
constants_table: &mut ConstantsTable,
|
||||
) {
|
||||
// push all args
|
||||
for argument in &self.arguments {
|
||||
match argument {
|
||||
Expression::Call(call) => {
|
||||
call.assemble(context, symbol_table, constants_table); // will leave return val on stack
|
||||
}
|
||||
Expression::IntegerLiteral(integer_literal) => {
|
||||
context.instruction(AsmInstruction::Push(Push::new(Operand::IntegerLiteral(
|
||||
integer_literal.value(),
|
||||
))));
|
||||
}
|
||||
Expression::String(string_literal) => {
|
||||
let name = constants_table.insert_string(string_literal.content());
|
||||
let temp_register = context.new_local_register();
|
||||
context.instruction(AsmInstruction::LoadConstant(LoadConstant::new(
|
||||
&name,
|
||||
temp_register,
|
||||
)));
|
||||
context.instruction(AsmInstruction::Push(Push::new(Operand::Register(
|
||||
temp_register,
|
||||
))));
|
||||
}
|
||||
Expression::Identifier(identifier) => match identifier.expressible_symbol() {
|
||||
ExpressibleSymbol::Function(_) => {
|
||||
panic!("Pushing function symbols not supported.")
|
||||
}
|
||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
||||
context.instruction(AsmInstruction::Push(Push::new(
|
||||
Operand::StackFrameOffset(
|
||||
parameter_symbol.borrow().stack_frame_offset(),
|
||||
),
|
||||
)));
|
||||
}
|
||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||
context.instruction(AsmInstruction::Push(Push::new(Operand::Register(
|
||||
variable_symbol.borrow().register(),
|
||||
))))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
let function_name = match self.callee() {
|
||||
Expression::Identifier(identifier) => identifier.name(),
|
||||
_ => panic!("Calling things other than identifiers not yet supported."),
|
||||
};
|
||||
|
||||
context.instruction(AsmInstruction::InvokePlatformStatic(
|
||||
InvokePlatformStatic::new(function_name),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn source_range(&self) -> &SourceRange {
|
||||
&self.source_range
|
||||
}
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
use crate::asm::asm_function::AsmFunction;
|
||||
use crate::ast::assemble_context::AssembleContext;
|
||||
use crate::ast::function::Function;
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ir::Ir;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
@ -49,4 +52,16 @@ impl CompilationUnit {
|
||||
}
|
||||
irs
|
||||
}
|
||||
|
||||
pub fn assemble(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
constants_table: &mut ConstantsTable,
|
||||
) -> Vec<AsmFunction> {
|
||||
let mut context = AssembleContext::new();
|
||||
for function in &self.functions {
|
||||
function.assemble(&mut context, symbol_table, constants_table);
|
||||
}
|
||||
context.take_functions()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
use crate::ast::assemble_context::AssembleContext;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::function::FunctionLoweringContext;
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
@ -49,4 +51,18 @@ impl ExpressionStatement {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assemble(
|
||||
&self,
|
||||
context: &mut AssembleContext,
|
||||
symbol_table: &SymbolTable,
|
||||
constants_table: &mut ConstantsTable,
|
||||
) {
|
||||
match self.expression.as_ref() {
|
||||
Expression::Call(call) => {
|
||||
call.assemble(context, symbol_table, constants_table);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
use crate::ast::assemble_context::AssembleContext;
|
||||
use crate::ast::statement::Statement;
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ir::Ir;
|
||||
use crate::ir::ir_constant::IrConstant;
|
||||
@ -93,6 +95,20 @@ impl Function {
|
||||
irs.push(Ir::Function(ir_function));
|
||||
irs
|
||||
}
|
||||
|
||||
pub fn assemble(
|
||||
&self,
|
||||
context: &mut AssembleContext,
|
||||
symbol_table: &SymbolTable,
|
||||
constants_table: &mut ConstantsTable,
|
||||
) {
|
||||
context.new_function(&self.declared_name, &self.declared_name_source_range);
|
||||
context.new_block(&format!("{}_enter", self.declared_name));
|
||||
for statement in &self.statements {
|
||||
statement.assemble(context, symbol_table, constants_table);
|
||||
}
|
||||
context.complete_function();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FunctionLoweringContext {
|
||||
|
||||
@ -56,11 +56,19 @@ impl Identifier {
|
||||
ExpressibleSymbol::Function(function_symbol) => {
|
||||
TypeInfo::Function(function_symbol.clone())
|
||||
}
|
||||
ExpressibleSymbol::Parameter(parameter_symbol) => parameter_symbol.type_info().clone(),
|
||||
ExpressibleSymbol::Variable(variable_symbol) => variable_symbol.type_info().clone(),
|
||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
||||
parameter_symbol.borrow().type_info().clone()
|
||||
}
|
||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||
variable_symbol.borrow().type_info().clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expressible_symbol(&self) -> &ExpressibleSymbol {
|
||||
self.expressible_symbol.as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn lower_to_ir(&self, context: &mut FunctionLoweringContext) -> IrExpression {
|
||||
IrExpression::Variable(IrVariable::new(self.name()))
|
||||
}
|
||||
|
||||
@ -1,17 +1,21 @@
|
||||
use crate::asm::asm_instruction::{AsmInstruction, LoadConstant, Move, Operand, Pop};
|
||||
use crate::ast::assemble_context::AssembleContext;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::function::FunctionLoweringContext;
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
use crate::ir::ir_variable::IrVariable;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::VariableSymbol;
|
||||
use crate::symbol::{ExpressibleSymbol, VariableSymbol};
|
||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||
|
||||
pub struct LetStatement {
|
||||
declared_name: String,
|
||||
declared_name_source_range: SourceRange,
|
||||
initializer: Box<Expression>,
|
||||
scope_id: Option<usize>,
|
||||
}
|
||||
|
||||
impl LetStatement {
|
||||
@ -24,6 +28,7 @@ impl LetStatement {
|
||||
declared_name: declared_name.to_string(),
|
||||
declared_name_source_range,
|
||||
initializer: initializer.into(),
|
||||
scope_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,6 +65,7 @@ impl LetStatement {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.scope_id = Some(symbol_table.current_scope_id());
|
||||
diagnostics
|
||||
}
|
||||
|
||||
@ -79,4 +85,62 @@ impl LetStatement {
|
||||
let assign_statement = IrAssign::new(destination, data);
|
||||
context.add_statement(IrStatement::Assign(assign_statement));
|
||||
}
|
||||
|
||||
pub fn assemble(
|
||||
&self,
|
||||
context: &mut AssembleContext,
|
||||
symbol_table: &SymbolTable,
|
||||
constants_table: &mut ConstantsTable,
|
||||
) {
|
||||
let destination_register = context.new_local_register();
|
||||
|
||||
// save register to symbol
|
||||
let variable_symbol =
|
||||
symbol_table.get_variable_symbol(self.scope_id.unwrap(), self.declared_name());
|
||||
variable_symbol
|
||||
.borrow_mut()
|
||||
.set_register(destination_register);
|
||||
|
||||
match self.initializer() {
|
||||
Expression::Call(call) => {
|
||||
call.assemble(context, symbol_table, constants_table);
|
||||
context.instruction(AsmInstruction::Pop(Pop::new(destination_register)));
|
||||
}
|
||||
Expression::IntegerLiteral(integer_literal) => {
|
||||
context.instruction(AsmInstruction::Move(Move::new(
|
||||
Operand::IntegerLiteral(integer_literal.value()),
|
||||
destination_register,
|
||||
)));
|
||||
}
|
||||
Expression::String(string_literal) => {
|
||||
let name = constants_table.insert_string(string_literal.content());
|
||||
context.instruction(AsmInstruction::LoadConstant(LoadConstant::new(
|
||||
&name,
|
||||
destination_register,
|
||||
)));
|
||||
}
|
||||
Expression::Identifier(identifier) => {
|
||||
let expressible_symbol = identifier.expressible_symbol();
|
||||
match expressible_symbol {
|
||||
ExpressibleSymbol::Function(_) => {
|
||||
panic!("Moving functions to registers not yet supported");
|
||||
}
|
||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
||||
context.instruction(AsmInstruction::Move(Move::new(
|
||||
Operand::StackFrameOffset(
|
||||
parameter_symbol.borrow().stack_frame_offset(),
|
||||
),
|
||||
destination_register,
|
||||
)));
|
||||
}
|
||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||
context.instruction(AsmInstruction::Move(Move::new(
|
||||
Operand::Register(variable_symbol.borrow().register()),
|
||||
destination_register,
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
mod assemble_context;
|
||||
pub mod call;
|
||||
pub mod compilation_unit;
|
||||
pub mod expression;
|
||||
@ -12,6 +13,7 @@ pub mod string_literal;
|
||||
|
||||
#[cfg(test)]
|
||||
mod name_tests {
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::ir::Ir;
|
||||
use crate::ir::assemble_context::AssembleContext;
|
||||
use crate::parser::parse_compilation_unit;
|
||||
@ -29,18 +31,10 @@ mod name_tests {
|
||||
0
|
||||
);
|
||||
assert_eq!(compilation_unit.check_name_usages(&symbol_table).len(), 0);
|
||||
let irs = compilation_unit.lower_to_ir();
|
||||
for ir in &irs {
|
||||
println!("{:#?}", ir);
|
||||
}
|
||||
for ir in &irs {
|
||||
match ir {
|
||||
Ir::Function(ir_function) => {
|
||||
let asm_function = ir_function.assemble(&mut AssembleContext::new());
|
||||
println!("{:#?}", asm_function);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let mut constants_table = ConstantsTable::new();
|
||||
let asm_functions = compilation_unit.assemble(&symbol_table, &mut constants_table);
|
||||
for asm_function in &asm_functions {
|
||||
println!("{:#?}", asm_function);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
use crate::ast::assemble_context::AssembleContext;
|
||||
use crate::ast::expression_statement::ExpressionStatement;
|
||||
use crate::ast::function::FunctionLoweringContext;
|
||||
use crate::ast::let_statement::LetStatement;
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
|
||||
@ -47,4 +49,20 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assemble(
|
||||
&self,
|
||||
context: &mut AssembleContext,
|
||||
symbol_table: &SymbolTable,
|
||||
constants_table: &mut ConstantsTable,
|
||||
) {
|
||||
match self {
|
||||
Statement::Let(let_statement) => {
|
||||
let_statement.assemble(context, symbol_table, constants_table);
|
||||
}
|
||||
Statement::Expression(expression_statement) => {
|
||||
expression_statement.assemble(context, symbol_table, constants_table);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
dmc-lib/src/constants_table.rs
Normal file
22
dmc-lib/src/constants_table.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct ConstantsTable {
|
||||
string_counter: usize,
|
||||
strings_to_names: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl ConstantsTable {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
string_counter: 0,
|
||||
strings_to_names: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_string(&mut self, s: &str) -> String {
|
||||
let name = format!("s_{}", self.string_counter);
|
||||
self.string_counter += 1;
|
||||
self.strings_to_names.insert(s.into(), name.clone());
|
||||
name
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@ impl IrFunction {
|
||||
for statement in &self.statements {
|
||||
instructions.append(&mut statement.assemble(context));
|
||||
}
|
||||
let blocks = vec![AsmBlock::new(0, instructions)];
|
||||
let blocks = vec![AsmBlock::new("oops", instructions)];
|
||||
AsmFunction::new(&self.name, blocks)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
mod asm;
|
||||
mod ast;
|
||||
mod constants_table;
|
||||
mod diagnostic;
|
||||
mod ir;
|
||||
mod lexer;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::symbol::{FunctionSymbol, ParameterSymbol, VariableSymbol};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -6,8 +7,8 @@ pub struct Scope {
|
||||
debug_name: String,
|
||||
parent_id: Option<usize>,
|
||||
function_symbols: HashMap<Rc<str>, Rc<FunctionSymbol>>,
|
||||
parameter_symbols: HashMap<Rc<str>, Rc<ParameterSymbol>>,
|
||||
variable_symbols: HashMap<Rc<str>, Rc<VariableSymbol>>,
|
||||
parameter_symbols: HashMap<Rc<str>, Rc<RefCell<ParameterSymbol>>>,
|
||||
variable_symbols: HashMap<Rc<str>, Rc<RefCell<VariableSymbol>>>,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
@ -29,19 +30,19 @@ impl Scope {
|
||||
&mut self.function_symbols
|
||||
}
|
||||
|
||||
pub fn parameter_symbols(&self) -> &HashMap<Rc<str>, Rc<ParameterSymbol>> {
|
||||
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<ParameterSymbol>> {
|
||||
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<VariableSymbol>> {
|
||||
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<VariableSymbol>> {
|
||||
pub fn variable_symbols_mut(&mut self) -> &mut HashMap<Rc<str>, Rc<RefCell<VariableSymbol>>> {
|
||||
&mut self.variable_symbols
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SourceRange {
|
||||
start: usize,
|
||||
end: usize,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::type_info::TypeInfo;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct FunctionSymbol {
|
||||
@ -34,6 +35,7 @@ impl FunctionSymbol {
|
||||
pub struct ParameterSymbol {
|
||||
name: Rc<str>,
|
||||
type_info: TypeInfo,
|
||||
stack_frame_offset: Option<usize>,
|
||||
}
|
||||
|
||||
impl ParameterSymbol {
|
||||
@ -41,6 +43,7 @@ impl ParameterSymbol {
|
||||
Self {
|
||||
name: name.into(),
|
||||
type_info,
|
||||
stack_frame_offset: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,11 +58,20 @@ impl ParameterSymbol {
|
||||
pub fn type_info(&self) -> &TypeInfo {
|
||||
&self.type_info
|
||||
}
|
||||
|
||||
pub fn set_stack_frame_offset(&mut self, offset: usize) {
|
||||
self.stack_frame_offset = Some(offset);
|
||||
}
|
||||
|
||||
pub fn stack_frame_offset(&self) -> usize {
|
||||
self.stack_frame_offset.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VariableSymbol {
|
||||
name: Rc<str>,
|
||||
type_info: TypeInfo,
|
||||
register: Option<usize>,
|
||||
}
|
||||
|
||||
impl VariableSymbol {
|
||||
@ -67,6 +79,7 @@ impl VariableSymbol {
|
||||
Self {
|
||||
name: name.into(),
|
||||
type_info,
|
||||
register: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,10 +94,18 @@ impl VariableSymbol {
|
||||
pub fn type_info(&self) -> &TypeInfo {
|
||||
&self.type_info
|
||||
}
|
||||
|
||||
pub fn set_register(&mut self, register: usize) {
|
||||
self.register = Some(register);
|
||||
}
|
||||
|
||||
pub fn register(&self) -> usize {
|
||||
self.register.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ExpressibleSymbol {
|
||||
Function(Rc<FunctionSymbol>),
|
||||
Parameter(Rc<ParameterSymbol>),
|
||||
Variable(Rc<VariableSymbol>),
|
||||
Parameter(Rc<RefCell<ParameterSymbol>>),
|
||||
Variable(Rc<RefCell<VariableSymbol>>),
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use crate::scope::Scope;
|
||||
use crate::symbol::{ExpressibleSymbol, FunctionSymbol, ParameterSymbol, VariableSymbol};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct SymbolTable {
|
||||
@ -71,9 +72,10 @@ impl SymbolTable {
|
||||
parameter_symbol.name(),
|
||||
)));
|
||||
}
|
||||
self.current_scope_mut()
|
||||
.parameter_symbols_mut()
|
||||
.insert(parameter_symbol.name_owned(), Rc::new(parameter_symbol));
|
||||
self.current_scope_mut().parameter_symbols_mut().insert(
|
||||
parameter_symbol.name_owned(),
|
||||
Rc::new(RefCell::new(parameter_symbol)),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -86,9 +88,10 @@ impl SymbolTable {
|
||||
variable_symbol.name(),
|
||||
)));
|
||||
}
|
||||
self.current_scope_mut()
|
||||
.variable_symbols_mut()
|
||||
.insert(variable_symbol.name_owned(), Rc::new(variable_symbol));
|
||||
self.current_scope_mut().variable_symbols_mut().insert(
|
||||
variable_symbol.name_owned(),
|
||||
Rc::new(RefCell::new(variable_symbol)),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -125,6 +128,11 @@ impl SymbolTable {
|
||||
}
|
||||
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 {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user