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)); }
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); }
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); }
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; }
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")); }
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)); }
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); } } }