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; | ||||
|  | ||||
| mod coredump; | ||||
| mod diff; | ||||
| mod docs; | ||||
| mod engine; | ||||
| mod errors; | ||||
|  | ||||
| @ -7,10 +7,18 @@ use crate::{ | ||||
| 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>); | ||||
| @ -18,6 +26,9 @@ type RefEdge<'tree> = (Option<Declaration<'tree>>, Reference<'tree>); | ||||
| /// | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct Scope<'tree> { | ||||
|     /// | ||||
|     pub program: types::NodeRef<'tree, types::Program>, | ||||
|  | ||||
|     /// | ||||
|     pub declarations: Vec<Declaration<'tree>>, | ||||
|  | ||||
| @ -29,8 +40,9 @@ pub struct Scope<'tree> { | ||||
| } | ||||
|  | ||||
| impl<'tree> Scope<'tree> { | ||||
|     pub fn new() -> Self { | ||||
|     pub fn new(program: types::NodeRef<'tree, types::Program>) -> Self { | ||||
|         Scope { | ||||
|             program, | ||||
|             declarations: vec![], | ||||
|             references: vec![], | ||||
|             children: vec![], | ||||
| @ -42,26 +54,29 @@ impl<'tree> Scope<'tree> { | ||||
|         let mut unmatched_refs = self.references.clone(); | ||||
|  | ||||
|         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 { | ||||
|                     Some((decl_node, decl_id)) => { | ||||
|                         edges.push((Some((decl_node.clone(), decl_id)), (ref_node.clone(), ref_id))); | ||||
|                     Some((decl_program, decl_node, decl_id)) => { | ||||
|                         edges.push(( | ||||
|                             Some((decl_program, decl_node.clone(), decl_id)), | ||||
|                             (ref_program, ref_node.clone(), ref_id), | ||||
|                         )); | ||||
|                     } | ||||
|                     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(( | ||||
|                 self.declarations | ||||
|                     .iter() | ||||
|                     .filter(|(_, decl_id)| decl_id.name == ref_id.name) | ||||
|                     .filter(|(_, _, decl_id)| decl_id.name == ref_id.name) | ||||
|                     .cloned() | ||||
|                     .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> { | ||||
|     pub fn new() -> Self { | ||||
|     pub fn new(program: types::NodeRef<'tree, types::Program>) -> 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; | ||||
|  | ||||
|     fn visit_node(&self, node: Node<'tree>) -> Result<bool, Self::Error> { | ||||
|         if let Node::Program(_program) = node { | ||||
|             let csv = ScopeVisitor::new(); | ||||
|         if let Node::Program(program) = node { | ||||
|             let csv = ScopeVisitor::new(program); | ||||
|             for child in node.children() { | ||||
|                 child.visit(csv.clone())?; | ||||
|             } | ||||
| @ -103,18 +118,19 @@ impl<'tree> Visitor<'tree> for ScopeVisitor<'tree> { | ||||
|  | ||||
|         match node { | ||||
|             Node::VariableDeclaration(vd) => { | ||||
|                 // process and return | ||||
|                 let program = self.scope.lock().unwrap().program; | ||||
|                 self.scope | ||||
|                     .lock() | ||||
|                     .unwrap() | ||||
|                     .declarations | ||||
|                     .push((node.clone(), &vd.declaration.id)); | ||||
|                     .push((program, node.clone(), &vd.declaration.id)); | ||||
|  | ||||
|                 let node: Node = (&vd.declaration.init).into(); | ||||
|                 node.visit(self.clone())?; | ||||
|             } | ||||
|             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() { | ||||
| @ -127,20 +143,14 @@ impl<'tree> Visitor<'tree> for ScopeVisitor<'tree> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn extract_refgraph<'a, 'tree>(node: Node<'tree>) -> Result<Scope<'tree>, std::convert::Infallible> { | ||||
|     let sv = ScopeVisitor::new(); | ||||
| pub fn extract_refgraph<'a, 'tree>( | ||||
|     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() { | ||||
|                 child.visit(sv.clone())?; | ||||
|             } | ||||
|         } | ||||
|         _ => { | ||||
|             node.visit(sv.clone())?; | ||||
|         } | ||||
|     for child in node.children() { | ||||
|         child.visit(sv.clone())?; | ||||
|     } | ||||
|  | ||||
|     let x = sv.scope.lock().unwrap().clone(); | ||||
| @ -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<_>>(); | ||||
|         assert_eq!(edges.len(), 3); | ||||
|  | ||||
|         // 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!(decl.is_none()); | ||||
|  | ||||
|         // 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!(decl.is_some()); | ||||
|         // 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!( | ||||
| @ -210,7 +220,7 @@ fn myfn = () => { | ||||
|             refgraph | ||||
|                 .declarations | ||||
|                 .iter() | ||||
|                 .map(|(_, id)| id.name.as_str()) | ||||
|                 .map(|(_, _, id)| id.name.as_str()) | ||||
|                 .collect::<Vec<_>>() | ||||
|                 .as_slice() | ||||
|         ); | ||||
| @ -221,7 +231,7 @@ fn myfn = () => { | ||||
|             refgraph | ||||
|                 .references | ||||
|                 .iter() | ||||
|                 .map(|(_, id)| id.name.as_str()) | ||||
|                 .map(|(_, _, id)| id.name.as_str()) | ||||
|                 .collect::<Vec<_>>() | ||||
|                 .as_slice() | ||||
|         ); | ||||
| @ -234,7 +244,7 @@ fn myfn = () => { | ||||
|             &["foo"], | ||||
|             myfn.declarations | ||||
|                 .iter() | ||||
|                 .map(|(_, id)| id.name.as_str()) | ||||
|                 .map(|(_, _, id)| id.name.as_str()) | ||||
|                 .collect::<Vec<_>>() | ||||
|                 .as_slice() | ||||
|         ); | ||||
| @ -244,7 +254,7 @@ fn myfn = () => { | ||||
|             &["sin", "foo"], | ||||
|             myfn.references | ||||
|                 .iter() | ||||
|                 .map(|(_, id)| id.name.as_str()) | ||||
|                 .map(|(_, _, id)| id.name.as_str()) | ||||
|                 .collect::<Vec<_>>() | ||||
|                 .as_slice() | ||||
|         ); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user