Beispiel #1
0
        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));
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
 public static ZilResult Again(ZilActivation activation)
 {
     return(new ZilResult(Outcome.Again, null, activation));
 }
Beispiel #5
0
 public static ZilResult Return(ZilActivation activation, ZilObject value)
 {
     return(new ZilResult(Outcome.Return, value, activation));
 }
Beispiel #6
0
 private ZilResult(Outcome outcome, ZilObject value, ZilActivation activation)
 {
     this.outcome    = outcome;
     this.value      = value;
     this.activation = activation;
 }
Beispiel #7
0
 public bool IsAgain(ZilActivation currentActivation) =>
 outcome == Outcome.Again && activation == currentActivation;
Beispiel #8
0
 public bool IsReturn(ZilActivation currentActivation, out ZilObject value)
 {
     value = this.value;
     return(outcome == Outcome.Return && activation == currentActivation);
 }
Beispiel #9
0
        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);
                }
            }
        }