private static IokeObject CreateSuperCallFor(IokeObject out_self, IokeObject out_context, IokeObject out_message, object out_on, string out_name) { return(out_context.runtime.NewNativeMethod("will call the super method of the current message on the same receiver", new NativeMethod("super", DefaultArgumentsDefinition.builder() .WithRestUnevaluated("arguments") .Arguments, (method, context, message, on, outer) => { object superCell = context.runtime.nul; string realname = out_name; if (realname != null) { superCell = IokeObject.FindSuperCellOn(out_on, out_self, out_context, realname); } if (superCell == context.runtime.nul) { realname = Message.GetName(out_message); superCell = IokeObject.FindSuperCellOn(out_on, out_self, out_context, realname); } if (superCell != context.runtime.nul) { if (IokeObject.dataOf(superCell) is Method) { return Interpreter.Activate(((IokeObject)superCell), context, message, out_on); } else { return superCell; } } else { return Interpreter.SignalNoSuchCell(message, context, out_on, realname, superCell, out_self); } }))); }
public override void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "Dict"; obj.Mimics(IokeObject.As(IokeObject.FindCell(runtime.Mixins, "Sequenced"), null), runtime.nul, runtime.nul); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a hash for the dictionary", new NativeMethod.WithNoArguments("hash", (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); return(context.runtime.NewNumber(((Dict)IokeObject.dataOf(on)).dict.GetHashCode())); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the left hand side dictionary is equal to the right hand side dictionary.", new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(runtime.Dict) .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { Dict d = (Dict)IokeObject.dataOf(on); object other = args[0]; return(((other is IokeObject) && (IokeObject.dataOf(other) is Dict) && d.dict.Equals(((Dict)IokeObject.dataOf(other)).dict)) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes one argument, that should be a default value, and returns a new mimic of the receiver, with the default value for that new dict set to the argument", new TypeCheckingNativeMethod("withDefault", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("defaultValue") .Arguments, (method, on, args, keywords, context, message) => { object newDict = IokeObject.Mimic(on, message, context); SetDefaultValue(newDict, IokeObject.As(args[0], context)); return(newDict); }))); obj.RegisterMethod(runtime.NewNativeMethod("creates a new Dict from the arguments provided, combined with the values in the receiver. the arguments provided will override those in the receiver. the rules for arguments are the same as for dict, except that dicts can also be provided. all positional arguments will be added before the keyword arguments.", new TypeCheckingNativeMethod("merge", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRest("pairsAndDicts") .WithKeywordRest("keywordPairs") .Arguments, (method, on, args, keywords, context, message) => { var newMap = new SaneHashtable(); foreach (DictionaryEntry de in GetMap(on)) { newMap[de.Key] = de.Value; } foreach (object o in args) { if (IokeObject.dataOf(o) is Dict) { foreach (DictionaryEntry de in GetMap(o)) { newMap[de.Key] = de.Value; } } else if (IokeObject.dataOf(o) is Pair) { newMap[Pair.GetFirst(o)] = Pair.GetSecond(o); } else { newMap[o] = context.runtime.nil; } } foreach (var entry in keywords) { string s = entry.Key; object key = context.runtime.GetSymbol(s.Substring(0, s.Length - 1)); object value = entry.Value; if (value == null) { value = context.runtime.nil; } newMap[key] = value; } return(context.runtime.NewDict(newMap)); }))); obj.AliasMethod("merge", "+", null, null); obj.RegisterMethod(runtime.NewNativeMethod("takes one argument, the key of the element to return. if the key doesn't map to anything in the dict, returns the default value", new TypeCheckingNativeMethod("at", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("key") .Arguments, (method, on, args, keywords, context, message) => { object result = Dict.GetMap(on)[args[0]]; if (result == null) { return(GetDefaultValue(on, context, message)); } else { return(result); } }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if this dict is empty, false otherwise", new TypeCheckingNativeMethod.WithNoArguments("empty?", obj, (method, on, args, keywords, context, message) => { return(Dict.GetMap(on).Count == 0 ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes one argument, the key to check if it is in the dict.", new TypeCheckingNativeMethod("key?", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("key") .Arguments, (method, on, args, keywords, context, message) => { return((Dict.GetMap(on).Contains(args[0])) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes two arguments, the key of the element to set and the value to set it too. returns the value set", new TypeCheckingNativeMethod("[]=", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("key") .WithRequiredPositional("value") .Arguments, (method, on, args, keywords, context, message) => { Dict.GetMap(on)[args[0]] = args[1]; return(args[1]); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns the number of pairs contained in this dict.", new TypeCheckingNativeMethod.WithNoArguments("size", obj, (method, on, args, keywords, context, message) => { return(runtime.NewNumber(Dict.GetMap(on).Count)); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("inspect", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewText(Dict.GetInspect(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a brief text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("notice", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewText(Dict.GetNotice(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns all the keys of this dict", new TypeCheckingNativeMethod.WithNoArguments("keys", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewSet(Dict.GetKeys(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a new sequence to iterate over this dictionary", new TypeCheckingNativeMethod.WithNoArguments("seq", obj, (method, on, args, keywords, context, message) => { IokeObject ob = method.runtime.KeyValueIteratorSequence.AllocateCopy(null, null); ob.MimicsWithoutCheck(method.runtime.KeyValueIteratorSequence); ob.Data = new Sequence.KeyValueIteratorSequence(Dict.GetMap(on).GetEnumerator()); return(ob); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes either one or two or three arguments. if one argument is given, it should be a message chain that will be sent to each object in the dict. the result will be thrown away. if two arguments are given, the first is an unevaluated name that will be set to each of the entries in the dict in succession, and then the second argument will be evaluated in a scope with that argument in it. if three arguments is given, the first one is an unevaluated name that will be set to the index of each element, and the other two arguments are the name of the argument for the value, and the actual code. the code will evaluate in a lexical context, and if the argument name is available outside the context, it will be shadowed. the method will return the dict. the entries yielded will be mimics of Pair.", new NativeMethod("each", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("indexOrArgOrCode") .WithOptionalPositionalUnevaluated("argOrCode") .WithOptionalPositionalUnevaluated("code") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); on = runtime.Dict.ConvertToThis(on, message, context); var ls = Dict.GetMap(on); switch (message.Arguments.Count) { case 0: { return(Interpreter.Send(runtime.seqMessage, context, on)); } case 1: { IokeObject code = IokeObject.As(message.Arguments[0], context); foreach (DictionaryEntry o in ls) { context.runtime.interpreter.Evaluate(code, context, context.RealContext, runtime.NewPair(o.Key, o.Value)); } break; } case 2: { IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for Dict#each", context); string name = IokeObject.As(message.Arguments[0], context).Name; IokeObject code = IokeObject.As(message.Arguments[1], context); foreach (DictionaryEntry o in ls) { c.SetCell(name, runtime.NewPair(o.Key, o.Value)); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); } break; } case 3: { IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for Dict#each", context); string iname = IokeObject.As(message.Arguments[0], context).Name; string name = IokeObject.As(message.Arguments[1], context).Name; IokeObject code = IokeObject.As(message.Arguments[2], context); int index = 0; foreach (DictionaryEntry o in ls) { c.SetCell(name, runtime.NewPair(o.Key, o.Value)); c.SetCell(iname, runtime.NewNumber(index++)); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); } break; } } return(on); }))); }
public static void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "DefaultBehavior Literals"; obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument that is expected to be a Text, and returns the symbol corresponding to that text", new NativeMethod(":", DefaultArgumentsDefinition.builder() .WithRequiredPositional("symbolText") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string sym = Text.GetText(Interpreter.Send(runtime.asText, context, args[0])); return(runtime.GetSymbol(sym)); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and returns a new Pair of the receiver and the argument", new NativeMethod("=>", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(context.runtime.NewPair(on, args[0])); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a new message with the name given as argument to this method.", new NativeMethod("message", DefaultArgumentsDefinition.builder() .WithRequiredPositional("name") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); object o = args[0]; string name = null; if (IokeObject.dataOf(o) is Text) { name = Text.GetText(o); } else { name = Text.GetText(Interpreter.Send(context.runtime.asText, context, o)); } Message m = new Message(context.runtime, name); IokeObject ret = context.runtime.CreateMessage(m); if (".".Equals(name)) { Message.SetIsTerminator(ret, true); } Message.CopySourceLocation(message, ret); return(ret); }))); obj.RegisterMethod(runtime.NewNativeMethod("creates a new Set from the result of evaluating all arguments provided.", new NativeMethod("set", DefaultArgumentsDefinition.builder() .WithRest("elements") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(context.runtime.NewSet(args)); }))); obj.RegisterMethod(runtime.NewNativeMethod("creates a new Dict from the arguments provided. these arguments can be two different things - either a keyword argument, or a pair. if it's a keyword argument, the entry added to the dict for it will be a symbol with the name from the keyword, without the ending colon. if it's not a keyword, it is expected to be an evaluated pair, where the first part of the pair is the key, and the second part is the value.", new NativeMethod("dict", DefaultArgumentsDefinition.builder() .WithRest("pairs") .WithKeywordRest("keywordPairs") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); var arguments = message.Arguments; var moo = new SaneHashtable(arguments.Count); foreach (object o in arguments) { object key, value; if (Message.IsKeyword(o)) { string str = Message.GetName(o); key = context.runtime.GetSymbol(str.Substring(0, str.Length - 1)); if (Message.GetNext(o) != null) { value = Interpreter.GetEvaluatedArgument(Message.GetNext(o), context); } else { value = context.runtime.nil; } } else { object result = Interpreter.GetEvaluatedArgument(o, context); if ((result is IokeObject) && (IokeObject.dataOf(result) is Pair)) { key = Pair.GetFirst(result); value = Pair.GetSecond(result); } else { key = result; value = context.runtime.nil; } } moo[key] = value; } return(context.runtime.NewDict(moo)); }))); }
public static void Init(IokeObject obj) { obj.Kind = "Locals"; obj.body.mimicCount = 0; obj.SetCell("=", obj.runtime.Base.body.Get("=")); var assgn = IokeObject.As(obj.runtime.DefaultBehavior.body.Get("Assignment"), null).body; obj.SetCell("++", assgn.Get("++")); obj.SetCell("--", assgn.Get("--")); obj.SetCell("+=", assgn.Get("+=")); obj.SetCell("-=", assgn.Get("-=")); obj.SetCell("/=", assgn.Get("/=")); obj.SetCell("*=", assgn.Get("*=")); obj.SetCell("%=", assgn.Get("%=")); obj.SetCell("**=", assgn.Get("**=")); obj.SetCell("&=", assgn.Get("&=")); obj.SetCell("|=", assgn.Get("|=")); obj.SetCell("^=", assgn.Get("^=")); obj.SetCell("<<=", assgn.Get("<<=")); obj.SetCell(">>=", assgn.Get(">>=")); obj.SetCell("&&=", assgn.Get("&&=")); obj.SetCell("||=", assgn.Get("||=")); obj.SetCell("cell", obj.runtime.Base.body.Get("cell")); obj.SetCell("cell=", obj.runtime.Base.body.Get("cell=")); obj.SetCell("cells", obj.runtime.Base.body.Get("cells")); obj.SetCell("cellNames", obj.runtime.Base.body.Get("cellNames")); obj.SetCell("removeCell!", obj.runtime.Base.body.Get("removeCell!")); obj.SetCell("undefineCell!", obj.runtime.Base.body.Get("undefineCell!")); obj.SetCell("cellOwner?", obj.runtime.Base.body.Get("cellOwner?")); obj.SetCell("cellOwner", obj.runtime.Base.body.Get("cellOwner")); obj.SetCell("identity", obj.runtime.Base.body.Get("identity")); obj.RegisterMethod(obj.runtime.NewNativeMethod("will pass along the call to the real self object of this context.", new NativeMethod("pass", DefaultArgumentsDefinition.builder() .WithRestUnevaluated("arguments") .Arguments, (method, context, message, on, outer) => { object selfDelegate = IokeObject.As(on, context).Self; if(selfDelegate != null && selfDelegate != on) { return Interpreter.Perform(selfDelegate, context, message); } return context.runtime.nil; }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("will return a text representation of the current stack trace", new NativeMethod.WithNoArguments("stackTraceAsText", (method, context, m, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, m, on); Runtime runtime = context.runtime; StringBuilder sb = new StringBuilder(); IokeObject current = IokeObject.As(on, context); while("Locals".Equals(current.GetKind(m, context))) { IokeObject message = IokeObject.As(IokeObject.GetCell(current, m, context, "currentMessage"), context); IokeObject start = message; while(Message.GetPrev(start) != null && Message.GetPrev(start).Line == message.Line) { start = Message.GetPrev(start); } string s1 = Message.Code(start); int ix = s1.IndexOf("\n"); if(ix > -1) { ix--; } sb.Append(string.Format(" {0,-48} {1}\n", (ix == -1 ? s1 : s1.Substring(0,ix)), "[" + message.File + ":" + message.Line + ":" + message.Position + GetContextMessageName(IokeObject.As(current.body.Get("surroundingContext"), context)) + "]")); current = IokeObject.As(IokeObject.FindCell(current, "surroundingContext"), context); } return runtime.NewText(sb.ToString()); }))); }
public static void Init(Runtime runtime) { IokeObject obj = new IokeObject(runtime, "Allows access to the internals of any object without actually using methods on that object"); obj.Kind = "Reflector"; obj.MimicsWithoutCheck(runtime.Origin); runtime.IokeGround.RegisterCell("Reflector", obj); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the documentation text of the object given as argument. anything can have a documentation text - this text will initially be nil.", new TypeCheckingNativeMethod("other:documentation", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { return(Base.Documentation(context, message, args[0])); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("sets the documentation string for a specific object.", new TypeCheckingNativeMethod("other:documentation=", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("text").WhichMustMimic(obj.runtime.Text).OrBeNil() .Arguments, (method, on, args, keywords, context, message) => { return(Base.SetDocumentation(context, message, args[0], args[1])); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("will return a new derivation of the receiving object. Might throw exceptions if the object is an oddball object.", new TypeCheckingNativeMethod("other:mimic", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { return(IokeObject.As(args[0], context).Mimic(message, context)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument that names the cell to set, sets this cell to the result of evaluating the second argument, and returns the value set.", new NativeMethod("other:cell=", DefaultArgumentsDefinition .builder() .WithRequiredPositional("other") .WithRequiredPositional("cellName") .WithRequiredPositional("value") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(Base.AssignCell(context, message, args[0], args[1], args[2])); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns the cell that matches that name, without activating even if it's activatable.", new NativeMethod("other:cell", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1])); return(IokeObject.GetCell(args[0], message, context, name)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns a boolean indicating whether such a cell is reachable from this point.", new NativeMethod("other:cell?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { IList args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1])); return(IokeObject.FindCell((IokeObject)args[0], name) != context.runtime.nul ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns a boolean indicating whether this cell is owned by the receiver or not. the assumption is that the cell should exist. if it doesn't exist, a NoSuchCell condition will be signalled.", new NativeMethod("other:cellOwner?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1])); return((IokeObject.FindPlace(args[0], message, context, name) == args[0]) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns the closest object that defines such a cell. if it doesn't exist, a NoSuchCell condition will be signalled.", new NativeMethod("other:cellOwner", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1])); object result = IokeObject.FindPlace(args[0], message, context, name); if (result == context.runtime.nul) { return(context.runtime.nil); } return(result); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and removes that cell from the current receiver. if the current receiver has no such object, signals a condition. note that if another cell with that name is available in the mimic chain, it will still be accessible after calling this method. the method returns the receiver.", new NativeMethod("other:removeCell!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1])); IokeObject.RemoveCell(args[0], message, context, name); return(args[0]); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and makes that cell undefined in the current receiver. what that means is that from now on it will look like this cell doesn't exist in the receiver or any of its mimics. the cell will not show up if you call cellNames on the receiver or any of the receivers mimics. the undefined status can be removed by doing removeCell! on the correct cell name. a cell name that doesn't exist can still be undefined. the method returns the receiver.", new NativeMethod("other:undefineCell!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1])); IokeObject.UndefineCell(args[0], message, context, name); return(args[0]); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("takes one optional evaluated boolean argument, which defaults to false. if false, this method returns a list of the cell names of the receiver. if true, it returns the cell names of this object and all it's mimics recursively.", new NativeMethod("other:cellNames", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithOptionalPositional("includeMimics", "false") .WithOptionalPositional("cutoff", "nil") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(Base.CellNames(context, message, args[0], args.Count > 1 && IokeObject.IsObjectTrue(args[1]), (args.Count > 2) ? args[2] : null)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("takes one optional evaluated boolean argument, which defaults to false. if false, this method returns a dict of the cell names and values of the receiver. if true, it returns the cell names and values of this object and all it's mimics recursively.", new NativeMethod("other:cells", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithOptionalPositional("includeMimics", "false") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(Base.Cells(context, message, args[0], args.Count > 1 && IokeObject.IsObjectTrue(args[1]))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and returns either true or false if this object or one of it's mimics mimics that argument", new NativeMethod("other:mimics?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("potentialMimic") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject arg = IokeObject.As(args[1], context); if (IokeObject.IsMimic(args[0], arg, context)) { return(context.runtime.True); } else { return(context.runtime.False); } }))); obj.RegisterMethod(runtime.NewNativeMethod("modifies the receiver to be in all ways identical to the argument. if the receiver is nil, true or false, this method can't be used - but those are the only exceptions. it's generally not recommended to use it on kinds and objects that are important for the Ioke runtime, since the result might be highly unpredictable.", new NativeMethod("other:become!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("objectToBecome") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject me = IokeObject.As(args[0], context); IokeObject other = IokeObject.As(args[1], context); if (args[0] == context.runtime.nil || args[0] == context.runtime.True || args[0] == context.runtime.False) { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition, message, context, "Error", "CantMimicOddball"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", args[0]); context.runtime.ErrorCondition(condition); } me.Become(other, message, context); return(args[0]); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a text hex representation of the receiver in upper case hex literal, starting with 0x. This value is based on System.identityHashCode, and as such is not totally guaranteed to be totally unique. but almost.", new TypeCheckingNativeMethod("other:uniqueHexId", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { return(context.runtime.NewText("0x" + System.Convert.ToString(System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(IokeObject.As(args[0], context).body), 16).ToUpper())); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the evaluated argument is the same reference as the receiver, false otherwise.", new NativeMethod("other:same?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("other") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(IokeObject.Same(args[0], args[1]) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes the name of a message to send, and the arguments to give it. send should generally behave exactly as if you had sent the message itself - except that you can give a variable containing the name.", new NativeMethod("other:send", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("messageName") .WithRestUnevaluated("arguments") .WithKeywordRestUnevaluated("keywordArguments") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); object _recv = Interpreter.GetEvaluatedArgument(message, 0, context); object _name = Interpreter.GetEvaluatedArgument(message, 1, context); string name = Text.GetText(Interpreter.Send(runtime.asText, context, _name)); IokeObject newMessage = Message.DeepCopy(message); newMessage.Arguments.RemoveAt(0); newMessage.Arguments.RemoveAt(0); Message.SetName(newMessage, name); return(Interpreter.Send(newMessage, context, _recv)); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated Text argument and returns either true or false if this object or one of it's mimics have the kind of the name specified", new TypeCheckingNativeMethod("other:kind?", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("name").WhichMustMimic(runtime.Text) .Arguments, (method, on, args, keywords, context, message) => { string kind = Text.GetText(args[1]); return(IokeObject.IsKind(args[0], kind, context) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and returns either true or false if this object or one of it's mimics mimics that argument. exactly the same as 'mimics?'", new NativeMethod("other:is?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("potentialMimic") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject arg = IokeObject.As(args[1], context); return(IokeObject.IsMimic(args[0], arg, context) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a list of all the mimics of the receiver. it will not be the same list as is used to back the object, so modifications to this list will not show up in the object.", new TypeCheckingNativeMethod("other:mimics", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { var l = new SaneArrayList(); foreach (object x in IokeObject.GetMimics(args[0], context)) { l.Add(x); } return(context.runtime.NewList(l)); }))); obj.RegisterMethod(runtime.NewNativeMethod("removes all mimics on the receiver, and returns the receiver", new TypeCheckingNativeMethod("other:removeAllMimics!", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { IokeObject.RemoveAllMimics(args[0], message, context); return(args[0]); }))); obj.RegisterMethod(runtime.NewNativeMethod("removes the argument mimic from the list of all mimics on the receiver. will do nothing if the receiver has no such mimic. it returns the receiver", new NativeMethod("other:removeMimic!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("mimicToRemove") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject.RemoveMimic(args[0], args[1], message, context); return(args[0]); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and adds it to the list of mimics for the receiver. the receiver will be returned.", new NativeMethod("other:mimic!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("newMimic") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject newMimic = IokeObject.As(args[1], context); IokeObject.As(args[0], context).Mimics(newMimic, message, context); return(args[0]); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and prepends it to the list of mimics for the receiver. the receiver will be returned.", new NativeMethod("other:prependMimic!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .WithRequiredPositional("newMimic") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject newMimic = IokeObject.As(args[1], context); IokeObject.As(args[0], context).Mimics(0, newMimic, message, context); return(args[0]); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the receiver is frozen, otherwise false", new TypeCheckingNativeMethod("other:frozen?", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { return(IokeObject.As(args[0], context).IsFrozen ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("ensures that the receiver is frozen", new TypeCheckingNativeMethod("other:freeze!", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { IokeObject.Freeze(args[0]); return(args[0]); }))); obj.RegisterMethod(runtime.NewNativeMethod("ensures that the receiver is not frozen", new TypeCheckingNativeMethod("other:thaw!", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { IokeObject.Thaw(args[0]); return(args[0]); }))); }
public override void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "Range"; obj.Mimics(IokeObject.As(IokeObject.FindCell(runtime.Mixins, "Sequenced"), null), runtime.nul, runtime.nul); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the left hand side range is equal to the right hand side range.", new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(runtime.Range) .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { Range d = (Range)IokeObject.dataOf(on); object other = args[0]; return(((other is IokeObject) && (IokeObject.dataOf(other) is Range) && d.inclusive == ((Range)IokeObject.dataOf(other)).inclusive && d.from.Equals(((Range)IokeObject.dataOf(other)).from) && d.to.Equals(((Range)IokeObject.dataOf(other)).to)) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("will return a new inclusive Range based on the two arguments", new NativeMethod("inclusive", DefaultArgumentsDefinition.builder() .WithRequiredPositional("from") .WithRequiredPositional("to") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); object from = args[0]; object to = args[1]; bool comparing = IokeObject.IsMimic(from, IokeObject.As(context.runtime.Mixins.body.Get("Comparing"), context), context); bool inverted = false; if (comparing) { object result = Interpreter.Send(context.runtime.spaceShipMessage, context, from, to); if (result != context.runtime.nil && Number.ExtractInt(result, message, context) == 1) { inverted = true; } } return(runtime.NewRange(IokeObject.As(from, context), IokeObject.As(to, context), true, inverted)); }))); obj.RegisterMethod(runtime.NewNativeMethod("will return a new exclusive Range based on the two arguments", new NativeMethod("exclusive", DefaultArgumentsDefinition.builder() .WithRequiredPositional("from") .WithRequiredPositional("to") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); object from = args[0]; object to = args[1]; bool comparing = IokeObject.IsMimic(from, IokeObject.As(context.runtime.Mixins.body.Get("Comparing"), context), context); bool inverted = false; if (comparing) { object result = Interpreter.Send(context.runtime.spaceShipMessage, context, from, to); if (result != context.runtime.nil && Number.ExtractInt(result, message, context) == 1) { inverted = true; } } return(runtime.NewRange(IokeObject.As(from, context), IokeObject.As(to, context), false, inverted)); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the receiver is an exclusive range, false otherwise", new NativeMethod.WithNoArguments("exclusive?", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(((Range)IokeObject.dataOf(on)).inclusive ? context.runtime.False : context.runtime.True); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the receiver is an inclusive range, false otherwise", new NativeMethod.WithNoArguments("inclusive?", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(((Range)IokeObject.dataOf(on)).inclusive ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns the 'from' part of the range", new TypeCheckingNativeMethod.WithNoArguments("from", obj, (method, on, args, keywords, context, message) => { return(((Range)IokeObject.dataOf(on)).from); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns the 'to' part of the range", new NativeMethod.WithNoArguments("to", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(((Range)IokeObject.dataOf(on)).to); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a new sequence to iterate over this range", new TypeCheckingNativeMethod.WithNoArguments("seq", obj, (method, on, args, keywords, context, message) => { IokeObject ob = method.runtime.Iterator2Sequence.AllocateCopy(null, null); ob.MimicsWithoutCheck(method.runtime.Iterator2Sequence); Range r = ((Range)IokeObject.dataOf(on)); ob.Data = new Sequence.Iterator2Sequence(new RangeIterator(r.from, r.to, r.inclusive, r.inverted, context, message)); return(ob); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes either one or two or three arguments. if one argument is given, it should be a message chain that will be sent to each object in the range. the result will be thrown away. if two arguments are given, the first is an unevaluated name that will be set to each of the values in the range in succession, and then the second argument will be evaluated in a scope with that argument in it. if three arguments is given, the first one is an unevaluated name that will be set to the index of each element, and the other two arguments are the name of the argument for the value, and the actual code. the code will evaluate in a lexical context, and if the argument name is available outside the context, it will be shadowed. the method will return the range.", new NativeMethod("each", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("indexOrArgOrCode") .WithOptionalPositionalUnevaluated("argOrCode") .WithOptionalPositionalUnevaluated("code") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); IokeObject from = IokeObject.As(((Range)IokeObject.dataOf(on)).from, context); IokeObject to = IokeObject.As(((Range)IokeObject.dataOf(on)).to, context); bool inclusive = ((Range)IokeObject.dataOf(on)).inclusive; IokeObject messageToSend = context.runtime.succMessage; if (((Range)IokeObject.dataOf(on)).inverted) { messageToSend = context.runtime.predMessage; } switch (message.Arguments.Count) { case 0: { return(Interpreter.Send(runtime.seqMessage, context, on)); } case 1: { IokeObject code = IokeObject.As(message.Arguments[0], context); object current = from; while (!IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, to))) { context.runtime.interpreter.Evaluate(code, context, context.RealContext, current); current = Interpreter.Send(messageToSend, context, current); } if (inclusive) { context.runtime.interpreter.Evaluate(code, context, context.RealContext, current); } break; } case 2: { IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for Range#each", context); string name = IokeObject.As(message.Arguments[0], context).Name; IokeObject code = IokeObject.As(message.Arguments[1], context); object current = from; while (!IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, to))) { c.SetCell(name, current); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); current = Interpreter.Send(messageToSend, context, current); } if (inclusive) { c.SetCell(name, current); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); } break; } case 3: { IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for Range#each", context); string iname = IokeObject.As(message.Arguments[0], context).Name; string name = IokeObject.As(message.Arguments[1], context).Name; IokeObject code = IokeObject.As(message.Arguments[2], context); int index = 0; object current = from; while (!IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, to))) { c.SetCell(name, current); c.SetCell(iname, runtime.NewNumber(index++)); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); current = Interpreter.Send(messageToSend, context, current); } if (inclusive) { c.SetCell(name, current); c.SetCell(iname, runtime.NewNumber(index++)); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); } break; } } return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the argument is within the confines of this range. how this comparison is done depends on if the object mimics Comparing. If it does, < and > will be used. If not, all the available entries in this range will be enumerated using 'succ'/'pred' until either the end or the element we're looking for is found. in that case, comparison is done with '=='", new NativeMethod("===", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); object other = args[0]; IokeObject from = IokeObject.As(((Range)IokeObject.dataOf(on)).from, context); IokeObject to = IokeObject.As(((Range)IokeObject.dataOf(on)).to, context); bool comparing = IokeObject.IsMimic(from, IokeObject.As(context.runtime.Mixins.body.Get("Comparing"), context)); bool inclusive = ((Range)IokeObject.dataOf(on)).inclusive; if (comparing) { IokeObject firstMessage = context.runtime.lteMessage; IokeObject secondMessageInclusive = context.runtime.gteMessage; IokeObject secondMessageExclusive = context.runtime.gtMessage; if (((Range)IokeObject.dataOf(on)).inverted) { firstMessage = context.runtime.gteMessage; secondMessageInclusive = context.runtime.lteMessage; secondMessageExclusive = context.runtime.ltMessage; } if (IokeObject.IsObjectTrue(Interpreter.Send(firstMessage, context, from, other)) && ((inclusive && IokeObject.IsObjectTrue(Interpreter.Send(secondMessageInclusive, context, to, other))) || IokeObject.IsObjectTrue(Interpreter.Send(secondMessageExclusive, context, to, other)))) { return(context.runtime.True); } else { return(context.runtime.False); } } else { IokeObject messageToSend = context.runtime.succMessage; if (((Range)IokeObject.dataOf(on)).inverted) { messageToSend = context.runtime.predMessage; } object current = from; while (!IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, to))) { if (IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, other))) { return(context.runtime.True); } current = Interpreter.Send(messageToSend, context, current); } if (inclusive && IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, to, other))) { return(context.runtime.True); } return(context.runtime.False); } }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a text inspection of the object", new NativeMethod.WithNoArguments("inspect", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(method.runtime.NewText(Range.GetInspect(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a brief text inspection of the object", new NativeMethod.WithNoArguments("notice", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(method.runtime.NewText(Range.GetNotice(on))); }))); }
public static void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "DefaultBehavior Definitions"; obj.RegisterMethod(runtime.NewNativeMethod("expects any number of unevaluated arguments. if no arguments at all are given, will just return nil. creates a new method based on the arguments. this method will be evaluated using the context of the object it's called on, and thus the definition can not refer to the outside scope where the method is defined. (there are other ways of achieving this). all arguments except the last one is expected to be names of arguments that will be used in the method. there will possible be additions to the format of arguments later on - including named parameters and optional arguments. the actual code is the last argument given.", new NativeMethod("method", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("documentation") .WithRestUnevaluated("argumentsAndBody") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); var args = message.Arguments; if (args.Count == 0) { Message mx = new Message(context.runtime, "nil", null, false); mx.File = Message.GetFile(message); mx.Line = Message.GetLine(message); mx.Position = Message.GetPosition(message); IokeObject mmx = context.runtime.CreateMessage(mx); return(runtime.NewMethod(null, runtime.DefaultMethod, new DefaultMethod(context, DefaultArgumentsDefinition.Empty(), mmx))); } string doc = null; int start = 0; if (args.Count > 1 && ((IokeObject)Message.GetArguments(message)[0]).Name.Equals("internal:createText")) { start++; string s = (string)((IokeObject)args[0]).Arguments[0]; doc = s; } DefaultArgumentsDefinition def = DefaultArgumentsDefinition.CreateFrom(args, start, args.Count - 1, message, on, context); return(runtime.NewMethod(doc, runtime.DefaultMethod, new DefaultMethod(context, def, (IokeObject)args[args.Count - 1]))); }))); obj.RegisterMethod(runtime.NewNativeMethod("expects one code argument, optionally preceeded by a documentation string. will create a new DefaultMacro based on the code and return it.", new NativeMethod("macro", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("documentation") .WithOptionalPositionalUnevaluated("body") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); var args = message.Arguments; if (args.Count == 0) { Message mx = new Message(context.runtime, "nil", null, false); mx.File = Message.GetFile(message); mx.Line = Message.GetLine(message); mx.Position = Message.GetPosition(message); IokeObject mmx = context.runtime.CreateMessage(mx); return(runtime.NewMacro(null, runtime.DefaultMacro, new DefaultMacro(context, mmx))); } string doc = null; int start = 0; if (args.Count > 1 && ((IokeObject)Message.GetArguments(message)[0]).Name.Equals("internal:createText")) { start++; string s = (string)(((IokeObject)args[0]).Arguments[0]); doc = s; } return(runtime.NewMacro(doc, runtime.DefaultMacro, new DefaultMacro(context, (IokeObject)args[start]))); }))); obj.RegisterMethod(runtime.NewNativeMethod("creates a new lexical block that can be executed at will, while retaining a reference to the lexical closure it was created in. it will always update variables if they exist. there is currently no way of introducing shadowing variables in the local context. new variables can be created though, just like in a method. a lexical block mimics LexicalBlock, and can take arguments. at the moment these are restricted to required arguments, but support for the same argument types as DefaultMethod will come.", new NativeMethod("fn", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("documentation") .WithRestUnevaluated("argumentsAndBody") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); var args = message.Arguments; if (args.Count == 0) { return(runtime.NewLexicalBlock(null, runtime.LexicalBlock, new LexicalBlock(context, DefaultArgumentsDefinition.Empty(), method.runtime.nilMessage))); } string doc = null; int start = 0; if (args.Count > 1 && ((IokeObject)Message.GetArguments(message)[0]).Name.Equals("internal:createText")) { start++; string s = ((string)((IokeObject)args[0]).Arguments[0]); doc = s; } IokeObject code = IokeObject.As(args[args.Count - 1], context); DefaultArgumentsDefinition def = DefaultArgumentsDefinition.CreateFrom(args, start, args.Count - 1, message, on, context); return(runtime.NewLexicalBlock(doc, runtime.LexicalBlock, new LexicalBlock(context, def, code))); }))); obj.RegisterMethod(runtime.NewNativeMethod("expects one code argument, optionally preceeded by a documentation string. will create a new LexicalMacro based on the code and return it.", new NativeMethod("lecro", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("documentation") .WithOptionalPositionalUnevaluated("body") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); var args = message.Arguments; if (args.Count == 0) { Message mx = new Message(context.runtime, "nil", null, false); mx.File = Message.GetFile(message); mx.Line = Message.GetLine(message); mx.Position = Message.GetPosition(message); IokeObject mmx = context.runtime.CreateMessage(mx); return(runtime.NewMacro(null, runtime.LexicalMacro, new LexicalMacro(context, mmx))); } string doc = null; int start = 0; if (args.Count > 1 && ((IokeObject)Message.GetArguments(message)[0]).Name.Equals("internal:createText")) { start++; string s = ((string)((IokeObject)args[0]).Arguments[0]); doc = s; } return(runtime.NewMacro(doc, runtime.LexicalMacro, new LexicalMacro(context, (IokeObject)args[start]))); }))); obj.RegisterMethod(runtime.NewNativeMethod("expects one code argument, optionally preceeded by a documentation string. will create a new DefaultSyntax based on the code and return it.", new NativeMethod("syntax", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("documentation") .WithOptionalPositionalUnevaluated("body") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); var args = message.Arguments; if (args.Count == 0) { Message mx = new Message(context.runtime, "nil", null, false); mx.File = Message.GetFile(message); mx.Line = Message.GetLine(message); mx.Position = Message.GetPosition(message); IokeObject mmx = context.runtime.CreateMessage(mx); return(runtime.NewMacro(null, runtime.DefaultSyntax, new DefaultSyntax(context, mmx))); } string doc = null; int start = 0; if (args.Count > 1 && ((IokeObject)Message.GetArguments(message)[0]).Name.Equals("internal:createText")) { start++; string s = (string)((IokeObject)args[0]).Arguments[0]; doc = s; } return(runtime.NewMacro(doc, runtime.DefaultSyntax, new DefaultSyntax(context, (IokeObject)args[start]))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes two evaluated text or symbol arguments that name the method to alias, and the new name to give it. returns the receiver.", new NativeMethod("aliasMethod", DefaultArgumentsDefinition.builder() .WithRequiredPositional("oldName") .WithRequiredPositional("newName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string fromName = Text.GetText(Interpreter.Send(runtime.asText, context, args[0])); string toName = Text.GetText(Interpreter.Send(runtime.asText, context, args[1])); IokeObject.As(on, context).AliasMethod(fromName, toName, message, context); return(on); }))); }
public override void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "System"; if (currentWorkingDirectory == null) { // Use CLRs CWD try { currentWorkingDirectory = System.IO.Directory.GetCurrentDirectory(); } catch (System.Exception) { currentWorkingDirectory = "."; } } var l = new SaneArrayList(); l.Add(runtime.NewText(".")); loadPath = runtime.NewList(l); programArguments = runtime.NewList(new SaneArrayList()); IokeObject outx = runtime.Io.Mimic(null, null); outx.Data = new IokeIO(runtime.Out); obj.RegisterCell("out", outx); IokeObject errx = runtime.Io.Mimic(null, null); errx.Data = new IokeIO(runtime.Error); obj.RegisterCell("err", errx); IokeObject inx = runtime.Io.Mimic(null, null); inx.Data = new IokeIO(runtime.In); obj.RegisterCell("in", inx); obj.RegisterCell("currentDebugger", runtime.nil); obj.RegisterMethod(runtime.NewNativeMethod("takes one text or symbol argument and returns a boolean indicating whether the named feature is available on this runtime.", new NativeMethod("feature?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("feature") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(runtime.asText, context, args[0])); if (FEATURES.Contains(name)) { return(runtime.True); } else { return(runtime.False); } }))); obj.RegisterMethod(runtime.NewNativeMethod("returns the current file executing", new NativeMethod.WithNoArguments("currentFile", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(runtime.NewText(((IokeSystem)IokeObject.dataOf(on)).currentFile[0])); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if running on windows, otherwise false", new NativeMethod.WithNoArguments("windows?", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(DOSISH ? runtime.True : runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns the current load path", new NativeMethod.WithNoArguments("loadPath", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(((IokeSystem)IokeObject.dataOf(on)).loadPath); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a random number", new NativeMethod.WithNoArguments("randomNumber", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(context.runtime.NewNumber(((IokeSystem)IokeObject.dataOf(on)).random.Next())); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns the current working directory", new NativeMethod.WithNoArguments("currentWorkingDirectory", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(context.runtime.NewText(context.runtime.CurrentWorkingDirectory)); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns the host name of the local machine", new NativeMethod.WithNoArguments("hostName", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); string tt = System.Net.Dns.GetHostName(); return(context.runtime.NewText(tt)); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns the current directory that the code is executing in", new NativeMethod.WithNoArguments("currentDirectory", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); string name = Message.GetFile(message); FileInfo f = null; if (IsAbsoluteFileName(name)) { f = new FileInfo(name); } else { f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name)); } if (f.Exists) { return(context.runtime.NewText(f.Directory.FullName)); } return(context.runtime.nil); }))); obj.RegisterMethod(runtime.NewNativeMethod("forcibly exits the currently running interpreter. takes one optional argument that defaults to 1 - which is the value to return from the process, if the process is exited.", new NativeMethod("exit", DefaultArgumentsDefinition.builder() .WithOptionalPositional("other", "1") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); int val = 1; if (args.Count > 0) { object arg = args[0]; if (arg == context.runtime.True) { val = 0; } else if (arg == context.runtime.False) { val = 1; } else { val = Number.ExtractInt(arg, message, context); } } throw new ControlFlow.Exit(val); }))); obj.RegisterCell("programArguments", programArguments); obj.RegisterMethod(runtime.NewNativeMethod("returns result of evaluating first argument", new NativeMethod("ifMain", DefaultArgumentsDefinition.builder() .WithRequiredPositionalUnevaluated("code") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); if (((IokeSystem)IokeObject.dataOf(on)).CurrentProgram.Equals(message.File)) { IokeObject msg = ((IokeObject)message.Arguments[0]); return(context.runtime.interpreter.Evaluate(msg, context, context.RealContext, context)); } else { return(runtime.nil); } }))); obj.RegisterMethod(runtime.NewNativeMethod("adds a new piece of code that should be executed on exit", new NativeMethod("atExit", DefaultArgumentsDefinition.builder() .WithRequiredPositionalUnevaluated("code") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); GetAtExits(on).Add(new AtExitInfo(context, IokeObject.As(message.Arguments[0], context))); return(context.runtime.nil); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes one evaluated string argument and a boolean of whether loading should be forced or not. will import the file corresponding to the string based on the Ioke loading behavior", new NativeMethod("lowLevelLoad!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("module") .WithRequiredPositional("forceReload") .Arguments, (method, context, message, on, outer) => { IList args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); bool forceReload = IokeObject.IsObjectTrue(args[1]); string name = Text.GetText(Interpreter.Send(runtime.asText, context, args[0])); if (((IokeSystem)IokeObject.dataOf(runtime.System)).Use(IokeObject.As(on, context), context, message, name, forceReload)) { return(runtime.True); } else { return(runtime.False); } }))); }
public override void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "Set"; obj.Mimics(IokeObject.As(IokeObject.FindCell(runtime.Mixins, "Sequenced"), null), runtime.nul, runtime.nul); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a hash for the set", new NativeMethod.WithNoArguments("hash", (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); return(context.runtime.NewNumber(((IokeSet)IokeObject.dataOf(on))._set.GetHashCode())); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the left hand side set is equal to the right hand side set.", new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(runtime.Set) .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { IokeSet d = (IokeSet)IokeObject.dataOf(on); object other = args[0]; return(((other is IokeObject) && (IokeObject.dataOf(other) is IokeSet) && d._set.Equals(((IokeSet)IokeObject.dataOf(other))._set)) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("inspect", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewText(IokeSet.GetInspect(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Converts this set to use identity semantics, and then returns it.", new TypeCheckingNativeMethod.WithNoArguments("withIdentitySemantics!", obj, (method, on, args, keywords, context, message) => { IokeSet ss = (IokeSet)IokeObject.dataOf(on); ss._set = new SaneHashSet <object>(ss._set, new IdentityHashTable.IdentityEqualityComparer()); return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a brief text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("notice", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewText(IokeSet.GetNotice(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if this set is empty, false otherwise", new TypeCheckingNativeMethod.WithNoArguments("empty?", obj, (method, on, args, keywords, context, message) => { return(((IokeSet)IokeObject.dataOf(on)).Set.Count == 0 ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("Adds the argument to this set, if it's not already in the set. Returns the set after adding the object.", new TypeCheckingNativeMethod("<<", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("value") .Arguments, (method, on, args, keywords, context, message) => { ((IokeSet)IokeObject.dataOf(on))._set.Add(args[0]); return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("Removes the argument from the set, if it's in the set. Returns the set after removing the object.", new TypeCheckingNativeMethod("remove!", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("value") .Arguments, (method, on, args, keywords, context, message) => { ((IokeSet)IokeObject.dataOf(on))._set.Remove(args[0]); return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a new set that contains the receivers elements and the elements of the set sent in as the argument.", new TypeCheckingNativeMethod("+", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("otherSet").WhichMustMimic(obj) .Arguments, (method, on, args, keywords, context, message) => { var newSet = new SaneHashSet <object>(); newSet.UnionWith(((IokeSet)IokeObject.dataOf(on)).Set); newSet.UnionWith(((IokeSet)IokeObject.dataOf(args[0])).Set); return(context.runtime.NewSet(newSet)); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a new set that is the intersection of the receiver and the argument.", new TypeCheckingNativeMethod("\u2229", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("otherSet").WhichMustMimic(obj) .Arguments, (method, on, args, keywords, context, message) => { var newSet = new SaneHashSet <object>(); newSet.UnionWith(((IokeSet)IokeObject.dataOf(on)).Set); newSet.IntersectWith(((IokeSet)IokeObject.dataOf(args[0])).Set); return(context.runtime.NewSet(newSet)); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if this set is a subset of the argument set", new TypeCheckingNativeMethod("\u2286", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("otherSet").WhichMustMimic(obj) .Arguments, (method, on, args, keywords, context, message) => { var one = ((IokeSet)IokeObject.dataOf(args[0])).Set; var two = ((IokeSet)IokeObject.dataOf(on)).Set; var result = two.IsSubsetOf(one); return(result ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if this set is a proper subset of the argument set", new TypeCheckingNativeMethod("\u2282", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("otherSet").WhichMustMimic(obj) .Arguments, (method, on, args, keywords, context, message) => { var one = ((IokeSet)IokeObject.dataOf(args[0])).Set; var two = ((IokeSet)IokeObject.dataOf(on)).Set; var result = two.IsProperSubsetOf(one); if (one.Count == 0 && two.Count == 0) { result = false; } return(result ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if this set is a superset of the argument set", new TypeCheckingNativeMethod("\u2287", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("otherSet").WhichMustMimic(obj) .Arguments, (method, on, args, keywords, context, message) => { var one = ((IokeSet)IokeObject.dataOf(args[0])).Set; var two = ((IokeSet)IokeObject.dataOf(on)).Set; var result = two.IsSupersetOf(one); return(result ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if this set is a proper superset of the argument set", new TypeCheckingNativeMethod("\u2283", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("otherSet").WhichMustMimic(obj) .Arguments, (method, on, args, keywords, context, message) => { var one = ((IokeSet)IokeObject.dataOf(args[0])).Set; var two = ((IokeSet)IokeObject.dataOf(on)).Set; var result = two.IsProperSupersetOf(one); return(result ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the receiver includes the evaluated argument, otherwise false", new TypeCheckingNativeMethod("include?", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("object") .Arguments, (method, on, args, keywords, context, message) => { return(((IokeSet)IokeObject.dataOf(on)).Set.Contains(args[0]) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a new sequence to iterate over this set", new TypeCheckingNativeMethod.WithNoArguments("seq", obj, (method, on, args, keywords, context, message) => { IokeObject ob = method.runtime.IteratorSequence.AllocateCopy(null, null); ob.MimicsWithoutCheck(method.runtime.IteratorSequence); ob.Data = new Sequence.IteratorSequence(((IokeSet)IokeObject.dataOf(on))._set.GetEnumerator()); return(ob); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes either one, two or three arguments. if one argument is given, it should be a message chain that will be sent to each object in the set. the result will be thrown away. if two arguments are given, the first is an unevaluated name that will be set to each of the values in the set in succession, and then the second argument will be evaluated in a scope with that argument in it. if three arguments is given, the first one is an unevaluated name that will be set to the index of each element, and the other two arguments are the name of the argument for the value, and the actual code. the code will evaluate in a lexical context, and if the argument name is available outside the context, it will be shadowed. the method will return the set. the iteration order is not defined.", new NativeMethod("each", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("indexOrArgOrCode") .WithOptionalPositionalUnevaluated("argOrCode") .WithOptionalPositionalUnevaluated("code") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); object onAsSet = context.runtime.Set.ConvertToThis(on, message, context); var _set = ((IokeSet)IokeObject.dataOf(onAsSet))._set; switch (message.Arguments.Count) { case 0: { return(Interpreter.Send(runtime.seqMessage, context, on)); } case 1: { IokeObject code = IokeObject.As(message.Arguments[0], context); foreach (object o in _set) { context.runtime.interpreter.Evaluate(code, context, context.RealContext, o); } break; } case 2: { IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for Set#each", context); string name = IokeObject.As(message.Arguments[0], context).Name; IokeObject code = IokeObject.As(message.Arguments[1], context); foreach (object o in _set) { c.SetCell(name, o); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); } break; } case 3: { IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for Set#each", context); string iname = IokeObject.As(message.Arguments[0], context).Name; string name = IokeObject.As(message.Arguments[1], context).Name; IokeObject code = IokeObject.As(message.Arguments[2], context); int index = 0; foreach (object o in _set) { c.SetCell(name, o); c.SetCell(iname, runtime.NewNumber(index++)); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); } break; } } return(onAsSet); }))); }
public static void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "FileSystem"; IokeObject file = new IokeObject(runtime, "represents a file in the file system", new IokeFile(null)); file.MimicsWithoutCheck(runtime.Io); file.Init(); obj.RegisterCell("File", file); obj.RegisterMethod(runtime.NewNativeMethod("Tries to interpret the given arguments as strings describing file globs, and returns an array containing the result of applying these globs.", new NativeMethod("[]", DefaultArgumentsDefinition.builder() .WithRest("globTexts") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); var dirs = FileSystem.Glob(context.runtime, IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0]))); var result = new SaneArrayList(); foreach (string s in dirs) { result.Add(context.runtime.NewText(s)); } return(context.runtime.NewList(result)); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and returns true if it's the relative or absolute name of a directory, and false otherwise.", new NativeMethod("directory?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("directoryName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0])); DirectoryInfo f = null; if (IokeSystem.IsAbsoluteFileName(name)) { f = new DirectoryInfo(name); } else { f = new DirectoryInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name)); } return(f.Exists ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument that should be a file name, and returns a text of the contents of this file.", new NativeMethod("readFully", DefaultArgumentsDefinition.builder() .WithRequiredPositional("fileName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0])); FileInfo f = null; if (IokeSystem.IsAbsoluteFileName(name)) { f = new FileInfo(name); } else { f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name)); } return(context.runtime.NewText(File.ReadAllText(f.FullName))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and returns true if it's the relative or absolute name of a file, and false otherwise.", new NativeMethod("file?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("fileName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0])); FileInfo f = null; if (IokeSystem.IsAbsoluteFileName(name)) { f = new FileInfo(name); } else { f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name)); } return(f.Exists ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and returns true if it's the relative or absolute name of something that exists.", new NativeMethod("exists?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("entryName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0])); string nx = null; if (IokeSystem.IsAbsoluteFileName(name)) { nx = name; } else { nx = Path.Combine(context.runtime.CurrentWorkingDirectory, name); } return((new FileInfo(nx).Exists || new DirectoryInfo(nx).Exists) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument that should be the path of a file or directory, and returns the parent of it - or nil if there is no parent.", new NativeMethod("parentOf", DefaultArgumentsDefinition.builder() .WithRequiredPositional("entryName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(args[0]); string nx; if (IokeSystem.IsAbsoluteFileName(name)) { nx = name; } else { nx = Path.Combine(context.runtime.CurrentWorkingDirectory, name); } string parent = Path.GetDirectoryName(nx); if (parent == null) { return(context.runtime.nil); } string cwd = context.runtime.CurrentWorkingDirectory; if (!IokeSystem.IsAbsoluteFileName(name) && parent.Equals(cwd)) { return(context.runtime.nil); } if (parent.StartsWith(cwd)) { parent = parent.Substring(cwd.Length + 1); } return(context.runtime.NewText(parent)); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes a file name and a lexical block - opens the file, ensures that it exists and then yields the file to the block. Finally it closes the file after the block has finished executing, and then returns the result of the block.", new NativeMethod("withOpenFile", DefaultArgumentsDefinition.builder() .WithRequiredPositional("fileName") .WithRequiredPositional("code") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0])); FileInfo f = null; if (IokeSystem.IsAbsoluteFileName(name)) { f = new FileInfo(name); } else { f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name)); } try { if (!f.Exists) { using (FileStream fs = File.Create(f.FullName)) { } } } catch (IOException) { } IokeObject ff = context.runtime.NewFile(context, f); object result = context.runtime.nil; try { result = Interpreter.Send(context.runtime.callMessage, context, args[1], ff); } finally { Interpreter.Send(context.runtime.closeMessage, context, ff); } return(result); }))); obj.RegisterMethod(runtime.NewNativeMethod("Copies a file. Takes two text arguments, where the first is the name of the file to copy and the second is the name of the destination. If the destination is a directory, the file will be copied with the same name, and if it's a filename, the file will get a new name", new NativeMethod("copyFile", DefaultArgumentsDefinition.builder() .WithRequiredPositional("fileName") .WithRequiredPositional("destination") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(args[0]); FileInfo f = null; if (IokeSystem.IsAbsoluteFileName(name)) { f = new FileInfo(name); } else { f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name)); } string name2 = Text.GetText(args[1]); string nx = null; if (IokeSystem.IsAbsoluteFileName(name2)) { nx = name2; } else { nx = Path.Combine(context.runtime.CurrentWorkingDirectory, name2); } if (new DirectoryInfo(nx).Exists) { nx = Path.Combine(nx, f.Name); } try { File.Copy(f.FullName, nx, true); } catch (IOException) { } return(context.runtime.nil); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and creates a directory with that name. It also takes an optional second argument. If it's true, will try to create all necessary directories inbetween. Default is false. Will signal a condition if the directory already exists, or if there's a file with that name.", new NativeMethod("createDirectory!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("directoryName") .WithOptionalPositional("createPath", "false") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0])); DirectoryInfo f = null; if (IokeSystem.IsAbsoluteFileName(name)) { f = new DirectoryInfo(name); } else { f = new DirectoryInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name)); } if (f.Exists || new FileInfo(f.FullName).Exists) { string msg = null; if (f.Exists) { msg = "Can't create directory '" + name + "' since there already exists a directory with that name"; } else { msg = "Can't create directory '" + name + "' since there already exists a file with that name"; } IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "IO"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("text", runtime.NewText(msg)); runtime.WithReturningRestart("ignore", context, () => { runtime.ErrorCondition(condition); }); } Directory.CreateDirectory(f.FullName); return(context.runtime.nil); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and removes a directory with that name. Will signal a condition if the directory doesn't exist, or if there's a file with that name.", new NativeMethod("removeDirectory!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("directoryName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0])); string nf = null; if (IokeSystem.IsAbsoluteFileName(name)) { nf = name; } else { nf = Path.Combine(context.runtime.CurrentWorkingDirectory, name); } if (!(new DirectoryInfo(nf).Exists) || new FileInfo(nf).Exists) { string msg = null; if (!(new DirectoryInfo(nf).Exists)) { msg = "Can't remove directory '" + name + "' since it doesn't exist"; } else { msg = "Can't remove directory '" + name + "' since it is a file"; } IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "IO"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("text", runtime.NewText(msg)); runtime.WithReturningRestart("ignore", context, () => { runtime.ErrorCondition(condition); }); } Directory.Delete(nf); return(context.runtime.nil); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and removes a file with that name. Will signal a condition if the file doesn't exist, or if there's a directory with that name.", new NativeMethod("removeFile!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("fileName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0])); string nf = null; if (IokeSystem.IsAbsoluteFileName(name)) { nf = name; } else { nf = Path.Combine(context.runtime.CurrentWorkingDirectory, name); } if (!(new FileInfo(nf).Exists) || new DirectoryInfo(nf).Exists) { string msg = null; if (!(new FileInfo(nf).Exists)) { msg = "Can't remove file '" + name + "' since it doesn't exist"; } else { msg = "Can't remove file '" + name + "' since it is a directory"; } IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "IO"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("text", runtime.NewText(msg)); runtime.WithReturningRestart("ignore", context, () => { runtime.ErrorCondition(condition); }); } File.Delete(nf); return(context.runtime.nil); }))); }
public static void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "DefaultBehavior Conditions"; obj.RegisterMethod(runtime.NewNativeMethod("takes one optional unevaluated parameter (this should be the first if provided), that is the name of the restart to create. this will default to nil. takes two keyword arguments, report: and test:. These should both be lexical blocks. if not provided, there will be reasonable defaults. the only required argument is something that evaluates into a lexical block. this block is what will be executed when the restart is invoked. will return a Restart mimic.", new NativeMethod("restart", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("name") .WithKeyword("report") .WithKeyword("test") .WithRequiredPositional("action") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); string name = null; IokeObject report = null; IokeObject test = null; IokeObject code = null; IList args = message.Arguments; int argCount = args.Count; if (argCount > 4) { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Invocation", "TooManyArguments"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("extra", runtime.NewList(ArrayList.Adapter(args).GetRange(4, argCount - 4))); runtime.WithReturningRestart("ignoreExtraArguments", context, () => { runtime.ErrorCondition(condition); }); argCount = 4; } else if (argCount < 1) { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Invocation", "TooFewArguments"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("missing", runtime.NewNumber(1 - argCount)); runtime.ErrorCondition(condition); } for (int i = 0; i < argCount; i++) { object o = args[i]; Message m = (Message)IokeObject.dataOf(o); if (m.IsKeyword()) { string n = m.Name; if (n.Equals("report:")) { report = IokeObject.As(runtime.interpreter.Evaluate(m.next, context, context.RealContext, context), context); } else if (n.Equals("test:")) { test = IokeObject.As(runtime.interpreter.Evaluate(m.next, context, context.RealContext, context), context); } else { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Invocation", "MismatchedKeywords"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("expected", runtime.NewList(new SaneArrayList(new object[] { runtime.NewText("report:"), runtime.NewText("test:") }))); IList extra = new SaneArrayList(); extra.Add(runtime.NewText(n)); condition.SetCell("extra", runtime.NewList(extra)); runtime.WithReturningRestart("ignoreExtraKeywords", context, () => { runtime.ErrorCondition(condition); }); } } else { if (code != null) { name = code.Name; code = IokeObject.As(o, context); } else { code = IokeObject.As(o, context); } } } code = IokeObject.As(runtime.interpreter.Evaluate(code, context, context.RealContext, context), context); object restart = Interpreter.Send(runtime.mimicMessage, context, runtime.Restart); IokeObject.SetCell(restart, "code", code, context); if (null != name) { IokeObject.SetCell(restart, "name", runtime.GetSymbol(name), context); } if (null != test) { IokeObject.SetCell(restart, "test", test, context); } if (null != report) { IokeObject.SetCell(restart, "report", report, context); } return(restart); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes zero or more arguments that should evaluate to a condition mimic - this list will match all the conditions this Rescue should be able to catch. the last argument is not optional, and should be something activatable that takes one argument - the condition instance. will return a Rescue mimic.", new NativeMethod("rescue", DefaultArgumentsDefinition.builder() .WithRest("conditionsAndAction") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); int count = message.Arguments.Count; IList conds = new SaneArrayList(); for (int i = 0, j = count - 1; i < j; i++) { conds.Add(Interpreter.GetEvaluatedArgument(message, i, context)); } if (conds.Count == 0) { conds.Add(context.runtime.Condition); } object handler = Interpreter.GetEvaluatedArgument(message, count - 1, context); object rescue = Interpreter.Send(context.runtime.mimicMessage, context, context.runtime.Rescue); IokeObject.SetCell(rescue, "handler", handler, context); IokeObject.SetCell(rescue, "conditions", context.runtime.NewList(conds), context); return(rescue); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes zero or more arguments that should evaluate to a condition mimic - this list will match all the conditions this Handler should be able to catch. the last argument is not optional, and should be something activatable that takes one argument - the condition instance. will return a Handler mimic.", new NativeMethod("handle", DefaultArgumentsDefinition.builder() .WithRest("conditionsAndAction") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); int count = message.Arguments.Count; IList conds = new SaneArrayList(); for (int i = 0, j = count - 1; i < j; i++) { conds.Add(Interpreter.GetEvaluatedArgument(message, i, context)); } if (conds.Count == 0) { conds.Add(context.runtime.Condition); } object code = Interpreter.GetEvaluatedArgument(message, count - 1, context); object handle = Interpreter.Send(context.runtime.mimicMessage, context, context.runtime.Handler); IokeObject.SetCell(handle, "handler", code, context); IokeObject.SetCell(handle, "conditions", context.runtime.NewList(conds), context); return(handle); }))); obj.RegisterMethod(runtime.NewNativeMethod("will evaluate all arguments, and expects all except for the last to be a Restart. bind will associate these restarts for the duration of the execution of the last argument and then unbind them again. it will return the result of the last argument, or if a restart is executed it will instead return the result of that invocation.", new NativeMethod("bind", DefaultArgumentsDefinition.builder() .WithRestUnevaluated("bindablesAndCode") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); IList args = message.Arguments; int argCount = args.Count; if (argCount == 0) { return(context.runtime.nil); } IokeObject code = IokeObject.As(args[argCount - 1], context); var restarts = new SaneList <Runtime.RestartInfo>(); var rescues = new SaneList <Runtime.RescueInfo>(); var handlers = new SaneList <Runtime.HandlerInfo>(); Runtime.BindIndex index = context.runtime.GetBindIndex(); bool doUnregister = true; try { foreach (object o in ArrayList.Adapter(args).GetRange(0, argCount - 1)) { IokeObject msg = IokeObject.As(o, context); IokeObject bindable = IokeObject.As(runtime.interpreter.Evaluate(msg, context, context.RealContext, context), context); bool loop = false; do { loop = false; if (IokeObject.IsKind(bindable, "Restart")) { object ioName = Interpreter.Send(runtime.nameMessage, context, bindable); string name = null; if (ioName != runtime.nil) { name = Symbol.GetText(ioName); } restarts.Insert(0, new Runtime.RestartInfo(name, bindable, restarts, index, null)); index = index.NextCol(); } else if (IokeObject.IsKind(bindable, "Rescue")) { object conditions = Interpreter.Send(runtime.conditionsMessage, context, bindable); var applicable = IokeList.GetList(conditions); rescues.Insert(0, new Runtime.RescueInfo(bindable, applicable, rescues, index)); index = index.NextCol(); } else if (IokeObject.IsKind(bindable, "Handler")) { object conditions = Interpreter.Send(runtime.conditionsMessage, context, bindable); var applicable = IokeList.GetList(conditions); handlers.Insert(0, new Runtime.HandlerInfo(bindable, applicable, handlers, index)); index = index.NextCol(); } else { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Type", "IncorrectType"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("expectedType", runtime.GetSymbol("Bindable")); object[] newCell = new object[] { bindable }; runtime.WithRestartReturningArguments(() => { runtime.ErrorCondition(condition); }, context, new IokeObject.UseValue("bindable", newCell)); bindable = IokeObject.As(newCell[0], context); loop = true; } } while(loop); loop = false; } runtime.RegisterRestarts(restarts); runtime.RegisterRescues(rescues); runtime.RegisterHandlers(handlers); return(runtime.interpreter.Evaluate(code, context, context.RealContext, context)); } catch (ControlFlow.Restart e) { Runtime.RestartInfo ri = null; if ((ri = e.GetRestart).token == restarts) { runtime.UnregisterHandlers(handlers); runtime.UnregisterRescues(rescues); runtime.UnregisterRestarts(restarts); doUnregister = false; return(Interpreter.Send(runtime.callMessage, context, Interpreter.Send(runtime.codeMessage, context, ri.restart), e.Arguments)); } else { throw e; } } catch (ControlFlow.Rescue e) { Runtime.RescueInfo ri = null; if ((ri = e.GetRescue).token == rescues) { runtime.UnregisterHandlers(handlers); runtime.UnregisterRescues(rescues); runtime.UnregisterRestarts(restarts); doUnregister = false; return(Interpreter.Send(runtime.callMessage, context, Interpreter.Send(runtime.handlerMessage, context, ri.rescue), e.Condition)); } else { throw e; } } finally { if (doUnregister) { runtime.UnregisterHandlers(handlers); runtime.UnregisterRescues(rescues); runtime.UnregisterRestarts(restarts); } } }))); obj.RegisterMethod(runtime.NewNativeMethod("takes either a name (as a symbol) or a Restart instance. if the restart is active, will transfer control to it, supplying the rest of the given arguments to that restart.", new NativeMethod("invokeRestart", DefaultArgumentsDefinition.builder() .WithRequiredPositional("nameOrRestart") .WithRest("arguments") .Arguments, (method, context, message, on, outer) => { IList posArgs = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, posArgs, new SaneDictionary <string, object>()); IokeObject restart = IokeObject.As(posArgs[0], context); Runtime.RestartInfo realRestart = null; var args = new SaneArrayList(); if (restart.IsSymbol) { string name = Symbol.GetText(restart); realRestart = context.runtime.FindActiveRestart(name); if (null == realRestart) { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "RestartNotActive"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("restart", restart); runtime.WithReturningRestart("ignoreMissingRestart", context, () => { runtime.ErrorCondition(condition); }); return(runtime.nil); } } else { realRestart = context.runtime.FindActiveRestart(restart); if (null == realRestart) { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "RestartNotActive"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("restart", restart); runtime.WithReturningRestart("ignoreMissingRestart", context, () => { runtime.ErrorCondition(condition); }); return(runtime.nil); } } int argCount = posArgs.Count; for (int i = 1; i < argCount; i++) { args.Add(posArgs[i]); } throw new ControlFlow.Restart(realRestart, args); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes either a name (as a symbol) or a Restart instance. if the restart is active, will return that restart, otherwise returns nil.", new NativeMethod("findRestart", DefaultArgumentsDefinition.builder() .WithRequiredPositional("nameOrRestart") .Arguments, (method, context, message, on, outer) => { IList args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject restart = IokeObject.As(args[0], context); Runtime.RestartInfo realRestart = null; while (!(restart.IsSymbol || restart.GetKind(message, context).Equals("Restart"))) { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Type", "IncorrectType"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("expectedType", runtime.GetSymbol("Restart")); object[] newCell = new object[] { restart }; runtime.WithRestartReturningArguments(() => { runtime.ErrorCondition(condition); }, context, new IokeObject.UseValue("restart", newCell)); restart = IokeObject.As(newCell[0], context); } if (restart.IsSymbol) { string name = Symbol.GetText(restart); realRestart = runtime.FindActiveRestart(name); } else if (restart.GetKind(message, context).Equals("Restart")) { realRestart = runtime.FindActiveRestart(restart); } if (realRestart == null) { return(runtime.nil); } else { return(realRestart.restart); } }))); obj.RegisterMethod(runtime.NewNativeMethod("takes an optional condition to specify - returns all restarts that are applicable to that condition. closer restarts will be first in the list", new NativeMethod("availableRestarts", DefaultArgumentsDefinition.builder() .WithOptionalPositional("condition", "Condition") .Arguments, (method, context, message, on, outer) => { IList args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); object toLookFor = runtime.Condition; if (args.Count > 0) { toLookFor = args[0]; } var result = new SaneArrayList(); var activeRestarts = runtime.ActiveRestarts; foreach (var lri in activeRestarts) { foreach (var rri in lri) { if (IokeObject.IsObjectTrue(Interpreter.Send(runtime.callMessage, context, Interpreter.Send(runtime.testMessage, context, rri.restart), toLookFor))) { result.Add(rri.restart); } } } return(runtime.NewList(result)); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes one or more datums descibing the condition to signal. this datum can be either a mimic of a Condition, in which case it will be signalled directly, or it can be a mimic of a Condition with arguments, in which case it will first be mimicked and the arguments assigned in some way. finally, if the argument is a Text, a mimic of Condition Default will be signalled, with the provided text.", new NativeMethod("signal!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("datum") .WithKeywordRest("conditionArguments") .Arguments, (method, context, message, on, outer) => { IList positionalArgs = new SaneArrayList(); IDictionary <string, object> keywordArgs = new SaneDictionary <string, object>(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, positionalArgs, keywordArgs); object datum = positionalArgs[0]; return(Signal(datum, positionalArgs, keywordArgs, message, context)); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes the same kind of arguments as 'signal!', and will signal a condition. the default condition used is Condition Error Default. if no rescue or restart is invoked error! will report the condition to System err and exit the currently running Ioke VM. this might be a problem when exceptions happen inside of running Java code, as callbacks and so on.. if 'System currentDebugger' is non-nil, it will be invoked before the exiting of the VM. the exit can only be avoided by invoking a restart. that means that error! will never return. ", new NativeMethod("error!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("datum") .WithKeywordRest("errorArguments") .Arguments, (method, context, message, on, outer) => { IList positionalArgs = new SaneArrayList(); IDictionary <string, object> keywordArgs = new SaneDictionary <string, object>(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, positionalArgs, keywordArgs); object datum = positionalArgs[0]; if (IokeObject.dataOf(datum) is Text) { object oldDatum = datum; datum = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Default"), context).Mimic(message, context); IokeObject.SetCell(datum, message, context, "text", oldDatum); } IokeObject condition = Signal(datum, positionalArgs, keywordArgs, message, context); IokeObject err = IokeObject.As(context.runtime.System.GetCell(message, context, "err"), context); Interpreter.Send(context.runtime.printMessage, context, err, context.runtime.NewText("*** - ")); Interpreter.Send(context.runtime.printlnMessage, context, err, Interpreter.Send(context.runtime.reportMessage, context, condition)); IokeObject currentDebugger = IokeObject.As(Interpreter.Send(context.runtime.currentDebuggerMessage, context, context.runtime.System), context); if (!currentDebugger.IsNil) { Interpreter.Send(context.runtime.invokeMessage, context, currentDebugger, condition, context); } throw new ControlFlow.Exit(condition); }))); }
public static void Init(IokeObject obj) { obj.Kind = "Base"; obj.RegisterMethod(obj.runtime.NewNativeMethod("expects two or more arguments, the first arguments unevaluated, the last evaluated. assigns the result of evaluating the last argument in the context of the caller, and assigns this result to the name/s provided by the first arguments. the first arguments remains unevaluated. the result of the assignment is the value assigned to the name. if the last argument is a method-like object and it's name is not set, that name will be set to the name of the cell.", new NativeMethod("=", DefaultArgumentsDefinition.builder() .WithRequiredPositionalUnevaluated("place") .WithRestUnevaluated("morePlacesForDestructuring") .WithRequiredPositional("value") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); var args = message.Arguments; if (args.Count == 2) { IokeObject m1 = IokeObject.As(Message.GetArguments(message)[0], context); string name = m1.Name; if (m1.Arguments.Count == 0) { object value = Interpreter.GetEvaluatedArgument(message, 1, context); IokeObject.Assign(on, name, value, context, message); if (value is IokeObject) { if ((IokeObject.dataOf(value) is Named) && ((Named)IokeObject.dataOf(value)).Name == null) { ((Named)IokeObject.dataOf(value)).Name = name; } else if (name.Length > 0 && char.IsUpper(name[0]) && !(IokeObject.As(value, context).HasKind)) { if (on == context.runtime.Ground || on == context.runtime.IokeGround) { IokeObject.As(value, context).Kind = name; } else { IokeObject.As(value, context).Kind = IokeObject.As(on, context).GetKind(message, context) + " " + name; } } } return(value); } else { string newName = name + "="; IList arguments = new SaneArrayList(m1.Arguments); arguments.Add(Message.GetArguments(message)[1]); IokeObject msg = context.runtime.NewMessageFrom(message, newName, arguments); return(Interpreter.Send(msg, context, on)); } } else { int lastIndex = args.Count - 1; int numPlaces = lastIndex; return(RecursiveDestructuring(args, numPlaces, message, context, on, Interpreter.GetEvaluatedArgument(args[lastIndex], context))); } }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("will return a new derivation of the receiving object. Might throw exceptions if the object is an oddball object.", new NativeMethod.WithNoArguments("mimic", (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); return(IokeObject.As(on, context).Mimic(message, context)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument that names the cell to set, sets this cell to the result of evaluating the second argument, and returns the value set.", new NativeMethod("cell=", DefaultArgumentsDefinition .builder() .WithRequiredPositional("cellName") .WithRequiredPositional("value") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(AssignCell(context, message, on, args[0], args[1])); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns the cell that matches that name, without activating even if it's activatable.", new NativeMethod("cell", DefaultArgumentsDefinition.builder() .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0])); return(IokeObject.GetCell(on, message, context, name)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a hash for the object", new NativeMethod.WithNoArguments("hash", (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); return(context.runtime.NewNumber(System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(IokeObject.As(on, context).body))); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns true if the left hand side is equal to the right hand side. exactly what this means depend on the object. the default behavior of Ioke objects is to only be equal if they are the same instance.", new NativeMethod("==", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, context, message, on, outer) => { IList args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return((IokeObject.As(on, context).body == IokeObject.As(args[0], context).body) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns a boolean indicating whether such a cell is reachable from this point.", new NativeMethod("cell?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { IList args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0])); return(IokeObject.FindCell((IokeObject)on, name) != context.runtime.nul ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the documentation text of the object called on. anything can have a documentation text - this text will initially be nil.", new NativeMethod.WithNoArguments("documentation", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(Documentation(context, message, on)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a boolean indicating of this object should be activated or not.", new NativeMethod.WithNoArguments("activatable", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(IokeObject.As(on, context).IsActivatable ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("sets the activatable flag for a specific object. this will not impact objects that mimic this object..", new TypeCheckingNativeMethod("activatable=", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("activatableFlag") .Arguments, (method, on, args, keywords, context, message) => { IokeObject.As(on, context).SetActivatable(IokeObject.IsObjectTrue(args[0])); return(args[0]); } ))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns this object", new NativeMethod.WithNoArguments("identity", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(on); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("sets the documentation string for a specific object.", new TypeCheckingNativeMethod("documentation=", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("text").WhichMustMimic(obj.runtime.Text).OrBeNil() .Arguments, (method, on, args, keywords, context, message) => { return(SetDocumentation(context, message, on, args[0])); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns a boolean indicating whether this cell is owned by the receiver or not. the assumption is that the cell should exist. if it doesn't exist, a NoSuchCell condition will be signalled.", new NativeMethod("cellOwner?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0])); return((IokeObject.FindPlace(on, message, context, name) == on) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns the closest object that defines such a cell. if it doesn't exist, a NoSuchCell condition will be signalled.", new NativeMethod("cellOwner", DefaultArgumentsDefinition.builder() .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0])); object result = IokeObject.FindPlace(on, message, context, name); if (result == context.runtime.nul) { return(context.runtime.nil); } return(result); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and removes that cell from the current receiver. if the current receiver has no such object, signals a condition. note that if another cell with that name is available in the mimic chain, it will still be accessible after calling this method. the method returns the receiver.", new NativeMethod("removeCell!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0])); IokeObject.RemoveCell(on, message, context, name); return(on); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and makes that cell undefined in the current receiver. what that means is that from now on it will look like this cell doesn't exist in the receiver or any of its mimics. the cell will not show up if you call cellNames on the receiver or any of the receivers mimics. the undefined status can be removed by doing removeCell! on the correct cell name. a cell name that doesn't exist can still be undefined. the method returns the receiver.", new NativeMethod("undefineCell!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("cellName") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0])); IokeObject.UndefineCell(on, message, context, name); return(on); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("takes one optional evaluated boolean argument, which defaults to false. if false, this method returns a list of the cell names of the receiver. if true, it returns the cell names of this object and all it's mimics recursively.", new NativeMethod("cellNames", DefaultArgumentsDefinition.builder() .WithOptionalPositional("includeMimics", "false") .WithOptionalPositional("cutoff", "nil") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(CellNames(context, message, on, args.Count > 0 && IokeObject.IsObjectTrue(args[0]), (args.Count > 1) ? args[1] : null)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("takes one optional evaluated boolean argument, which defaults to false. if false, this method returns a dict of the cell names and values of the receiver. if true, it returns the cell names and values of this object and all it's mimics recursively.", new NativeMethod("cells", DefaultArgumentsDefinition.builder() .WithOptionalPositional("includeMimics", "false") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(Cells(context, message, on, args.Count > 0 && IokeObject.IsObjectTrue(args[0]))); }))); }
public override void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "Regexp"; IokeObject regexpMatch = new IokeObject(runtime, "contains behavior related to assignment", new RegexpMatch(obj, null, null)); regexpMatch.MimicsWithoutCheck(runtime.Origin); regexpMatch.Init(); obj.RegisterCell("Match", regexpMatch); obj.RegisterMethod(runtime.NewNativeMethod("returns a hash for the regexp", new NativeMethod.WithNoArguments("hash", (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); Regexp r = (Regexp)IokeObject.dataOf(on); return(context.runtime.NewNumber(r.pattern.GetHashCode() + 13 * r.flags.GetHashCode())); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the left hand side pattern is equal to the right hand side pattern.", new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(runtime.Regexp) .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { Regexp d = (Regexp)IokeObject.dataOf(on); object other = args[0]; return(((other is IokeObject) && (IokeObject.dataOf(other) is Regexp) && ((on == context.runtime.Regexp || other == context.runtime.Regexp) ? on == other : (d.pattern.Equals(((Regexp)IokeObject.dataOf(other)).pattern) && d.flags.Equals(((Regexp)IokeObject.dataOf(other)).flags)))) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns the pattern use for this regular expression", new TypeCheckingNativeMethod.WithNoArguments("pattern", obj, (method, on, args, keywords, context, message) => { return(context.runtime.NewText(GetPattern(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one argument and tries to match that argument against the current pattern. Returns nil if no match can be done, or a Regexp Match object if a match succeeds", new TypeCheckingNativeMethod("match", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { IokeObject target = IokeObject.As(Interpreter.Send(context.runtime.asText, context, args[0]), context); string arg = Text.GetText(target); Matcher m = ((Regexp)IokeObject.dataOf(on)).regexp.Matcher(arg); if (m.Find()) { IokeObject match = regexpMatch.AllocateCopy(message, context); match.MimicsWithoutCheck(regexpMatch); match.Data = new RegexpMatch(IokeObject.As(on, context), m, target); return(match); } else { return(context.runtime.nil); } }))); obj.AliasMethod("match", "=~", null, null); obj.RegisterMethod(runtime.NewNativeMethod("Takes one argument that should be a text and returns a text that has all regexp meta characters quoted", new NativeMethod("quote", DefaultArgumentsDefinition.builder() .WithRequiredPositional("text") .Arguments, (method, on, args, keywords, context, message) => { return(context.runtime.NewText(Pattern.Quote(Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0]))))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one or two text arguments that describes the regular expression to create. the first text is the pattern and the second is the flags.", new NativeMethod("from", DefaultArgumentsDefinition.builder() .WithRequiredPositional("pattern") .WithOptionalPositional("flags", "") .Arguments, (method, on, args, keywords, context, message) => { string pattern = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0])); string flags = ""; if (args.Count > 1) { flags = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1])); } return(context.runtime.NewRegexp(pattern, flags, context, message)); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one argument and tries to match that argument against the current pattern. Returns a list of all the texts that were matched.", new TypeCheckingNativeMethod("allMatches", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { string arg = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0])); Matcher m = ((Regexp)IokeObject.dataOf(on)).regexp.Matcher(arg); var result = new SaneArrayList(); MatchIterator iter = m.FindAll(); while (iter.HasMore) { result.Add(runtime.NewText(iter.NextMatch.Group(0))); } return(runtime.NewList(result)); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("inspect", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewText(Regexp.GetInspect(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a brief text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("notice", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewText(Regexp.GetNotice(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a list of all the named groups in this regular expression", new TypeCheckingNativeMethod.WithNoArguments("names", obj, (method, on, args, keywords, context, message) => { var names = Regexp.GetRegexp(on).GroupNames; var theNames = new SaneArrayList(); foreach (object name in names) { theNames.Add(context.runtime.GetSymbol(((string)name))); } return(context.runtime.NewList(theNames)); }))); }
public static void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "DefaultBehavior Internal"; obj.RegisterMethod(runtime.NewNativeMethod("expects one 'strange' argument. creates a new instance of Text with the given Java String backing it.", new NativeMethod("internal:createText", DefaultArgumentsDefinition .builder() .WithRequiredPositionalUnevaluated("text") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); object o = Message.GetArguments(message)[0]; bool cache = true; if (o is IokeObject) { cache = false; o = Interpreter.GetEvaluatedArgument(o, context); } if (o is string) { string s = (string)o; object value = runtime.NewText(new StringUtils().ReplaceEscapes(s)); if (cache) { Message.CacheValue(message, value); } return(value); } else { return(IokeObject.ConvertToText(o, message, context, true)); } }))); obj.RegisterMethod(runtime.NewNativeMethod("expects one 'strange' argument. creates a new instance of Number that represents the number found in the strange argument.", new NativeMethod("internal:createNumber", DefaultArgumentsDefinition .builder() .WithRequiredPositionalUnevaluated("number") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); object o = Message.GetArguments(message)[0]; bool cache = true; if (o is IokeObject) { cache = false; o = Interpreter.GetEvaluatedArgument(o, context); } object value = null; if (o is string) { value = runtime.NewNumber((string)o); } else if (o is int) { value = runtime.NewNumber((int)o); } if (cache) { Message.CacheValue(message, value); } return(value); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes zero or more arguments, calls asText on non-text arguments, and then concatenates them and returns the result.", new NativeMethod("internal:concatenateText", DefaultArgumentsDefinition.builder() .WithRest("textSegments") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); StringBuilder sb = new StringBuilder(); foreach (object o in args) { if (o is IokeObject) { if (IokeObject.dataOf(o) is Text) { sb.Append(Text.GetText(o)); } else { var aa = Interpreter.Send(context.runtime.asText, context, o); sb.Append(Text.GetText(aa)); } } else { sb.Append(o); } } return(context.runtime.NewText(sb.ToString())); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes one or more arguments. it expects the last argument to be a text of flags, while the rest of the arguments are either texts or regexps or nil. if text, it will be inserted verbatim into the result regexp. if regexp it will be inserted into a group that make sure the flags of the regexp is preserved. if nil, nothing will be inserted.", new NativeMethod("internal:compositeRegexp", DefaultArgumentsDefinition.builder() .WithRest("regexpSegments") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); StringBuilder sb = new StringBuilder(); if ((IokeObject.dataOf(on) is Text) || (IokeObject.dataOf(on) is Regexp)) { AddObject(on, sb, context); } int size = args.Count; foreach (object o in ArrayList.Adapter(args).GetRange(0, size - 1)) { AddObject(o, sb, context); } object f = args[size - 1]; string flags = null; if (f is string) { flags = (string)f; } else if (IokeObject.dataOf(f) is Text) { flags = Text.GetText(f); } else if (IokeObject.dataOf(f) is Regexp) { sb.Append(Regexp.GetPattern(f)); flags = Regexp.GetFlags(f); } return(context.runtime.NewRegexp(sb.ToString(), flags, context, message)); }))); obj.RegisterMethod(runtime.NewNativeMethod("expects two 'strange' arguments. creates a new mimic of Regexp with the given Java String backing it.", new NativeMethod("internal:createRegexp", DefaultArgumentsDefinition.builder() .WithRequiredPositionalUnevaluated("regexp") .WithRequiredPositionalUnevaluated("flags") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); object o = Message.GetArguments(message)[0]; object o2 = Message.GetArguments(message)[1]; if (o is IokeObject) { o = Interpreter.GetEvaluatedArgument(o, context); } if (o2 is IokeObject) { o2 = Interpreter.GetEvaluatedArgument(o2, context); } if (o is string) { string s = (string)o; return(runtime.NewRegexp(new StringUtils().ReplaceRegexpEscapes(s), (string)o2, context, message)); } else { return(IokeObject.ConvertToRegexp(o, message, context)); } }))); obj.RegisterMethod(runtime.NewNativeMethod("expects one 'strange' argument. creates a new instance of Decimal that represents the number found in the strange argument.", new NativeMethod("internal:createDecimal", DefaultArgumentsDefinition.builder() .WithRequiredPositionalUnevaluated("decimal") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); object o = Message.GetArguments(message)[0]; bool cache = true; if (o is IokeObject) { cache = false; o = Interpreter.GetEvaluatedArgument(o, context); } object value = runtime.NewDecimal((string)o); if (cache) { Message.CacheValue(message, value); } return(value); }))); }
public override void Init(IokeObject obj) { obj.Kind = "DefaultMacro"; obj.SetActivatable(true); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the name of the macro", new TypeCheckingNativeMethod.WithNoArguments("name", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(((DefaultMacro)IokeObject.dataOf(on)).name)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("activates this macro with the arguments given to call", new NativeMethod("call", DefaultArgumentsDefinition.builder() .WithRestUnevaluated("arguments") .Arguments, (method, _context, message, on, outer) => { return(Interpreter.Activate(IokeObject.As(on, _context), _context, message, _context.RealContext)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the message chain for this macro", new TypeCheckingNativeMethod.WithNoArguments("message", obj, (method, on, args, keywords, _context, message) => { return(((DefaultMacro)IokeObject.dataOf(on)).Code); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the code for the argument definition", new TypeCheckingNativeMethod.WithNoArguments("argumentsCode", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).ArgumentsCode)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("inspect", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(DefaultMacro.GetInspect(on))); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a brief text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("notice", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(DefaultMacro.GetNotice(on))); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the full code of this macro, as a Text", new TypeCheckingNativeMethod.WithNoArguments("code", obj, (method, on, args, keywords, _context, message) => { IokeData data = IokeObject.dataOf(on); if (data is DefaultMacro) { return(_context.runtime.NewText(((DefaultMacro)data).CodeString)); } else { return(_context.runtime.NewText(((AliasMethod)data).CodeString)); } }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns idiomatically formatted code for this macro", new TypeCheckingNativeMethod.WithNoArguments("formattedCode", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).FormattedCode(method))); }))); }
public static void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "DefaultBehavior Reflection"; obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and returns either true or false if this object or one of it's mimics mimics that argument", new NativeMethod("mimics?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("potentialMimic") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject arg = IokeObject.As(args[0], context); if (IokeObject.IsMimic(on, arg, context)) { return(context.runtime.True); } else { return(context.runtime.False); } }))); obj.RegisterMethod(runtime.NewNativeMethod("modifies the receiver to be in all ways identical to the argument. if the receiver is nil, true or false, this method can't be used - but those are the only exceptions. it's generally not recommended to use it on kinds and objects that are important for the Ioke runtime, since the result might be highly unpredictable.", new NativeMethod("become!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("objectToBecome") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject me = IokeObject.As(on, context); IokeObject other = IokeObject.As(args[0], context); if (on == context.runtime.nil || on == context.runtime.True || on == context.runtime.False) { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition, message, context, "Error", "CantMimicOddball"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); context.runtime.ErrorCondition(condition); } me.Become(other, message, context); return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a text hex representation of the receiver in upper case hex literal, starting with 0x. This value is based on System.identityHashCode, and as such is not totally guaranteed to be totally unique. but almost.", new NativeMethod.WithNoArguments("uniqueHexId", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(context.runtime.NewText("0x" + System.Convert.ToString(System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(IokeObject.As(on, context).body), 16).ToUpper())); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a textual representation of the object called on.", new NativeMethod.WithNoArguments("asText", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(method.runtime.NewText(on.ToString())); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the evaluated argument is the same reference as the receiver, false otherwise.", new NativeMethod("same?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(IokeObject.Same(on, args[0]) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes the name of a message to send, and the arguments to give it. send should generally behave exactly as if you had sent the message itself - except that you can give a variable containing the name.", new NativeMethod("send", DefaultArgumentsDefinition.builder() .WithRequiredPositional("messageName") .WithRestUnevaluated("arguments") .WithKeywordRestUnevaluated("keywordArguments") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); object _name = Interpreter.GetEvaluatedArgument(message, 0, context); string name = Text.GetText(Interpreter.Send(runtime.asText, context, _name)); IokeObject newMessage = Message.DeepCopy(message); newMessage.Arguments.RemoveAt(0); Message.SetName(newMessage, name); return(Interpreter.Send(newMessage, context, on)); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns false if the left hand side is equal to the right hand side. exactly what this means depend on the object. the default behavior of Ioke objects is to only be equal if they are the same instance.", new NativeMethod("!=", DefaultArgumentsDefinition.builder() .WithRequiredPositional("other") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); return(!IokeObject.Equals(on, Interpreter.GetEvaluatedArgument(message, 0, context)) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated Text argument and returns either true or false if this object or one of it's mimics have the kind of the name specified", new TypeCheckingNativeMethod("kind?", TypeCheckingArgumentsDefinition.builder() .WithRequiredPositional("name").WhichMustMimic(runtime.Text) .Arguments, (method, on, args, keywords, context, message) => { string kind = Text.GetText(args[0]); return(IokeObject.IsKind(on, kind, context) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and returns either true or false if this object or one of it's mimics mimics that argument. exactly the same as 'mimics?'", new NativeMethod("is?", DefaultArgumentsDefinition.builder() .WithRequiredPositional("potentialMimic") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject arg = IokeObject.As(args[0], context); return(IokeObject.IsMimic(on, arg, context) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a list of all the mimics of the receiver. it will not be the same list as is used to back the object, so modifications to this list will not show up in the object.", new NativeMethod.WithNoArguments("mimics", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); var l = new SaneArrayList(); foreach (object x in IokeObject.GetMimics(on, context)) { l.Add(x); } return(context.runtime.NewList(l)); }))); obj.RegisterMethod(runtime.NewNativeMethod("removes all mimics on the receiver, and returns the receiver", new NativeMethod.WithNoArguments("removeAllMimics!", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); IokeObject.RemoveAllMimics(on, message, context); return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("removes the argument mimic from the list of all mimics on the receiver. will do nothing if the receiver has no such mimic. it returns the receiver", new NativeMethod("removeMimic!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("mimicToRemove") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject.RemoveMimic(on, args[0], message, context); return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and adds it to the list of mimics for the receiver. the receiver will be returned.", new NativeMethod("mimic!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("newMimic") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject newMimic = IokeObject.As(args[0], context); IokeObject.As(on, context).Mimics(newMimic, message, context); return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and prepends it to the list of mimics for the receiver. the receiver will be returned.", new NativeMethod("prependMimic!", DefaultArgumentsDefinition.builder() .WithRequiredPositional("newMimic") .Arguments, (method, context, message, on, outer) => { var args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); IokeObject newMimic = IokeObject.As(args[0], context); IokeObject.As(on, context).Mimics(0, newMimic, message, context); return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the receiver is frozen, otherwise false", new NativeMethod.WithNoArguments("frozen?", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); return(IokeObject.As(on, context).IsFrozen ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("ensures that the receiver is frozen", new NativeMethod.WithNoArguments("freeze!", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); IokeObject.Freeze(on); return(on); }))); obj.RegisterMethod(runtime.NewNativeMethod("ensures that the receiver is not frozen", new NativeMethod.WithNoArguments("thaw!", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); IokeObject.Thaw(on); return(on); }))); }
public static void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "DefaultBehavior FlowControl"; obj.RegisterMethod(runtime.NewNativeMethod("evaluates the first arguments, and then evaluates the second argument if the result was true, otherwise the last argument. returns the result of the call, or the result if it's not true.", new NativeMethod("if", DefaultArgumentsDefinition.builder() .WithRequiredPositional("condition") .WithOptionalPositionalUnevaluated("then") .WithOptionalPositionalUnevaluated("else") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); object test = Interpreter.GetEvaluatedArgument(message, 0, context); IokeObject itContext = context.runtime.NewLexicalContext(context.RealContext, "Lexical activation context", context); itContext.SetCell("it", test); if (IokeObject.IsObjectTrue(test)) { if (message.Arguments.Count > 1) { return(Interpreter.GetEvaluatedArgument(message, 1, itContext)); } else { return(test); } } else { if (message.Arguments.Count > 2) { return(Interpreter.GetEvaluatedArgument(message, 2, itContext)); } else { return(test); } } }))); obj.RegisterMethod(runtime.NewNativeMethod("evaluates the first arguments, and then evaluates the second argument if the result was false, otherwise the last argument. returns the result of the call, or the result if it's true.", new NativeMethod("unless", DefaultArgumentsDefinition.builder() .WithRequiredPositional("condition") .WithOptionalPositionalUnevaluated("then") .WithOptionalPositionalUnevaluated("else") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); object test = Interpreter.GetEvaluatedArgument(message, 0, context); IokeObject itContext = context.runtime.NewLexicalContext(context.RealContext, "Lexical activation context", context); itContext.SetCell("it", test); if (IokeObject.IsObjectTrue(test)) { if (message.Arguments.Count > 2) { return(Interpreter.GetEvaluatedArgument(message, 2, itContext)); } else { return(test); } } else { if (message.Arguments.Count > 1) { return(Interpreter.GetEvaluatedArgument(message, 1, itContext)); } else { return(test); } } }))); obj.RegisterMethod(runtime.NewNativeMethod("takes zero or more place and value pairs and one code argument, establishes a new lexical scope and binds the places to the values given. if the place is a simple name, it will just be created as a new binding in the lexical scope. if it is a place specification, that place will be temporarily changed - but guaranteed to be changed back after the lexical scope is finished. the let-form returns the final result of the code argument.", new NativeMethod("let", DefaultArgumentsDefinition.builder() .WithRestUnevaluated("placesAndValues") .WithRequiredPositionalUnevaluated("code") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); var args = message.Arguments; IokeObject lc = context.runtime.NewLexicalContext(context.RealContext, "Let lexical activation context", context); int ix = 0; int end = args.Count - 1; var valuesToUnbind = new LinkedList <object[]>(); try { while (ix < end) { IokeObject place = IokeObject.As(args[ix++], context); if (Message.GetNext(place) == null && place.Arguments.Count == 0) { object value = Interpreter.GetEvaluatedArgument(message, ix++, context); lc.SetCell(Message.GetName(place), value); } else { place = Message.DeepCopy(place); IokeObject realPlace = place; while (Message.GetNext(realPlace) != null) { if (Message.GetNext(Message.GetNext(realPlace)) == null) { IokeObject temp = Message.GetNext(realPlace); Message.SetNext(realPlace, null); realPlace = temp; } else { realPlace = Message.GetNext(realPlace); } } object wherePlace = context.RealContext; if (place != realPlace) { wherePlace = Interpreter.GetEvaluatedArgument(place, context); } object originalValue = runtime.WithReturningRescue(context, null, () => { return(Interpreter.Send(realPlace, context, wherePlace)); }); if (realPlace.Arguments.Count != 0) { string newName = realPlace.Name + "="; var arguments = new SaneArrayList(realPlace.Arguments); arguments.Add(args[ix++]); IokeObject msg = context.runtime.NewMessageFrom(realPlace, newName, arguments); Interpreter.Send(msg, context, wherePlace); valuesToUnbind.AddFirst(new object[] { wherePlace, originalValue, realPlace }); } else { object value = Interpreter.GetEvaluatedArgument(message, ix++, context); IokeObject.Assign(wherePlace, realPlace.Name, value, context, message); valuesToUnbind.AddFirst(new object[] { wherePlace, originalValue, realPlace }); } } } return(Interpreter.GetEvaluatedArgument(message, end, lc)); } finally { while (valuesToUnbind.Count > 0) { try { object[] vals = valuesToUnbind.First.Value; valuesToUnbind.RemoveFirst(); IokeObject wherePlace = IokeObject.As(vals[0], context); object value = vals[1]; IokeObject realPlace = IokeObject.As(vals[2], context); if (realPlace.Arguments.Count != 0) { string newName = realPlace.Name + "="; var arguments = new SaneArrayList(realPlace.Arguments); if (value == null) { if (newName.Equals("cell=")) { Interpreter.Send(context.runtime.removeCellMessage, context, wherePlace, new SaneArrayList(realPlace.Arguments)); } else { arguments.Add(context.runtime.CreateMessage(Message.Wrap(context.runtime.nil))); IokeObject msg = context.runtime.NewMessageFrom(realPlace, newName, arguments); Interpreter.Send(msg, context, wherePlace); } } else { arguments.Add(context.runtime.CreateMessage(Message.Wrap(IokeObject.As(value, context)))); IokeObject msg = context.runtime.NewMessageFrom(realPlace, newName, arguments); Interpreter.Send(msg, context, wherePlace); } } else { if (value == null) { IokeObject.RemoveCell(wherePlace, context, message, realPlace.Name); } else { IokeObject.Assign(wherePlace, realPlace.Name, value, context, message); } } } catch (System.Exception) {} } } }))); obj.RegisterMethod(runtime.NewNativeMethod("breaks out of the enclosing context. if an argument is supplied, this will be returned as the result of the object breaking out of", new NativeMethod("break", DefaultArgumentsDefinition.builder() .WithOptionalPositional("value", "nil") .Arguments, (method, context, message, on, outer) => { IList args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); object value = runtime.nil; if (message.Arguments.Count > 0) { value = Interpreter.GetEvaluatedArgument(message, 0, context); } throw new ControlFlow.Break(value); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns from the enclosing method/macro. if an argument is supplied, this will be returned as the result of the method/macro breaking out of.", new NativeMethod("return", DefaultArgumentsDefinition.builder() .WithOptionalPositional("value", "nil") .Arguments, (method, context, message, on, outer) => { object value = runtime.nil; IList args = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>()); if (args.Count > 0) { value = args[0]; } IokeObject ctx = context; while (ctx.data is LexicalContext) { ctx = ((LexicalContext)ctx.data).surroundingContext; } throw new ControlFlow.Return(value, ctx); }))); obj.RegisterMethod(runtime.NewNativeMethod("breaks out of the enclosing context and continues from that point again.", new NativeMethod.WithNoArguments("continue", (method, context, message, on, outer) => { outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>()); throw new ControlFlow.Continue(); }))); obj.RegisterMethod(runtime.NewNativeMethod("until the first argument evaluates to something true, loops and evaluates the next argument", new NativeMethod("until", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("condition") .WithRestUnevaluated("body") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); if (message.Arguments.Count == 0) { return(runtime.nil); } bool body = message.Arguments.Count > 1; object ret = runtime.nil; bool doAgain = false; do { doAgain = false; try { while (!IokeObject.IsObjectTrue(Interpreter.GetEvaluatedArgument(message, 0, context))) { if (body) { ret = Interpreter.GetEvaluatedArgument(message, 1, context); } } } catch (ControlFlow.Break e) { ret = e.Value; } catch (ControlFlow.Continue) { doAgain = true; } } while(doAgain); return(ret); }))); obj.RegisterMethod(runtime.NewNativeMethod("while the first argument evaluates to something true, loops and evaluates the next argument", new NativeMethod("while", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("condition") .WithRestUnevaluated("body") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); if (message.Arguments.Count == 0) { return(runtime.nil); } bool body = message.Arguments.Count > 1; object ret = runtime.nil; bool doAgain = false; do { doAgain = false; try { while (IokeObject.IsObjectTrue(Interpreter.GetEvaluatedArgument(message, 0, context))) { if (body) { ret = Interpreter.GetEvaluatedArgument(message, 1, context); } } } catch (ControlFlow.Break e) { ret = e.Value; } catch (ControlFlow.Continue) { doAgain = true; } } while(doAgain); return(ret); }))); obj.RegisterMethod(runtime.NewNativeMethod("loops forever - executing it's argument over and over until interrupted in some way.", new NativeMethod("loop", DefaultArgumentsDefinition.builder() .WithRestUnevaluated("body") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); if (message.Arguments.Count > 0) { while (true) { try { while (true) { Interpreter.GetEvaluatedArgument(message, 0, context); } } catch (ControlFlow.Break e) { return(e.Value); } catch (ControlFlow.Continue) { } } } else { while (true) { } } }))); obj.RegisterMethod(runtime.NewNativeMethod("will execute and return the value of the first argument. after the code has run, all the remaining blocks of code are guaranteed to run in order even if a non-local flow control happens inside the main code. if any code in the ensure blocks generate a new non-local flow control, the rest of the ensure blocks in that specific ensure invocation are not guaranteed to run.", new NativeMethod("ensure", DefaultArgumentsDefinition.builder() .WithRequiredPositionalUnevaluated("code") .WithRestUnevaluated("ensureBlocks") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); var args = message.Arguments; int argCount = args.Count; object result = runtime.nil; try { IokeObject msg = IokeObject.As(args[0], context); result = context.runtime.interpreter.Evaluate(msg, context, context.RealContext, context); } finally { foreach (object o in ArrayList.Adapter(args).GetRange(1, argCount - 1)) { IokeObject msg = IokeObject.As(o, context); context.runtime.interpreter.Evaluate(msg, context, context.RealContext, context); } } return(result); }))); }
public override void Init(IokeObject obj) { obj.Kind = "DefaultSyntax"; obj.SetActivatable(true); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the name of the syntax", new TypeCheckingNativeMethod.WithNoArguments("name", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(((DefaultSyntax)IokeObject.dataOf(on)).name)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("activates this syntax with the arguments given to call", new NativeMethod("call", DefaultArgumentsDefinition.builder() .WithRestUnevaluated("arguments") .Arguments, (method, _context, message, on, outer) => { return(Interpreter.Activate(IokeObject.As(on, _context), _context, message, _context.RealContext)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the result of activating this syntax without actually doing the replacement or execution part.", new NativeMethod("expand", DefaultArgumentsDefinition.builder() .WithRestUnevaluated("arguments") .Arguments, (method, _context, message, on, outer) => { object onAsSyntax = _context.runtime.DefaultSyntax.ConvertToThis(on, message, _context); return(((DefaultSyntax)IokeObject.dataOf(onAsSyntax)).Expand(IokeObject.As(onAsSyntax, context), context, message, context.RealContext, null)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the message chain for this syntax", new TypeCheckingNativeMethod.WithNoArguments("message", obj, (method, on, args, keywords, _context, message) => { return(((AssociatedCode)IokeObject.dataOf(on)).Code); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the code for the argument definition", new TypeCheckingNativeMethod.WithNoArguments("argumentsCode", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).ArgumentsCode)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("inspect", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(DefaultSyntax.GetInspect(on))); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a brief text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("notice", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(DefaultSyntax.GetNotice(on))); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the full code of this syntax, as a Text", new TypeCheckingNativeMethod.WithNoArguments("code", obj, (method, on, args, keywords, _context, message) => { IokeData data = IokeObject.dataOf(on); if (data is DefaultSyntax) { return(_context.runtime.NewText(((DefaultSyntax)data).CodeString)); } else { return(_context.runtime.NewText(((AliasMethod)data).CodeString)); } }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns idiomatically formatted code for this syntax", new TypeCheckingNativeMethod.WithNoArguments("formattedCode", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).FormattedCode(method))); }))); }
public override void Init(IokeObject obj) { obj.Kind = "LexicalBlock"; obj.RegisterMethod(obj.runtime.NewNativeMethod("takes two evaluated arguments, where this first one is a list of messages which will be used as the arguments and the code, and the second is the context where this lexical scope should be created in", new NativeMethod("createFrom", DefaultArgumentsDefinition.builder() .WithRequiredPositional("messageList") .WithRequiredPositional("lexicalContext") .Arguments, (method, _context, _message, on, outer) => { Runtime runtime = _context.runtime; var positionalArgs = new SaneArrayList(); outer.ArgumentsDefinition.GetEvaluatedArguments(_context, _message, on, positionalArgs, new SaneDictionary <string, object>()); var args = IokeList.GetList(positionalArgs[0]); IokeObject ground = IokeObject.As(positionalArgs[1], _context); IokeObject code = IokeObject.As(args[args.Count - 1], _context); DefaultArgumentsDefinition def = DefaultArgumentsDefinition.CreateFrom(args, 0, args.Count - 1, _message, on, _context); return(runtime.NewLexicalBlock(null, runtime.LexicalBlock, new LexicalBlock(ground, def, code))); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("invokes the block with the arguments provided, returning the result of the last expression in the block", new NativeMethod("call", DefaultArgumentsDefinition.builder() .WithRestUnevaluated("arguments") .Arguments, (method, _context, _message, on, outer) => { return(Interpreter.Activate(IokeObject.As(on, _context), _context, _message, on)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the full code of this lexical block, as a Text", new TypeCheckingNativeMethod.WithNoArguments("code", obj, (method, on, args, keywords, _context, _message) => { IokeObject objx = IokeObject.As(on, _context); string x = objx.IsActivatable ? "x" : ""; string argstr = ((LexicalBlock)IokeObject.dataOf(on)).arguments.GetCode(); return(_context.runtime.NewText("fn" + x + "(" + argstr + Message.Code(((LexicalBlock)IokeObject.dataOf(on)).message) + ")")); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the code for the argument definition", new TypeCheckingNativeMethod.WithNoArguments("argumentsCode", obj, (method, on, args, keywords, _context, _message) => { return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).ArgumentsCode)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a list of the keywords this block takes", new TypeCheckingNativeMethod.WithNoArguments("keywords", obj, (method, on, args, keywords, _context, _message) => { var keywordList = new SaneArrayList(); foreach (string keyword in ((LexicalBlock)IokeObject.dataOf(on)).arguments.Keywords) { keywordList.Add(_context.runtime.GetSymbol(keyword.Substring(0, keyword.Length - 1))); } return(_context.runtime.NewList(keywordList)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a list of the argument names the positional arguments this block takes", new TypeCheckingNativeMethod.WithNoArguments("argumentNames", obj, (method, on, args, keywords, _context, _message) => { var names = new SaneArrayList(); foreach (var arg in ((LexicalBlock)IokeObject.dataOf(on)).arguments.Arguments) { if (!(arg is DefaultArgumentsDefinition.KeywordArgument)) { names.Add(_context.runtime.GetSymbol(arg.Name)); } } return(_context.runtime.NewList(names)); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the message chain for this block", new TypeCheckingNativeMethod.WithNoArguments("message", obj, (method, on, args, keywords, _context, _message) => { return(((AssociatedCode)IokeObject.dataOf(on)).Code); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("inspect", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(LexicalBlock.GetInspect(on))); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a brief text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("notice", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(LexicalBlock.GetNotice(on))); }))); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns idiomatically formatted code for this lexical block", new TypeCheckingNativeMethod.WithNoArguments("formattedCode", obj, (method, on, args, keywords, _context, message) => { return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).FormattedCode(method))); }))); }