From 9747990c12cee8491184113e1d05fe54664e49bc Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Sun, 24 Jan 2021 08:06:16 -0600 Subject: [PATCH] a --- Cargo.lock | 1 + Cargo.toml | 1 + example | 4 ++ src/ast.rs | 5 +-- src/hir.rs | 34 --------------- src/hoas.rs | 106 +++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 5 ++- src/parser.lalrpop | 1 + src/utils.rs | 2 +- 9 files changed, 119 insertions(+), 40 deletions(-) delete mode 100644 src/hir.rs create mode 100644 src/hoas.rs diff --git a/Cargo.lock b/Cargo.lock index 6a77eab..04dcbe4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -324,6 +324,7 @@ dependencies = [ "lalrpop-util", "lazy_static", "parking_lot", + "petgraph", "regex", "structopt", "target-lexicon", diff --git a/Cargo.toml b/Cargo.toml index f3d0786..10e0758 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ cranelift-object = "0.69.0" lalrpop-util = "0.19.4" lazy_static = "1.4.0" parking_lot = "0.11.1" +petgraph = "0.5.1" regex = "1.4.3" structopt = "0.3.21" target-lexicon = "0.11.1" diff --git a/example b/example index 3b4499e..dce12e8 100644 --- a/example +++ b/example @@ -1,7 +1,11 @@ fn main { urmom(); +isEven(); 5 } fn urmom { 12 } + +fn isEven { isOdd } +fn isOdd { isEven } diff --git a/src/ast.rs b/src/ast.rs index 9520e70..36ed48b 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -25,6 +25,7 @@ pub enum Stmt { pub enum Expr { Seq(Vec, Box), FuncCall(Ident), + Var(Ident), Lit(Lit), } @@ -34,9 +35,7 @@ pub enum Lit { } #[derive(Debug)] -pub enum Type { - -} +pub enum Type {} #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct Ident(pub String); diff --git a/src/hir.rs b/src/hir.rs deleted file mode 100644 index 3133adc..0000000 --- a/src/hir.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::collections::HashMap; - -use crate::ast::{Program, Decl, Func, Type, Ident}; -use crate::utils::Id; - -#[derive(Debug)] -pub struct Namespaces { - funcs: HashMap, - types: HashMap, - - func_names: HashMap, - type_names: HashMap, -} - -impl Namespaces { - pub fn create(program: Program) -> Self { - let mut funcs = HashMap::new(); - let mut types = HashMap::new(); - let mut func_names = HashMap::new(); - let mut type_names = HashMap::new(); - - for decl in program.decls { - match decl { - Decl::Func(func) => { - let id = Id::default(); - func_names.insert(func.name.clone(), id); - funcs.insert(id, func); - } - } - } - - Namespaces { funcs, types, func_names, type_names } - } -} diff --git a/src/hoas.rs b/src/hoas.rs new file mode 100644 index 0000000..b01f362 --- /dev/null +++ b/src/hoas.rs @@ -0,0 +1,106 @@ +use std::collections::{HashMap, HashSet}; + +use petgraph::{algo, graphmap::DiGraphMap}; + +use crate::ast::*; +use crate::utils::Id; + +type Graph = DiGraphMap; +type Scopes = Vec>; + +#[derive(Debug)] +pub struct Namespaces { + funcs: HashMap, + types: HashMap, + + func_names: HashMap, + type_names: HashMap, +} + +impl Namespaces { + pub fn create(program: Program) -> Self { + let mut funcs = HashMap::new(); + let mut types = HashMap::new(); + let mut func_names = HashMap::new(); + let mut type_names = HashMap::new(); + + for decl in program.decls { + match decl { + Decl::Func(func) => { + let id = Id::default(); + func_names.insert(func.name.0.clone(), id); + funcs.insert(id, func); + } + } + } + + Namespaces { + funcs, + types, + func_names, + type_names, + } + } + + pub fn name_resolution(&self) { + let mut graph = Graph::new(); + + for (id, func) in self.funcs.iter() { + walk_func(&mut graph, &self, *id, func); + } + println!("graph: {:?}", graph); + + let scc = algo::tarjan_scc(&graph); + for group in scc.iter() { + println!("group: {:?}", group); + } + } +} + +fn walk_func(g: &mut Graph, n: &Namespaces, src: Id, f: &Func) { + let mut scopes = Vec::new(); + scopes.push(HashSet::new()); + for s in f.stmts.iter() { + walk_stmt(g, n, src, &mut scopes, s); + } + walk_expr(g, n, src, &mut scopes, &f.ret); + scopes.pop(); + assert!(scopes.is_empty()); +} + +fn walk_stmt(g: &mut Graph, n: &Namespaces, src: Id, sc: &mut Scopes, s: &Stmt) { + match s { + Stmt::Expr(e) | Stmt::Return(e) => walk_expr(g, n, src, sc, e), + } +} + +fn walk_expr(g: &mut Graph, n: &Namespaces, src: Id, sc: &mut Scopes, e: &Expr) { + match e { + Expr::FuncCall(id) | Expr::Var(id) => { + let id = &id.0; + let mut found = false; + for scope in sc.iter().rev() { + if scope.contains(id) { + found = true; + break; + } + } + if !found { + if let Some(target_id) = n.func_names.get(id) { + g.add_node(src); + g.add_node(*target_id); + g.add_edge(src, *target_id, ()); + } + } + } + Expr::Seq(stmts, e) => { + sc.push(HashSet::new()); + for s in stmts { + walk_stmt(g, n, src, sc, s); + } + walk_expr(g, n, src, sc, e); + sc.pop(); + } + Expr::Lit(_) => {} + } +} diff --git a/src/main.rs b/src/main.rs index f054e8e..7085f4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ mod ast; +mod hoas; mod parser; -mod hir; mod utils; use std::fs::{File, OpenOptions}; @@ -11,7 +11,7 @@ use anyhow::Result; use cranelift::prelude::*; use structopt::StructOpt; -use crate::hir::Namespaces; +use crate::hoas::Namespaces; #[derive(StructOpt)] struct Opt { @@ -35,6 +35,7 @@ fn main() -> Result<()> { let namespaces = Namespaces::create(parsed); println!("namespaces: {:?}", namespaces); + namespaces.name_resolution(); let isa = { use std::str::FromStr; diff --git a/src/parser.lalrpop b/src/parser.lalrpop index c7bbd37..c26e968 100644 --- a/src/parser.lalrpop +++ b/src/parser.lalrpop @@ -21,6 +21,7 @@ BlockExpr: Expr = "{" "}" => Expr::Seq(stmts, Box::new Expr: Expr = { "(" ")" => Expr::FuncCall(name), + Ident => Expr::Var(<>), Lit => Expr::Lit(<>), }; diff --git a/src/utils.rs b/src/utils.rs index 14ddedd..557b209 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,7 +8,7 @@ lazy_static! { static ref N: Arc> = Arc::new(Mutex::new(0)); } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Id(usize); impl Default for Id {