public FuncTagBlueprint(VM interpreter, RantPattern source, Stringe name, IEnumerable <Token <R> >[] argData = null) : base(interpreter) { Source = source; Name = name.Trim(); RantFuncSigs defs; if (!RantFuncs.F.TryGetValue(Name.Value, out defs)) { throw new RantException(Source, Name, "A function of the name '" + Name.Value + "' does not exist."); } if ((_tagDef = defs.GetSignature((argData == null ? 0 : argData.Length))) == null) { throw new RantException(Source, Name, "The function '" + Name.Value + "' has no signature that accepts " + (argData == null ? 0 : argData.Length) + " argument(s)."); } if (argData == null) { _args = new Argument[0]; } else { var lastType = _tagDef.Parameters.Last(); // Insert token arguments into the array, set string args to null. _args = argData.Select((a, i) => (i >= _tagDef.ParamCount ? (lastType & ParamFlags.Code) == ParamFlags.Code // Covers multi params : (_tagDef.Parameters[i] & ParamFlags.Code) == ParamFlags.Code) ? Argument.FromTokens(a) : null).ToArray(); // Queue string arguments on the stack. for (int i = 0; i < argData.Length; i++) { if ((i >= _tagDef.ParamCount && (lastType & ParamFlags.Code) != ParamFlags.Code) || (_tagDef.Parameters[i] & ParamFlags.Code) != ParamFlags.Code) { interpreter.PushState(VM.State.CreateSub(source, argData[i], interpreter)); } } } }
static RantFuncs() { F = new Dictionary <string, RantFuncSigs>(StringComparer.InvariantCultureIgnoreCase); // Repeaters, probability, and block attributes F["rep"] = F["r"] = new RantFunc(Repeat, ParamFlags.None); F["sep"] = F["s"] = new RantFunc(Separator, ParamFlags.Code); F["before"] = new RantFunc(Before, ParamFlags.Code); F["after"] = new RantFunc(After, ParamFlags.Code); F["chance"] = new RantFunc(Chance, ParamFlags.None); F["break"] = new RantFunc(Break); F["repnum"] = F["rn"] = new RantFunc(RepNum); F["repindex"] = F["ri"] = new RantFunc(RepIndex); F["repcount"] = F["rc"] = new RantFunc(RepCount); // Synchronizers F["sync"] = F["x"] = new RantFuncSigs( new RantFunc(SyncCreateApply, ParamFlags.None, ParamFlags.None), new RantFunc(SyncApply, ParamFlags.None) ); F["xreset"] = new RantFunc(SyncReset, ParamFlags.None); F["xseed"] = new RantFunc(SyncReseed, ParamFlags.None, ParamFlags.None); F["xnone"] = new RantFunc(Desync); F["xnew"] = new RantFunc(SyncCreate, ParamFlags.None, ParamFlags.None); F["xpin"] = new RantFunc(Pin, ParamFlags.None); F["xunpin"] = new RantFunc(Unpin, ParamFlags.None); F["xstep"] = new RantFunc(Step, ParamFlags.None); // RNG manipulation F["branch"] = F["b"] = new RantFuncSigs( new RantFunc(Branch, ParamFlags.None), new RantFunc(BranchScope, ParamFlags.None, ParamFlags.Code) ); F["merge"] = F["m"] = new RantFunc(Merge); F["generation"] = F["g"] = new RantFuncSigs(new RantFunc(Generation), new RantFunc(GenerationSet, ParamFlags.None)); // Repeater conditionals F["first"] = new RantFunc(First, ParamFlags.Code); F["last"] = new RantFunc(Last, ParamFlags.Code); F["middle"] = new RantFunc(Middle, ParamFlags.Code); F["notfirst"] = new RantFunc(NotFirst, ParamFlags.Code); F["notlast"] = new RantFunc(NotLast, ParamFlags.Code); F["notmiddle"] = new RantFunc(NotMiddle, ParamFlags.Code); F["odd"] = new RantFunc(Odd, ParamFlags.Code); F["even"] = new RantFunc(Even, ParamFlags.Code); F["nth"] = new RantFuncSigs( new RantFunc(Nth, ParamFlags.None, ParamFlags.None, ParamFlags.Code), new RantFunc(NthSimple, ParamFlags.None, ParamFlags.Code) ); // Quantifier conditionals F["alt"] = new RantFunc(Alt, ParamFlags.Code, ParamFlags.Code); F["any"] = new RantFunc(Any, ParamFlags.Code, ParamFlags.Code); // Replacers F["match"] = new RantFunc(ReplaceMatch); F["group"] = new RantFunc(ReplaceGroup, ParamFlags.None); // Subrotuine interaction F["arg"] = new RantFunc(Arg, ParamFlags.None); // Formatting F["numfmt"] = new RantFuncSigs( new RantFunc(NumFmt, ParamFlags.None), new RantFunc(NumFmtScope, ParamFlags.None, ParamFlags.Code)); F["digits"] = new RantFuncSigs( new RantFunc(Digits, ParamFlags.None), new RantFunc(DigitsScope, ParamFlags.None, ParamFlags.Code)); F["endian"] = new RantFunc(Endian, ParamFlags.None); F["caps"] = F["case"] = new RantFuncSigs( new RantFunc(Case, ParamFlags.None), new RantFunc(CaseScope, ParamFlags.None, ParamFlags.Code)); F["capsinfer"] = new RantFunc(CapsInfer, ParamFlags.None); F["quot"] = F["q"] = new RantFunc(Quote, ParamFlags.Code); // Channels F["out"] = new RantFunc(Out, ParamFlags.None, ParamFlags.None); F["close"] = new RantFunc(Close, ParamFlags.None); // External interaction F["extern"] = F["ext"] = new RantFunc(Extern, ParamFlags.None, ParamFlags.Multi); // Markers and targets F["mark"] = new RantFunc(Mark, ParamFlags.None); F["dist"] = new RantFunc(Dist, ParamFlags.None, ParamFlags.None); F["get"] = new RantFunc(Get, ParamFlags.None); F["send"] = new RantFunc(Send, ParamFlags.None, ParamFlags.None); F["osend"] = new RantFunc(SendOverwrite, ParamFlags.None, ParamFlags.None); F["clrt"] = new RantFunc(ClearTarget, ParamFlags.None); F["copy"] = new RantFunc(Copy, ParamFlags.None, ParamFlags.None); // String generation, manipulation, and analysis F["len"] = new RantFunc(Length, ParamFlags.None); F["char"] = new RantFuncSigs( new RantFunc(Character, ParamFlags.None), new RantFunc(CharacterMulti, ParamFlags.None, ParamFlags.None)); F["num"] = F["n"] = new RantFunc(Number, ParamFlags.None, ParamFlags.None); F["dec"] = new RantFunc(NumberDec); // Flags F["define"] = new RantFunc(DefineFlag, ParamFlags.None | ParamFlags.Multi); F["undef"] = new RantFunc(UndefineFlag, ParamFlags.None | ParamFlags.Multi); F["ifdef"] = new RantFunc(IfDef, ParamFlags.None, ParamFlags.Code); F["ifndef"] = new RantFunc(IfNDef, ParamFlags.None, ParamFlags.Code); F["else"] = new RantFunc(Else, ParamFlags.Code); // Comparisons F["cmp"] = new RantFunc(Compare, ParamFlags.None, ParamFlags.None, ParamFlags.Code); F["is"] = new RantFunc(CmpIs, ParamFlags.None, ParamFlags.Code); // Misc F["src"] = new RantFunc(Src); F["rhymemode"] = new RantFunc(RhymeMode, ParamFlags.None); }