a
This commit is contained in:
parent
cbd9dc2986
commit
9747990c12
9 changed files with 119 additions and 40 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -324,6 +324,7 @@ dependencies = [
|
||||||
"lalrpop-util",
|
"lalrpop-util",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"petgraph",
|
||||||
"regex",
|
"regex",
|
||||||
"structopt",
|
"structopt",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
|
|
|
@ -12,6 +12,7 @@ cranelift-object = "0.69.0"
|
||||||
lalrpop-util = "0.19.4"
|
lalrpop-util = "0.19.4"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
parking_lot = "0.11.1"
|
parking_lot = "0.11.1"
|
||||||
|
petgraph = "0.5.1"
|
||||||
regex = "1.4.3"
|
regex = "1.4.3"
|
||||||
structopt = "0.3.21"
|
structopt = "0.3.21"
|
||||||
target-lexicon = "0.11.1"
|
target-lexicon = "0.11.1"
|
||||||
|
|
4
example
4
example
|
@ -1,7 +1,11 @@
|
||||||
fn main
|
fn main
|
||||||
{
|
{
|
||||||
urmom();
|
urmom();
|
||||||
|
isEven();
|
||||||
5
|
5
|
||||||
}
|
}
|
||||||
|
|
||||||
fn urmom { 12 }
|
fn urmom { 12 }
|
||||||
|
|
||||||
|
fn isEven { isOdd }
|
||||||
|
fn isOdd { isEven }
|
||||||
|
|
|
@ -25,6 +25,7 @@ pub enum Stmt {
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Seq(Vec<Stmt>, Box<Expr>),
|
Seq(Vec<Stmt>, Box<Expr>),
|
||||||
FuncCall(Ident),
|
FuncCall(Ident),
|
||||||
|
Var(Ident),
|
||||||
Lit(Lit),
|
Lit(Lit),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,9 +35,7 @@ pub enum Lit {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Type {
|
pub enum Type {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
pub struct Ident(pub String);
|
pub struct Ident(pub String);
|
||||||
|
|
34
src/hir.rs
34
src/hir.rs
|
@ -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<Id, Func>,
|
|
||||||
types: HashMap<Id, Type>,
|
|
||||||
|
|
||||||
func_names: HashMap<Ident, Id>,
|
|
||||||
type_names: HashMap<Ident, Id>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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 }
|
|
||||||
}
|
|
||||||
}
|
|
106
src/hoas.rs
Normal file
106
src/hoas.rs
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use petgraph::{algo, graphmap::DiGraphMap};
|
||||||
|
|
||||||
|
use crate::ast::*;
|
||||||
|
use crate::utils::Id;
|
||||||
|
|
||||||
|
type Graph = DiGraphMap<Id, ()>;
|
||||||
|
type Scopes = Vec<HashSet<String>>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Namespaces {
|
||||||
|
funcs: HashMap<Id, Func>,
|
||||||
|
types: HashMap<Id, Type>,
|
||||||
|
|
||||||
|
func_names: HashMap<String, Id>,
|
||||||
|
type_names: HashMap<String, Id>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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(_) => {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
mod ast;
|
mod ast;
|
||||||
|
mod hoas;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod hir;
|
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
|
@ -11,7 +11,7 @@ use anyhow::Result;
|
||||||
use cranelift::prelude::*;
|
use cranelift::prelude::*;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use crate::hir::Namespaces;
|
use crate::hoas::Namespaces;
|
||||||
|
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
|
@ -35,6 +35,7 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
let namespaces = Namespaces::create(parsed);
|
let namespaces = Namespaces::create(parsed);
|
||||||
println!("namespaces: {:?}", namespaces);
|
println!("namespaces: {:?}", namespaces);
|
||||||
|
namespaces.name_resolution();
|
||||||
|
|
||||||
let isa = {
|
let isa = {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
|
@ -21,6 +21,7 @@ BlockExpr: Expr = "{" <stmts:Stmt*> <expr:Expr> "}" => Expr::Seq(stmts, Box::new
|
||||||
|
|
||||||
Expr: Expr = {
|
Expr: Expr = {
|
||||||
<name:Ident> "(" ")" => Expr::FuncCall(name),
|
<name:Ident> "(" ")" => Expr::FuncCall(name),
|
||||||
|
Ident => Expr::Var(<>),
|
||||||
Lit => Expr::Lit(<>),
|
Lit => Expr::Lit(<>),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ lazy_static! {
|
||||||
static ref N: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
|
static ref N: Arc<Mutex<usize>> = 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);
|
pub struct Id(usize);
|
||||||
|
|
||||||
impl Default for Id {
|
impl Default for Id {
|
||||||
|
|
Loading…
Add table
Reference in a new issue