minor refactor
This commit is contained in:
parent
4e7fc9c790
commit
ebcb5f818b
2 changed files with 263 additions and 262 deletions
|
@ -5,271 +5,16 @@ extern crate maplit;
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
mod symbol;
|
mod symbol;
|
||||||
|
mod visitor;
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use bimap::BiHashMap;
|
use petgraph::{dot::Dot, graph::Graph};
|
||||||
use petgraph::{dot::Dot, graph::Graph, graphmap::DiGraphMap, visit::Dfs};
|
use proc_macro2::TokenStream;
|
||||||
use proc_macro2::{Span, TokenStream, TokenTree};
|
use syn::Expr;
|
||||||
use quote::ToTokens;
|
|
||||||
use syn::{punctuated::Punctuated, Expr, ExprPath, Ident, Path, PathArguments, PathSegment};
|
|
||||||
|
|
||||||
use crate::symbol::Symbol;
|
use crate::symbol::Symbol;
|
||||||
|
use crate::visitor::{Elem, Rsx, TagLhs, Visitor};
|
||||||
type Id = Symbol;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
||||||
enum TagLhs {
|
|
||||||
Bind(String),
|
|
||||||
On(String),
|
|
||||||
Plain(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
struct Elem<T> {
|
|
||||||
tag: String,
|
|
||||||
attrs: HashMap<TagLhs, String>,
|
|
||||||
inner: Vec<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Rsx {
|
|
||||||
Elem(Elem<Rsx>),
|
|
||||||
Code(Expr),
|
|
||||||
Text(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum TaggedRsx {
|
|
||||||
Elem(Id, Elem<TaggedRsx>),
|
|
||||||
Code(Id, Expr),
|
|
||||||
Text(Id, String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TaggedRsx {
|
|
||||||
pub fn get_id(&self) -> Id {
|
|
||||||
match self {
|
|
||||||
TaggedRsx::Elem(id, _) | TaggedRsx::Code(id, _) | TaggedRsx::Text(id, _) => *id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
|
|
||||||
enum DepNode {
|
|
||||||
// This is an attribute on an element
|
|
||||||
// Not read-only
|
|
||||||
RsxAttr(Symbol, Symbol),
|
|
||||||
// This is a text node (innertext)
|
|
||||||
// These are read-only
|
|
||||||
RsxSpan(Symbol),
|
|
||||||
// This is something in the model
|
|
||||||
ModelValue(Symbol),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum DepActions {
|
|
||||||
Updates,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
|
||||||
struct DependencyGraph(DiGraphMap<DepNode, ()>);
|
|
||||||
|
|
||||||
impl DependencyGraph {
|
|
||||||
fn new() -> Self {
|
|
||||||
let graph = DiGraphMap::new();
|
|
||||||
DependencyGraph(graph)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
|
||||||
struct Visitor {
|
|
||||||
idx: u32,
|
|
||||||
deps: DependencyGraph,
|
|
||||||
model: HashMap<Id, String>,
|
|
||||||
impl_code: TokenStream,
|
|
||||||
elem_attr_map: HashMap<Id, HashSet<Id>>,
|
|
||||||
|
|
||||||
// symbol maps
|
|
||||||
model_bimap: BiHashMap<Id, String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Visitor {
|
|
||||||
fn new() -> Visitor {
|
|
||||||
Visitor {
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_model(&mut self, model: &HashMap<String, String>) {
|
|
||||||
for (key, value) in model {
|
|
||||||
let id = Symbol::gensym();
|
|
||||||
self.model_bimap.insert(id, key.clone());
|
|
||||||
self.model.insert(id, value.clone());
|
|
||||||
}
|
|
||||||
// self.model.extend(model.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_graph(&mut self, nodes: &[Rsx]) -> Vec<TaggedRsx> {
|
|
||||||
let mut new_nodes = Vec::new();
|
|
||||||
for node in nodes {
|
|
||||||
let node_id = Symbol::gensym();
|
|
||||||
let new_node = match node {
|
|
||||||
Rsx::Elem(Elem { tag, attrs, inner }) => {
|
|
||||||
let tag_inner = self.make_graph(&inner);
|
|
||||||
for (lhs, rhs) in attrs {
|
|
||||||
if let TagLhs::Bind(attr) = lhs {
|
|
||||||
if let Some(id) = self.model_bimap.get_by_right(rhs) {
|
|
||||||
let from = DepNode::RsxAttr(node_id, Symbol::from(attr));
|
|
||||||
let to = DepNode::ModelValue(*id);
|
|
||||||
self.deps.0.add_edge(from, to, ());
|
|
||||||
if let Some(set) = self.elem_attr_map.get_mut(&node_id) {
|
|
||||||
set.insert(Symbol::from(attr));
|
|
||||||
} else {
|
|
||||||
let mut set = HashSet::new();
|
|
||||||
set.insert(Symbol::from(attr));
|
|
||||||
self.elem_attr_map.insert(node_id, set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TaggedRsx::Elem(
|
|
||||||
node_id,
|
|
||||||
Elem {
|
|
||||||
tag: tag.to_string(),
|
|
||||||
attrs: attrs.clone(),
|
|
||||||
inner: tag_inner,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Rsx::Code(expr) => {
|
|
||||||
let deps = self.extract_model_dependencies(expr);
|
|
||||||
for dep in deps {
|
|
||||||
let from = DepNode::ModelValue(dep);
|
|
||||||
let to = DepNode::RsxSpan(node_id);
|
|
||||||
self.deps.0.add_edge(from, to, ());
|
|
||||||
}
|
|
||||||
|
|
||||||
TaggedRsx::Code(node_id, expr.clone())
|
|
||||||
}
|
|
||||||
Rsx::Text(literal) => TaggedRsx::Text(node_id, literal.clone()),
|
|
||||||
};
|
|
||||||
new_nodes.push(new_node);
|
|
||||||
}
|
|
||||||
new_nodes
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gen_code(&mut self, nodes: &[TaggedRsx]) -> Vec<String> {
|
|
||||||
let mut names = Vec::new();
|
|
||||||
for node in nodes {
|
|
||||||
let node_str = node.get_id().as_str();
|
|
||||||
let make_node_id = format_ident!("make_{}", node_str);
|
|
||||||
match node {
|
|
||||||
TaggedRsx::Elem(node_id, Elem { tag, attrs, inner }) => {
|
|
||||||
let mut updates = TokenStream::new();
|
|
||||||
if let Some(this_attrs) = self.elem_attr_map.get(node_id) {
|
|
||||||
for attr in this_attrs {
|
|
||||||
let starting = DepNode::RsxAttr(*node_id, *attr);
|
|
||||||
let mut dfs = Dfs::new(&self.deps.0, starting);
|
|
||||||
let mut update_func = TokenStream::new();
|
|
||||||
while let Some(nx) = dfs.next(&self.deps.0) {
|
|
||||||
if nx != starting {
|
|
||||||
println!("NX: {:?}", nx);
|
|
||||||
match nx {
|
|
||||||
DepNode::ModelValue(sym) => {
|
|
||||||
let sym_name = format_ident!(
|
|
||||||
"{}",
|
|
||||||
self.model_bimap.get_by_left(&sym).unwrap()
|
|
||||||
);
|
|
||||||
let inner_lock = format_ident!(
|
|
||||||
"inner_lock_{}",
|
|
||||||
Symbol::gensym().as_str()
|
|
||||||
);
|
|
||||||
updates.extend(quote! {
|
|
||||||
let #inner_lock = self.#sym_name.clone();
|
|
||||||
});
|
|
||||||
update_func.extend(quote! {
|
|
||||||
{
|
|
||||||
let mut locked = #inner_lock.lock();
|
|
||||||
*locked = new_value.clone();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
DepNode::RsxSpan(id) => {
|
|
||||||
let id_str = id.as_str();
|
|
||||||
update_func.extend(quote! {
|
|
||||||
{
|
|
||||||
if let Some(target) = document().get_element_by_id(#id_str) {
|
|
||||||
target.set_text_content(&new_value.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let attr_name = attr.as_str();
|
|
||||||
updates.extend(quote! {
|
|
||||||
let inner_el = el.clone();
|
|
||||||
el.add_event_listener(move |evt: stdweb::web::event::InputEvent| {
|
|
||||||
let new_value = InputElement::try_from(inner_el.clone()).unwrap().raw_value();
|
|
||||||
js! { console.log("bruh", @{inner_el.clone()}, @{&new_value}); }
|
|
||||||
#update_func
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.impl_code.extend(quote! {
|
|
||||||
fn #make_node_id(&self) -> impl stdweb::web::INode {
|
|
||||||
let el = document().create_element(#tag).unwrap();
|
|
||||||
el.set_attribute("id", #node_str);
|
|
||||||
#updates
|
|
||||||
el
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.gen_code(&inner);
|
|
||||||
}
|
|
||||||
TaggedRsx::Code(node_id, expr) => {
|
|
||||||
self.impl_code.extend(quote! {
|
|
||||||
#[inline]
|
|
||||||
fn #make_node_id(&self) -> impl stdweb::web::INode {
|
|
||||||
let el = document().create_element("span").expect("shouldn't fail");
|
|
||||||
el.set_attribute("id", #node_str);
|
|
||||||
el
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
TaggedRsx::Text(node_id, literal) => {
|
|
||||||
self.impl_code.extend(quote! {
|
|
||||||
#[inline]
|
|
||||||
fn #make_node_id(&self) -> impl stdweb::web::INode {
|
|
||||||
document().create_text_node(#literal)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
names.push(format!("{}", make_node_id));
|
|
||||||
}
|
|
||||||
names
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is using a really dumb heuristic
|
|
||||||
fn extract_model_dependencies(&self, expr: &Expr) -> HashSet<Symbol> {
|
|
||||||
let tokens = expr.to_token_stream();
|
|
||||||
let mut result = HashSet::new();
|
|
||||||
|
|
||||||
for token in tokens.into_iter() {
|
|
||||||
if let TokenTree::Ident(ident) = token {
|
|
||||||
if let Some(id) = self.model_bimap.get_by_right(&ident.to_string()) {
|
|
||||||
result.insert(*id);
|
|
||||||
}
|
|
||||||
// result.insert(format!("{}", ident));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process(
|
fn process(
|
||||||
name: impl AsRef<str>,
|
name: impl AsRef<str>,
|
||||||
|
@ -286,7 +31,7 @@ fn process(
|
||||||
|
|
||||||
// println!("{:?}", visitor);
|
// println!("{:?}", visitor);
|
||||||
println!("DOT:");
|
println!("DOT:");
|
||||||
let graph: Graph<_, _, _> = visitor.deps.0.clone().into_graph();
|
let graph: Graph<_, _, _> = visitor.deps.clone().into_graph();
|
||||||
println!("{:?}", Dot::new(&graph));
|
println!("{:?}", Dot::new(&graph));
|
||||||
|
|
||||||
let name = format_ident!("{}", name);
|
let name = format_ident!("{}", name);
|
||||||
|
|
256
enterprise-compiler/src/visitor.rs
Normal file
256
enterprise-compiler/src/visitor.rs
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use bimap::BiHashMap;
|
||||||
|
use petgraph::graphmap::DiGraphMap;
|
||||||
|
use petgraph::visit::Dfs;
|
||||||
|
use proc_macro2::{TokenStream, TokenTree};
|
||||||
|
use quote::ToTokens;
|
||||||
|
use syn::Expr;
|
||||||
|
|
||||||
|
use crate::Symbol;
|
||||||
|
|
||||||
|
type Id = Symbol;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum TagLhs {
|
||||||
|
Bind(String),
|
||||||
|
On(String),
|
||||||
|
Plain(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Elem<T> {
|
||||||
|
pub tag: String,
|
||||||
|
pub attrs: HashMap<TagLhs, String>,
|
||||||
|
pub inner: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Rsx {
|
||||||
|
Elem(Elem<Rsx>),
|
||||||
|
Code(Expr),
|
||||||
|
Text(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TaggedRsx {
|
||||||
|
Elem(Id, Elem<TaggedRsx>),
|
||||||
|
Code(Id, Expr),
|
||||||
|
Text(Id, String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TaggedRsx {
|
||||||
|
pub fn get_id(&self) -> Id {
|
||||||
|
match self {
|
||||||
|
TaggedRsx::Elem(id, _) | TaggedRsx::Code(id, _) | TaggedRsx::Text(id, _) => *id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
|
||||||
|
pub enum DepNode {
|
||||||
|
// This is an attribute on an element
|
||||||
|
// Not read-only
|
||||||
|
RsxAttr(Symbol, Symbol),
|
||||||
|
// This is a text node (innertext)
|
||||||
|
// These are read-only
|
||||||
|
RsxSpan(Symbol),
|
||||||
|
// This is something in the model
|
||||||
|
ModelValue(Symbol),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum DepActions {
|
||||||
|
Updates,
|
||||||
|
}
|
||||||
|
|
||||||
|
type DependencyGraph = DiGraphMap<DepNode, ()>;
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
pub struct Visitor {
|
||||||
|
idx: u32,
|
||||||
|
pub(crate) deps: DependencyGraph,
|
||||||
|
model: HashMap<Id, String>,
|
||||||
|
pub(crate) impl_code: TokenStream,
|
||||||
|
elem_attr_map: HashMap<Id, HashSet<Id>>,
|
||||||
|
|
||||||
|
// symbol maps
|
||||||
|
model_bimap: BiHashMap<Id, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Visitor {
|
||||||
|
pub fn new() -> Visitor {
|
||||||
|
Visitor {
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_model(&mut self, model: &HashMap<String, String>) {
|
||||||
|
for (key, value) in model {
|
||||||
|
let id = Symbol::gensym();
|
||||||
|
self.model_bimap.insert(id, key.clone());
|
||||||
|
self.model.insert(id, value.clone());
|
||||||
|
}
|
||||||
|
// self.model.extend(model.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_graph(&mut self, nodes: &[Rsx]) -> Vec<TaggedRsx> {
|
||||||
|
let mut new_nodes = Vec::new();
|
||||||
|
for node in nodes {
|
||||||
|
let node_id = Symbol::gensym();
|
||||||
|
let new_node = match node {
|
||||||
|
Rsx::Elem(Elem { tag, attrs, inner }) => {
|
||||||
|
let tag_inner = self.make_graph(&inner);
|
||||||
|
for (lhs, rhs) in attrs {
|
||||||
|
if let TagLhs::Bind(attr) = lhs {
|
||||||
|
if let Some(id) = self.model_bimap.get_by_right(rhs) {
|
||||||
|
let from = DepNode::RsxAttr(node_id, Symbol::from(attr));
|
||||||
|
let to = DepNode::ModelValue(*id);
|
||||||
|
self.deps.add_edge(from, to, ());
|
||||||
|
if let Some(set) = self.elem_attr_map.get_mut(&node_id) {
|
||||||
|
set.insert(Symbol::from(attr));
|
||||||
|
} else {
|
||||||
|
let mut set = HashSet::new();
|
||||||
|
set.insert(Symbol::from(attr));
|
||||||
|
self.elem_attr_map.insert(node_id, set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TaggedRsx::Elem(
|
||||||
|
node_id,
|
||||||
|
Elem {
|
||||||
|
tag: tag.to_string(),
|
||||||
|
attrs: attrs.clone(),
|
||||||
|
inner: tag_inner,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Rsx::Code(expr) => {
|
||||||
|
let deps = self.extract_model_dependencies(expr);
|
||||||
|
for dep in deps {
|
||||||
|
let from = DepNode::ModelValue(dep);
|
||||||
|
let to = DepNode::RsxSpan(node_id);
|
||||||
|
self.deps.add_edge(from, to, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedRsx::Code(node_id, expr.clone())
|
||||||
|
}
|
||||||
|
Rsx::Text(literal) => TaggedRsx::Text(node_id, literal.clone()),
|
||||||
|
};
|
||||||
|
new_nodes.push(new_node);
|
||||||
|
}
|
||||||
|
new_nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_code(&mut self, nodes: &[TaggedRsx]) -> Vec<String> {
|
||||||
|
let mut names = Vec::new();
|
||||||
|
for node in nodes {
|
||||||
|
let node_str = node.get_id().as_str();
|
||||||
|
let make_node_id = format_ident!("make_{}", node_str);
|
||||||
|
match node {
|
||||||
|
TaggedRsx::Elem(node_id, Elem { tag, attrs, inner }) => {
|
||||||
|
let mut updates = TokenStream::new();
|
||||||
|
if let Some(this_attrs) = self.elem_attr_map.get(node_id) {
|
||||||
|
for attr in this_attrs {
|
||||||
|
let starting = DepNode::RsxAttr(*node_id, *attr);
|
||||||
|
let mut dfs = Dfs::new(&self.deps, starting);
|
||||||
|
let mut update_func = TokenStream::new();
|
||||||
|
while let Some(nx) = dfs.next(&self.deps) {
|
||||||
|
if nx != starting {
|
||||||
|
println!("NX: {:?}", nx);
|
||||||
|
match nx {
|
||||||
|
DepNode::ModelValue(sym) => {
|
||||||
|
let sym_name = format_ident!(
|
||||||
|
"{}",
|
||||||
|
self.model_bimap.get_by_left(&sym).unwrap()
|
||||||
|
);
|
||||||
|
let inner_lock = format_ident!(
|
||||||
|
"inner_lock_{}",
|
||||||
|
Symbol::gensym().as_str()
|
||||||
|
);
|
||||||
|
updates.extend(quote! {
|
||||||
|
let #inner_lock = self.#sym_name.clone();
|
||||||
|
});
|
||||||
|
update_func.extend(quote! {
|
||||||
|
{
|
||||||
|
let mut locked = #inner_lock.lock();
|
||||||
|
*locked = new_value.clone();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
DepNode::RsxSpan(id) => {
|
||||||
|
let id_str = id.as_str();
|
||||||
|
update_func.extend(quote! {
|
||||||
|
{
|
||||||
|
if let Some(target) = document().get_element_by_id(#id_str) {
|
||||||
|
target.set_text_content(&new_value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updates.extend(quote! {
|
||||||
|
let inner_el = el.clone();
|
||||||
|
el.add_event_listener(move |evt: stdweb::web::event::InputEvent| {
|
||||||
|
let new_value = InputElement::try_from(inner_el.clone()).unwrap().raw_value();
|
||||||
|
#update_func
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.impl_code.extend(quote! {
|
||||||
|
fn #make_node_id(&self) -> impl stdweb::web::INode {
|
||||||
|
let el = document().create_element(#tag).unwrap();
|
||||||
|
el.set_attribute("id", #node_str);
|
||||||
|
#updates
|
||||||
|
el
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.gen_code(&inner);
|
||||||
|
}
|
||||||
|
TaggedRsx::Code(node_id, expr) => {
|
||||||
|
self.impl_code.extend(quote! {
|
||||||
|
#[inline]
|
||||||
|
fn #make_node_id(&self) -> impl stdweb::web::INode {
|
||||||
|
let el = document().create_element("span").expect("shouldn't fail");
|
||||||
|
el.set_attribute("id", #node_str);
|
||||||
|
el
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
TaggedRsx::Text(node_id, literal) => {
|
||||||
|
self.impl_code.extend(quote! {
|
||||||
|
#[inline]
|
||||||
|
fn #make_node_id(&self) -> impl stdweb::web::INode {
|
||||||
|
document().create_text_node(#literal)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
names.push(format!("{}", make_node_id));
|
||||||
|
}
|
||||||
|
names
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is using a really dumb heuristic
|
||||||
|
fn extract_model_dependencies(&self, expr: &Expr) -> HashSet<Symbol> {
|
||||||
|
let tokens = expr.to_token_stream();
|
||||||
|
let mut result = HashSet::new();
|
||||||
|
|
||||||
|
for token in tokens.into_iter() {
|
||||||
|
if let TokenTree::Ident(ident) = token {
|
||||||
|
if let Some(id) = self.model_bimap.get_by_right(&ident.to_string()) {
|
||||||
|
result.insert(*id);
|
||||||
|
}
|
||||||
|
// result.insert(format!("{}", ident));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue