From c010cbc17dcbb2f0d6005d21530143bf57cb5871 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 25 May 2022 13:50:33 +0200 Subject: Move route from context to VM --- src/eval/func.rs | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'src/eval/func.rs') diff --git a/src/eval/func.rs b/src/eval/func.rs index 83171ce7..16575c80 100644 --- a/src/eval/func.rs +++ b/src/eval/func.rs @@ -29,7 +29,7 @@ impl Func { /// Create a new function from a native rust function. pub fn from_fn( name: &'static str, - func: fn(&mut Context, &mut Args) -> TypResult, + func: fn(&mut Machine, &mut Args) -> TypResult, ) -> Self { Self(Arc::new(Repr::Native(Native { name, @@ -86,19 +86,25 @@ impl Func { } /// Call the function with the given arguments. - pub fn call(&self, ctx: &mut Context, mut args: Args) -> TypResult { + pub fn call(&self, vm: &mut Machine, mut args: Args) -> TypResult { let value = match self.0.as_ref() { - Repr::Native(native) => (native.func)(ctx, &mut args)?, - Repr::Closure(closure) => closure.call(ctx, &mut args)?, + Repr::Native(native) => (native.func)(vm, &mut args)?, + Repr::Closure(closure) => closure.call(vm, &mut args)?, Repr::With(wrapped, applied) => { args.items.splice(.. 0, applied.items.iter().cloned()); - return wrapped.call(ctx, args); + return wrapped.call(vm, args); } }; args.finish()?; Ok(value) } + /// Call the function without an existing virtual machine. + pub fn call_detached(&self, ctx: &mut Context, args: Args) -> TypResult { + let mut vm = Machine::new(ctx, vec![], Scopes::new(None)); + self.call(&mut vm, args) + } + /// Execute the function's set rule. pub fn set(&self, mut args: Args) -> TypResult { let styles = match self.0.as_ref() { @@ -138,7 +144,7 @@ struct Native { /// The name of the function. pub name: &'static str, /// The function pointer. - pub func: fn(&mut Context, &mut Args) -> TypResult, + pub func: fn(&mut Machine, &mut Args) -> TypResult, /// The set rule. pub set: Option TypResult>, /// The id of the node to customize with this function's show rule. @@ -163,7 +169,7 @@ pub trait Node: 'static { /// /// This is passed only the arguments that remain after execution of the /// node's set rule. - fn construct(ctx: &mut Context, args: &mut Args) -> TypResult; + fn construct(vm: &mut Machine, args: &mut Args) -> TypResult; /// Parse the arguments into style properties for this node. /// @@ -192,7 +198,7 @@ pub struct Closure { impl Closure { /// Call the function in the context with the arguments. - pub fn call(&self, ctx: &mut Context, args: &mut Args) -> TypResult { + pub fn call(&self, vm: &mut Machine, args: &mut Args) -> TypResult { // Don't leak the scopes from the call site. Instead, we use the // scope of captured variables we collected earlier. let mut scopes = Scopes::new(None); @@ -213,24 +219,20 @@ impl Closure { scopes.top.def_mut(sink, args.take()); } - // Set the new route if we are detached. - let detached = ctx.route.is_empty(); - if detached { - ctx.route = self.location.into_iter().collect(); - } + // Determine the route inside the closure. + let detached = vm.route.is_empty(); + let route = if detached { + self.location.into_iter().collect() + } else { + vm.route.clone() + }; // Evaluate the body. - let mut vm = Machine::new(ctx, scopes); - let result = self.body.eval(&mut vm); - let flow = vm.flow; - - // Restore the old route. - if detached { - ctx.route.clear(); - } + let mut sub = Machine::new(vm.ctx, route, scopes); + let result = self.body.eval(&mut sub); // Handle control flow. - match flow { + match sub.flow { Some(Flow::Return(_, Some(explicit))) => return Ok(explicit), Some(Flow::Return(_, None)) => {} Some(flow) => return Err(flow.forbidden())?, -- cgit v1.2.3