示例#1
0
 public static ZilResult PROG([NotNull] Context ctx,
                              [CanBeNull][Optional] ZilAtom activationAtom,
                              BindingParams.BindingList bindings,
                              [CanBeNull][Optional] ZilDecl bodyDecl,
                              [NotNull][Required] ZilObject[] body)
 {
     return(PerformProg(ctx, activationAtom, bindings, bodyDecl, body, "PROG", false, true));
 }
示例#2
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);
                }
            }
        }