public static ZilResult AGAIN(Context ctx, ZilActivation activation = null) { if (activation == null) { activation = ctx.GetEnclosingProgActivation(); if (activation == null) { throw new InterpreterError(InterpreterMessages._0_No_Enclosing_PROGREPEAT, "AGAIN"); } } return(ZilResult.Again(activation)); }
public bool ShouldPass([CanBeNull] ZilActivation currentActivation, ref ZilResult resultToPass) { switch (outcome) { case Outcome.Value: return(false); case Outcome.Return when currentActivation != null && activation == currentActivation: resultToPass = value; return(true); default: resultToPass = this; return(true); } }
public static ZilResult RETURN(Context ctx, ZilObject value = null, ZilActivation activation = null) { if (value == null) { value = ctx.TRUE; } if (activation == null) { activation = ctx.GetEnclosingProgActivation(); if (activation == null) { throw new InterpreterError(InterpreterMessages._0_No_Enclosing_PROGREPEAT, "RETURN"); } } return(ZilResult.Return(activation, value)); }
public static ZilResult Again(ZilActivation activation) { return(new ZilResult(Outcome.Again, null, activation)); }
public static ZilResult Return(ZilActivation activation, ZilObject value) { return(new ZilResult(Outcome.Return, value, activation)); }
private ZilResult(Outcome outcome, ZilObject value, ZilActivation activation) { this.outcome = outcome; this.value = value; this.activation = activation; }
public bool IsAgain(ZilActivation currentActivation) => outcome == Outcome.Again && activation == currentActivation;
public bool IsReturn(ZilActivation currentActivation, out ZilObject value) { value = this.value; return(outcome == Outcome.Return && activation == currentActivation); }
static ZilResult PerformProg([NotNull][ProvidesContext] Context ctx, [CanBeNull] ZilAtom activationAtom, BindingParams.BindingList bindings, [CanBeNull] ZilDecl bodyDecl, [ItemNotNull][NotNull] ZilObject[] body, [NotNull] string name, bool repeat, bool catchy) { using (var activation = new ZilActivation(ctx.GetStdAtom(StdAtom.PROG))) { using (var innerEnv = ctx.PushEnvironment()) { if (activationAtom != null) { innerEnv.Rebind(activationAtom, activation); } var bodyAtomDecls = bodyDecl?.GetAtomDeclPairs().ToLookup(p => p.Key, p => p.Value); foreach (var b in bindings.Bindings) { var atom = b.Atom; var initializer = b.Initializer; ZilObject value; if (initializer != null) { var initResult = initializer.Eval(ctx); if (initResult.ShouldPass(activation, ref initResult)) { return(initResult); } value = (ZilObject)initResult; } else { value = null; } var previousDecl = b.Decl; var firstBodyDecl = bodyAtomDecls?[atom].FirstOrDefault(); if (firstBodyDecl != null && (previousDecl != null || bodyAtomDecls[atom].Skip(1).Any())) { throw new InterpreterError(InterpreterMessages._0_Conflicting_DECLs_For_Atom_1, name, atom); } var decl = previousDecl ?? firstBodyDecl; if (value != null) { ctx.MaybeCheckDecl(initializer, value, decl, "LVAL of {0}", atom); } innerEnv.Rebind(atom, value, decl); } if (catchy) { innerEnv.Rebind(ctx.EnclosingProgActivationAtom, activation); } // evaluate body ZilResult result = null; bool again; do { again = false; foreach (var expr in body) { result = expr.Eval(ctx); if (result.IsAgain(activation)) { again = true; } else if (result.ShouldPass(activation, ref result)) { return(result); } } } while (repeat || again); return(result); } } }