add program into edge
This commit is contained in:
6
src/wasm-lib/kcl/src/diff/mod.rs
Normal file
6
src/wasm-lib/kcl/src/diff/mod.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
mod walk;
|
||||||
|
|
||||||
|
// use crate::{
|
||||||
|
// parsing::ast::types,
|
||||||
|
// walk::{Node, Visitable, Visitor},
|
||||||
|
// };
|
||||||
1
src/wasm-lib/kcl/src/diff/walk.rs
Normal file
1
src/wasm-lib/kcl/src/diff/walk.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
@ -57,6 +57,7 @@ macro_rules! eprint {
|
|||||||
static ALLOC: dhat::Alloc = dhat::Alloc;
|
static ALLOC: dhat::Alloc = dhat::Alloc;
|
||||||
|
|
||||||
mod coredump;
|
mod coredump;
|
||||||
|
mod diff;
|
||||||
mod docs;
|
mod docs;
|
||||||
mod engine;
|
mod engine;
|
||||||
mod errors;
|
mod errors;
|
||||||
|
|||||||
@ -7,10 +7,18 @@ use crate::{
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
///
|
///
|
||||||
type Declaration<'tree> = (Node<'tree>, &'tree types::Identifier);
|
type Declaration<'tree> = (
|
||||||
|
types::NodeRef<'tree, types::Program>,
|
||||||
|
Node<'tree>,
|
||||||
|
&'tree types::Identifier,
|
||||||
|
);
|
||||||
|
|
||||||
///
|
///
|
||||||
type Reference<'tree> = (Node<'tree>, &'tree types::Identifier);
|
type Reference<'tree> = (
|
||||||
|
types::NodeRef<'tree, types::Program>,
|
||||||
|
Node<'tree>,
|
||||||
|
&'tree types::Identifier,
|
||||||
|
);
|
||||||
|
|
||||||
///
|
///
|
||||||
type RefEdge<'tree> = (Option<Declaration<'tree>>, Reference<'tree>);
|
type RefEdge<'tree> = (Option<Declaration<'tree>>, Reference<'tree>);
|
||||||
@ -18,6 +26,9 @@ type RefEdge<'tree> = (Option<Declaration<'tree>>, Reference<'tree>);
|
|||||||
///
|
///
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Scope<'tree> {
|
pub struct Scope<'tree> {
|
||||||
|
///
|
||||||
|
pub program: types::NodeRef<'tree, types::Program>,
|
||||||
|
|
||||||
///
|
///
|
||||||
pub declarations: Vec<Declaration<'tree>>,
|
pub declarations: Vec<Declaration<'tree>>,
|
||||||
|
|
||||||
@ -29,8 +40,9 @@ pub struct Scope<'tree> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tree> Scope<'tree> {
|
impl<'tree> Scope<'tree> {
|
||||||
pub fn new() -> Self {
|
pub fn new(program: types::NodeRef<'tree, types::Program>) -> Self {
|
||||||
Scope {
|
Scope {
|
||||||
|
program,
|
||||||
declarations: vec![],
|
declarations: vec![],
|
||||||
references: vec![],
|
references: vec![],
|
||||||
children: vec![],
|
children: vec![],
|
||||||
@ -42,26 +54,29 @@ impl<'tree> Scope<'tree> {
|
|||||||
let mut unmatched_refs = self.references.clone();
|
let mut unmatched_refs = self.references.clone();
|
||||||
|
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
for (declaration, (ref_node, ref_id)) in child.edges() {
|
for (declaration, (ref_program, ref_node, ref_id)) in child.edges() {
|
||||||
match declaration {
|
match declaration {
|
||||||
Some((decl_node, decl_id)) => {
|
Some((decl_program, decl_node, decl_id)) => {
|
||||||
edges.push((Some((decl_node.clone(), decl_id)), (ref_node.clone(), ref_id)));
|
edges.push((
|
||||||
|
Some((decl_program, decl_node.clone(), decl_id)),
|
||||||
|
(ref_program, ref_node.clone(), ref_id),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
unmatched_refs.push((ref_node.clone(), ref_id));
|
unmatched_refs.push((ref_program, ref_node.clone(), ref_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ref_node, ref_id) in unmatched_refs.into_iter() {
|
for (ref_program, ref_node, ref_id) in unmatched_refs.into_iter() {
|
||||||
edges.push((
|
edges.push((
|
||||||
self.declarations
|
self.declarations
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, decl_id)| decl_id.name == ref_id.name)
|
.filter(|(_, _, decl_id)| decl_id.name == ref_id.name)
|
||||||
.cloned()
|
.cloned()
|
||||||
.next(),
|
.next(),
|
||||||
(ref_node.clone(), ref_id),
|
(ref_program, ref_node.clone(), ref_id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,9 +91,9 @@ pub struct ScopeVisitor<'tree> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tree> ScopeVisitor<'tree> {
|
impl<'tree> ScopeVisitor<'tree> {
|
||||||
pub fn new() -> Self {
|
pub fn new(program: types::NodeRef<'tree, types::Program>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
scope: Arc::new(Mutex::new(Scope::new())),
|
scope: Arc::new(Mutex::new(Scope::new(program))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,8 +102,8 @@ impl<'tree> Visitor<'tree> for ScopeVisitor<'tree> {
|
|||||||
type Error = std::convert::Infallible;
|
type Error = std::convert::Infallible;
|
||||||
|
|
||||||
fn visit_node(&self, node: Node<'tree>) -> Result<bool, Self::Error> {
|
fn visit_node(&self, node: Node<'tree>) -> Result<bool, Self::Error> {
|
||||||
if let Node::Program(_program) = node {
|
if let Node::Program(program) = node {
|
||||||
let csv = ScopeVisitor::new();
|
let csv = ScopeVisitor::new(program);
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
child.visit(csv.clone())?;
|
child.visit(csv.clone())?;
|
||||||
}
|
}
|
||||||
@ -103,18 +118,19 @@ impl<'tree> Visitor<'tree> for ScopeVisitor<'tree> {
|
|||||||
|
|
||||||
match node {
|
match node {
|
||||||
Node::VariableDeclaration(vd) => {
|
Node::VariableDeclaration(vd) => {
|
||||||
// process and return
|
let program = self.scope.lock().unwrap().program;
|
||||||
self.scope
|
self.scope
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.declarations
|
.declarations
|
||||||
.push((node.clone(), &vd.declaration.id));
|
.push((program, node.clone(), &vd.declaration.id));
|
||||||
|
|
||||||
let node: Node = (&vd.declaration.init).into();
|
let node: Node = (&vd.declaration.init).into();
|
||||||
node.visit(self.clone())?;
|
node.visit(self.clone())?;
|
||||||
}
|
}
|
||||||
Node::Identifier(id) => {
|
Node::Identifier(id) => {
|
||||||
self.scope.lock().unwrap().references.push((node.clone(), &id));
|
let program = self.scope.lock().unwrap().program;
|
||||||
|
self.scope.lock().unwrap().references.push((program, node.clone(), &id));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
@ -127,21 +143,15 @@ impl<'tree> Visitor<'tree> for ScopeVisitor<'tree> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_refgraph<'a, 'tree>(node: Node<'tree>) -> Result<Scope<'tree>, std::convert::Infallible> {
|
pub fn extract_refgraph<'a, 'tree>(
|
||||||
let sv = ScopeVisitor::new();
|
program: types::NodeRef<'tree, types::Program>,
|
||||||
|
) -> Result<Scope<'tree>, std::convert::Infallible> {
|
||||||
|
let sv = ScopeVisitor::new(program);
|
||||||
|
let node: Node = (program).into();
|
||||||
|
|
||||||
match node {
|
|
||||||
Node::Program(_) => {
|
|
||||||
// here we can avoid walking the root since that's going to create
|
|
||||||
// a new scope.
|
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
child.visit(sv.clone())?;
|
child.visit(sv.clone())?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
node.visit(sv.clone())?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let x = sv.scope.lock().unwrap().clone();
|
let x = sv.scope.lock().unwrap().clone();
|
||||||
Ok(x)
|
Ok(x)
|
||||||
@ -171,18 +181,18 @@ fn myfn = () => {
|
|||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
let refgraph = extract_refgraph((&program).into()).unwrap();
|
let refgraph = extract_refgraph(&program).unwrap();
|
||||||
|
|
||||||
let edges = refgraph.edges().into_iter().collect::<Vec<_>>();
|
let edges = refgraph.edges().into_iter().collect::<Vec<_>>();
|
||||||
assert_eq!(edges.len(), 3);
|
assert_eq!(edges.len(), 3);
|
||||||
|
|
||||||
// sin is a global so we are chilin
|
// sin is a global so we are chilin
|
||||||
let (decl, (_ref_node, ref_id)) = edges.get(2).unwrap();
|
let (decl, (_ref_prog, _ref_node, ref_id)) = edges.get(2).unwrap();
|
||||||
assert_eq!("sin", ref_id.name);
|
assert_eq!("sin", ref_id.name);
|
||||||
assert!(decl.is_none());
|
assert!(decl.is_none());
|
||||||
|
|
||||||
// myfn's foo
|
// myfn's foo
|
||||||
let (decl, (_ref_node, ref_id)) = edges.get(1).unwrap();
|
let (decl, (_ref_prog, _ref_node, ref_id)) = edges.get(1).unwrap();
|
||||||
assert_eq!("foo", ref_id.name);
|
assert_eq!("foo", ref_id.name);
|
||||||
assert!(decl.is_some());
|
assert!(decl.is_some());
|
||||||
// todo: check this is actually refering to the parent scope foo
|
// todo: check this is actually refering to the parent scope foo
|
||||||
@ -202,7 +212,7 @@ fn myfn = () => {
|
|||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
let refgraph = extract_refgraph((&program).into()).unwrap();
|
let refgraph = extract_refgraph(&program).unwrap();
|
||||||
|
|
||||||
assert_eq!(3, refgraph.declarations.len());
|
assert_eq!(3, refgraph.declarations.len());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -210,7 +220,7 @@ fn myfn = () => {
|
|||||||
refgraph
|
refgraph
|
||||||
.declarations
|
.declarations
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, id)| id.name.as_str())
|
.map(|(_, _, id)| id.name.as_str())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.as_slice()
|
.as_slice()
|
||||||
);
|
);
|
||||||
@ -221,7 +231,7 @@ fn myfn = () => {
|
|||||||
refgraph
|
refgraph
|
||||||
.references
|
.references
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, id)| id.name.as_str())
|
.map(|(_, _, id)| id.name.as_str())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.as_slice()
|
.as_slice()
|
||||||
);
|
);
|
||||||
@ -234,7 +244,7 @@ fn myfn = () => {
|
|||||||
&["foo"],
|
&["foo"],
|
||||||
myfn.declarations
|
myfn.declarations
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, id)| id.name.as_str())
|
.map(|(_, _, id)| id.name.as_str())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.as_slice()
|
.as_slice()
|
||||||
);
|
);
|
||||||
@ -244,7 +254,7 @@ fn myfn = () => {
|
|||||||
&["sin", "foo"],
|
&["sin", "foo"],
|
||||||
myfn.references
|
myfn.references
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, id)| id.name.as_str())
|
.map(|(_, _, id)| id.name.as_str())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.as_slice()
|
.as_slice()
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user