From 663fe00288161b86c327d503fc3631118be9cee1 Mon Sep 17 00:00:00 2001 From: Caleb Date: Fri, 7 Jul 2023 16:16:07 +1000 Subject: [PATCH] Started implementation of name resolution. Created a basic symbol table for holding identifier information --- src/frontend/errors.rs | 7 +++ src/main.rs | 12 ++++ src/name_resolution/mod.rs | 2 + src/name_resolution/name_resolver.rs | 77 +++++++++++++++++++++++++ src/name_resolution/resolution_table.rs | 49 ++++++++++++++++ 5 files changed, 147 insertions(+) create mode 100644 src/name_resolution/mod.rs create mode 100644 src/name_resolution/name_resolver.rs create mode 100644 src/name_resolution/resolution_table.rs diff --git a/src/frontend/errors.rs b/src/frontend/errors.rs index dca2ca3..d4a20b6 100644 --- a/src/frontend/errors.rs +++ b/src/frontend/errors.rs @@ -33,3 +33,10 @@ pub enum ParseError { UnknownCompilerDirective(SourceRef), TooManyErrors(SourceRef), } + +#[allow(dead_code)] +#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)] +pub enum NameResolutionError { + SymbolAlreadyExists(SourceRef), + UndefinedSymbol(SourceRef), +} diff --git a/src/main.rs b/src/main.rs index 311da50..cfa0d4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,12 +7,14 @@ use frontend::{ source::{SourceFile, SourceReporter}, token::Token, }; +use name_resolution::name_resolver::Resolver; use pir::ir::{PIRModule, PIRModulePass}; // use crate::tools::pfmt::Pfmt; mod analysis_a; mod frontend; +mod name_resolution; mod pastel; mod pir; mod tools; @@ -38,20 +40,24 @@ commands: "; #[allow(dead_code)] +#[derive(Clone, Copy)] enum Backend { PIR, // will go to PVM CPP, // will go to C++ } #[allow(dead_code)] +#[derive(Clone, Copy)] enum Stage { Lexer, Parser, PfmtFile, DependencyResolvr, + NameResolution, } #[allow(dead_code)] +#[derive(Clone, Copy)] enum Command { Compile, } @@ -111,6 +117,7 @@ fn create_config(args: Vec) -> ProtoConfig { "parse" => max_stage = Stage::Parser, "fmt" => max_stage = Stage::PfmtFile, "dep" => max_stage = Stage::DependencyResolvr, + "name" => max_stage = Stage::NameResolution, "dbg" => dbg_info = true, "help" => show_help = true, _ => {} @@ -230,4 +237,9 @@ fn main() { Err(_) => todo!(), } } + + if let Stage::NameResolution = config.max_stage { + let mut name_resolver = Resolver::new(&ir_mod); + let _res = name_resolver.process(); + } } diff --git a/src/name_resolution/mod.rs b/src/name_resolution/mod.rs new file mode 100644 index 0000000..ebbc1e6 --- /dev/null +++ b/src/name_resolution/mod.rs @@ -0,0 +1,2 @@ +pub mod name_resolver; +pub mod resolution_table; diff --git a/src/name_resolution/name_resolver.rs b/src/name_resolution/name_resolver.rs new file mode 100644 index 0000000..b2b4732 --- /dev/null +++ b/src/name_resolution/name_resolver.rs @@ -0,0 +1,77 @@ +use std::rc::Rc; + +use crate::pir::ir::{ + ExprRef, InsRef, KeyValueBindings, PIRExpr, PIRIns, PIRModule, PIRModulePass, +}; + +use super::resolution_table::{ResolutionTable, SymbolKind}; + +pub struct Resolver<'a> { + module: &'a PIRModule, + table: Rc, +} + +impl<'a> Resolver<'a> { + fn add_symbol(&mut self, identifier: String, kind: SymbolKind) -> Result<(), String> { + Rc::get_mut(&mut self.table) + .expect("Could not borrow table as mutable") + .add_symbol(identifier, kind) + } +} + +impl<'a> PIRModulePass<'a, (), (), (), Rc, String> for Resolver<'a> { + fn new(module: &'a PIRModule) -> Self { + Self { + module, + table: Rc::new(ResolutionTable::new()), + } + } + + fn process_ins(&mut self, ins: &InsRef) -> Result<(), String> { + let ins_node = self.module.ins_pool.get(&ins); + + match ins_node { + PIRIns::VariableDecl(var_name, _, init_expr, _) => { + let var_name = var_name.as_str(); + if let Some(init_expr) = init_expr { + self.process_expr(&init_expr)?; + } + + self.add_symbol(var_name, SymbolKind::Binding)?; + } + PIRIns::AssignmentIns(lhs, rhs) => { + self.process_expr(&lhs)?; + self.process_expr(&rhs)?; + } + PIRIns::ExpressionIns(expr, _) => { + self.process_expr(&expr)?; + } + n => todo!("Inst: {n:?}"), + } + + Ok(()) + } + + fn process_expr(&mut self, expr: &ExprRef) -> Result<(), String> { + let expr_node = self.module.expr_pool.get(&expr); + + match expr_node { + PIRExpr::Id(token, _) => {} + n => todo!("Expr: {n:?}"), + } + + Ok(()) + } + + fn process_pairs(&mut self, kv: &KeyValueBindings) -> Result<(), String> { + todo!() + } + + fn process(&mut self) -> Result, String> { + Ok(Rc::clone(&self.table)) + } + + fn get_module(&mut self) -> &'a PIRModule { + self.module + } +} diff --git a/src/name_resolution/resolution_table.rs b/src/name_resolution/resolution_table.rs new file mode 100644 index 0000000..c5f862e --- /dev/null +++ b/src/name_resolution/resolution_table.rs @@ -0,0 +1,49 @@ +use std::fmt::format; + +use crate::frontend::errors::NameResolutionError; + +#[derive(Clone, PartialEq, Eq)] +pub enum SymbolKind { + Binding, + Struct { field_names: Vec }, + Function, +} + +pub struct Symbol { + identifier: String, + kind: SymbolKind, +} + +pub struct ResolutionTable { + symbols: Vec, +} + +impl ResolutionTable { + pub fn new() -> Self { + Self { + symbols: Vec::new(), + } + } + + pub fn add_symbol(&mut self, identifier: String, kind: SymbolKind) -> Result<(), String> { + if self.has_symbol(&identifier, &kind) { + return Err(format!( + "Could not add symbol '{identifier}' as it was already defined" + )); + } + + self.symbols.push(Symbol { identifier, kind }); + + Ok(()) + } + + pub fn has_symbol(&self, identifier: &String, kind: &SymbolKind) -> bool { + for symbol in &self.symbols { + if symbol.kind == *kind && symbol.identifier == *identifier { + return true; + } + } + + false + } +}