Пример #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 ZilObject PerformDefine([NotNull][ProvidesContext] Context ctx, [NotNull] ZilAtom name,
                                       [CanBeNull] ZilAtom activationAtom,
                                       [NotNull] ZilList argList, ZilDecl decl, [NotNull] ZilObject[] body, [NotNull] string subrName)
        {
            if (!ctx.AllowRedefine && ctx.GetGlobalVal(name) != null)
            {
                throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, subrName, name.ToStringContext(ctx, false));
            }

            var func = new ZilFunction(
                subrName,
                name,
                activationAtom,
                argList,
                decl,
                body);

            ctx.SetGlobalVal(name, func);
            return(name);
        }
Пример #3
0
        public static ZilObject DEFMAC([NotNull] Context ctx, [NotNull] ZilAtom name,
                                       [CanBeNull][Optional] ZilAtom activationAtom, [ItemNotNull][NotNull] ZilList argList,
                                       [CanBeNull][Optional] ZilDecl decl, [NotNull][Required] ZilObject[] body)
        {
            if (!ctx.AllowRedefine && ctx.GetGlobalVal(name) != null)
            {
                throw new InterpreterError(InterpreterMessages._0_Already_Defined_1, "DEFMAC", name.ToStringContext(ctx, false));
            }

            var func = new ZilFunction(
                "DEFMAC",
                name,
                activationAtom,
                argList,
                decl,
                body);
            var macro = new ZilEvalMacro(func)
            {
                SourceLine = ctx.TopFrame.SourceLine
            };

            ctx.SetGlobalVal(name, macro);
            return(name);
        }
Пример #4
0
        public static ArgSpec Parse([NotNull] string caller, [CanBeNull] ZilAtom targetName, [CanBeNull] ZilAtom activationAtom,
                                    [NotNull] IEnumerable <ZilObject> argspec, [CanBeNull] ZilDecl bodyDecl = null)
        {
            var optArgsStart = -1;
            var auxArgsStart = -1;

            ZilAtom   varargsAtom = null, environmentAtom = null, quoteAtom = null;
            bool      varargsQuoted = false;
            ZilObject varargsDecl = null, valueDecl = null;

            var argAtoms    = new List <ZilAtom>();
            var argDecls    = new List <ZilObject>();
            var argQuoted   = new List <bool>();
            var argDefaults = new List <ZilObject>();

            const int OO_None        = 0;
            const int OO_Varargs     = 1;
            const int OO_Activation  = 2;
            const int OO_Value       = 3;
            const int OO_Environment = 4;

            int       cur        = 0;
            int       oneOffMode = OO_None;
            ZilObject oneOffTag  = null;

            foreach (var arg in argspec)
            {
                // check for arg clause separators: "OPT", "AUX", etc.
                if (arg is ZilString sep)
                {
                    switch (sep.Text)
                    {
                    case "OPT":
                    case "OPTIONAL":
                        if (optArgsStart != -1)
                        {
                            throw new InterpreterError(InterpreterMessages._0_Multiple_1_Clauses, caller, "\"OPT\"");
                        }
                        if (auxArgsStart != -1)
                        {
                            throw new InterpreterError(InterpreterMessages._0_OPT_After_AUX, caller);
                        }
                        optArgsStart = cur;
                        continue;

                    case "AUX":
                    case "EXTRA":
                        if (auxArgsStart != -1)
                        {
                            throw new InterpreterError(InterpreterMessages._0_Multiple_1_Clauses, caller, "\"AUX\"");
                        }
                        auxArgsStart = cur;
                        continue;

                    case "ARGS":
                        varargsQuoted = true;
                        goto case "TUPLE";

                    case "TUPLE":
                        if (varargsAtom != null)
                        {
                            throw new InterpreterError(InterpreterMessages._0_Multiple_1_Clauses, caller, "\"ARGS\" or \"TUPLE\"");
                        }
                        oneOffMode = OO_Varargs;
                        oneOffTag  = arg;
                        continue;

                    case "NAME":
                    case "ACT":
                        if (activationAtom != null)
                        {
                            throw new InterpreterError(InterpreterMessages._0_Multiple_1_Clauses, caller, "\"NAME\" or activation atom");
                        }
                        oneOffMode = OO_Activation;
                        oneOffTag  = arg;
                        continue;

                    case "BIND":
                        if (environmentAtom != null)
                        {
                            throw new InterpreterError(InterpreterMessages._0_Multiple_1_Clauses, caller, "\"BIND\"");
                        }
                        oneOffMode = OO_Environment;
                        oneOffTag  = arg;
                        continue;

                    case "VALUE":
                        if (valueDecl != null)
                        {
                            throw new InterpreterError(InterpreterMessages._0_Multiple_1_Clauses, caller, "\"VALUE\"");
                        }
                        oneOffMode = OO_Value;
                        oneOffTag  = arg;
                        continue;

                    default:
                        throw new InterpreterError(
                                  InterpreterMessages._0_Unrecognized_1_2,
                                  caller,
                                  "clause in arg spec",
                                  arg.ToString());
                    }
                }

                // handle one-offs
                switch (oneOffMode)
                {
                case OO_Varargs:
                    switch (arg)
                    {
                    case ZilAtom atom:
                        varargsAtom = atom;
                        break;

                    case ZilAdecl adecl:
                        varargsDecl = adecl.Second;
                        varargsAtom = (ZilAtom)adecl.First;
                        break;

                    default:
                        throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, caller, "an atom", oneOffTag);
                    }

                    oneOffMode = OO_None;
                    continue;

                case OO_Activation:
                    activationAtom = arg as ZilAtom;
                    if (activationAtom == null)
                    {
                        throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, caller, "an atom", oneOffTag);
                    }

                    oneOffMode = OO_None;
                    continue;

                case OO_Environment:
                    environmentAtom = arg as ZilAtom;
                    if (environmentAtom == null)
                    {
                        throw new InterpreterError(InterpreterMessages._0_Expected_1_After_2, caller, "an atom", oneOffTag);
                    }

                    oneOffMode = OO_None;
                    continue;

                case OO_Value:
                    valueDecl  = arg;
                    oneOffMode = OO_None;
                    continue;
                }

                // it's a real arg
                cur++;

                bool      quoted = false;
                ZilObject argName, argValue, argDecl;

                // could be an atom or a list: (atom defaultValue)
                if (arg is ZilList al && !(arg is ZilForm))
                {
                    if (al.IsEmpty)
                    {
                        throw new InterpreterError(InterpreterMessages._0_Empty_List_In_Arg_Spec, caller);
                    }

                    // TODO: report error if length != 2, or if in required args section
                    argName  = al.First;
                    argValue = al.Rest.First;
                }
Пример #5
0
 public static ZilObject DEFINE20([NotNull] Context ctx, [NotNull] ZilAtom name,
                                  [CanBeNull][Optional] ZilAtom activationAtom, [NotNull][ItemNotNull] ZilList argList,
                                  [CanBeNull][Optional] ZilDecl decl, [ItemCanBeNull][NotNull][Required] ZilObject[] body)
 {
     return(PerformDefine(ctx, name, activationAtom, argList, decl, body, "DEFINE20"));
 }
Пример #6
0
 public static ZilObject FUNCTION(Context ctx, [CanBeNull][Optional] ZilAtom activationAtom,
                                  [NotNull] ZilList argList, [CanBeNull][Optional] ZilDecl decl, [NotNull][Required] ZilObject[] body)
 {
     return(new ZilFunction("FUNCTION", null, activationAtom, argList, decl, body));
 }
Пример #7
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);
                }
            }
        }