Created
May 22, 2018 16:29
-
-
Save Yatekii/90341b4539ac6b0482c9b33708210e84 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub fn render(library: &Library, state: &mut State, mut stack: Vec<String>, expression: &mut Expression) -> Expression { | |
match expression { | |
// We have a symbolic expression that we have to evaluate | |
Expression::Symbolic(ref mut args) | Expression::NotDone(ref mut args) => { | |
// If we have a valid expression (unnamed ones are not allowed) | |
if args.len() > 0 { | |
// Get the first nested expression | |
return match args.remove(0) { | |
// If the first expression is a plain literal | |
Expression::Literal(Literal::S(name)) => { | |
// Try render all nested expressions | |
let possibly_rendered_args: Vec<Expression> = args.into_iter().map(|arg| { | |
stack.push(name.clone()); | |
let rendered = render(library, state, stack.clone(), arg); | |
rendered | |
}).collect(); | |
let rendered_args: Vec<&Expression> = possibly_rendered_args.iter().filter(|expr| if let Expression::Done(_) = expr { true } else { false }).collect(); | |
// If all child nodes are already rendered | |
if rendered_args.len() == args.len() { | |
// Render the parent if the environment is known | |
if let Some(renderer) = library.search_environment(name.clone()) { | |
// Unpack the rendered children | |
let rendered_args = rendered_args.iter().map(|arg| { | |
if let Expression::Done(rendered) = arg { | |
rendered.clone() | |
} else { | |
"".to_owned() | |
} | |
}).collect(); | |
*expression = renderer(state, stack, rendered_args); | |
} else { | |
// Even tho we failed, mark the expression as done processing | |
println!("Environment {} is not known to the renderer.", name.clone()); | |
*expression = Expression::Done(format!("{{environment {} is not known to the renderer}}", name.clone()).into()); | |
} | |
return expression.clone() | |
} else { | |
// Not all child nodes are already rendered | |
// Store the rendered ones | |
let n = possibly_rendered_args.len(); | |
for i in 0..n { | |
args[i] = possibly_rendered_args[i].clone(); | |
} | |
args.insert(0, Expression::Literal(Literal::S(name))); | |
// Signalize we have to reprocess this again | |
Expression::NotDone(args.clone()) | |
} | |
}, | |
// Name of the symbolic expression is not a literal | |
_ => panic!("Symbolic expressions can't name a symbolic expression") | |
} | |
} | |
panic!("Unnamed expressions are not allowed."); | |
}, | |
// We can immediately mark the expression as resolved, | |
// as we already have a literal that doesn't have to be processed | |
Expression::Literal(l) => match l { | |
Literal::S(s) => Expression::Done(s.to_owned()) | |
} | |
// If expression is already done, just return it | |
Expression::Done(_s) => expression.clone() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment