Ejemplo n.º 1
0
 private static object TypeCheckingRawActivate(IokeObject self, IokeObject context, IokeObject message, object on, NativeMethod outer)
 {
     IList args = new SaneArrayList();
     IDictionary<string, object> keywords = new SaneDictionary<string, object>();
     object receiver = ((TypeCheckingArgumentsDefinition)outer.ArgumentsDefinition).GetValidatedArgumentsAndReceiver(context, message, on, args, keywords);
     return outer.argsActivator(self, receiver, args, keywords, context, message);
 }
Ejemplo n.º 2
0
 private static object ArgumentActivator(IokeObject self, IokeObject context, IokeObject message, object on, NativeMethod outer)
 {
     IList args = new SaneArrayList();
     IDictionary<string, object> keywords = new SaneDictionary<string, object>();
     outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, keywords);
     return outer.argsActivator(self, on, args, keywords, context, message);
 }
Ejemplo n.º 3
0
 public override IokeObject Invoke(IokeObject context, IList arguments)
 {
     IList result = new SaneArrayList();
     for(int i=0; i<repeat; i++) {
         result.Add(value);
     }
     return context.runtime.NewList(result);
 }
Ejemplo n.º 4
0
Archivo: Base.cs Proyecto: goking/ioke
        public static object CellNames(IokeObject context, IokeObject message, object on, bool includeMimics, object cutoff)
        {
            if(includeMimics) {
                var visited = IdentityHashTable.Create();
                var names = new SaneArrayList();
                var visitedNames = new SaneHashSet<object>();
                var undefined = new SaneHashSet<string>();
                Runtime runtime = context.runtime;
                var toVisit = new SaneArrayList();
                toVisit.Add(on);

                while(toVisit.Count > 0) {
                    IokeObject current = IokeObject.As(toVisit[0], context);
                    toVisit.RemoveAt(0);
                    if(!visited.Contains(current)) {
                        visited[current] = null;
                        if(cutoff != current) {
                            foreach(IokeObject o in current.GetMimics()) toVisit.Add(o);
                        }

                        Cell c = current.body.firstAdded;
                        while(c != null) {
                            string s = c.name;
                            if(!undefined.Contains(s)) {
                                if(c.value == runtime.nul) {
                                    undefined.Add(s);
                                } else {
                                    object x = runtime.GetSymbol(s);
                                    if(!visitedNames.Contains(x)) {
                                        visitedNames.Add(x);
                                        names.Add(x);
                                    }
                                }
                            }

                            c = c.orderedNext;
                        }
                    }
                }

                return runtime.NewList(names);
            } else {
                var names = new SaneArrayList();
                Runtime runtime = context.runtime;

                Cell c = IokeObject.As(on, context).body.firstAdded;
                while(c != null) {
                    string s = c.name;
                    if(c.value != runtime.nul) {
                        names.Add(runtime.GetSymbol(s));
                    }
                    c = c.orderedNext;
                }
                return runtime.NewList(names);
            }
        }
Ejemplo n.º 5
0
Archivo: Base.cs Proyecto: fronx/ioke
        public static object CellNames(IokeObject context, IokeObject message, object on, bool includeMimics, object cutoff)
        {
            if(includeMimics) {
                var visited = IdentityHashTable.Create();
                var names = new SaneArrayList();
                var visitedNames = new SaneHashSet<object>();
                var undefined = new SaneHashSet<string>();
                Runtime runtime = context.runtime;
                var toVisit = new SaneArrayList();
                toVisit.Add(on);

                while(toVisit.Count > 0) {
                    IokeObject current = IokeObject.As(toVisit[0], context);
                    toVisit.RemoveAt(0);
                    if(!visited.Contains(current)) {
                        visited[current] = null;
                        if(cutoff != current) {
                            foreach(IokeObject o in current.GetMimics()) toVisit.Add(o);
                        }

                        var mso = current.Cells;

                        foreach(string s in mso.Keys) {
                            if(!undefined.Contains(s)) {
                                if(mso[s] == runtime.nul) {
                                    undefined.Add(s);
                                } else {
                                    object x = runtime.GetSymbol(s);
                                    if(!visitedNames.Contains(x)) {
                                        visitedNames.Add(x);
                                        names.Add(x);
                                    }
                                }
                            }
                        }
                    }
                }

                return runtime.NewList(names);
            } else {
                var mso = IokeObject.As(on, context).Cells;
                var names = new SaneArrayList();
                Runtime runtime = context.runtime;

                foreach(string s in mso.Keys) {
                    if(mso[s] != runtime.nul) {
                        names.Add(runtime.GetSymbol(s));
                    }
                }

                return runtime.NewList(names);
            }
        }
Ejemplo n.º 6
0
        private void AssignArgumentValues(IokeObject locals, IokeObject context, IokeObject message, object on, IList argumentsWithoutKeywords, IDictionary<string, object> givenKeywords, int argCount)
        {
            Runtime runtime = context.runtime;

            var intersection = new SaneHashSet<string>(givenKeywords.Keys);
            foreach(string k in keywords) intersection.Remove(k);

            int ix = 0;
            for(int i=0, j=this.arguments.Count;i<j;i++) {
                Argument a = this.arguments[i];

                if(a is KeywordArgument) {
                    string nm = a.Name + ":";
                    object result = null;
                    if(givenKeywords.ContainsKey(nm)) {
                        object given = givenKeywords[nm];
                        result = given;
                        locals.SetCell(a.Name, result);
                    } else {
                        object defVal = ((KeywordArgument)a).DefaultValue;
                        if(!(defVal is string)) {
                            IokeObject m1 = IokeObject.As(defVal, context);
                            result = ((Message)IokeObject.dataOf(m1)).EvaluateCompleteWithoutExplicitReceiver(m1, locals, locals.RealContext);
                            locals.SetCell(a.Name, result);
                        }
                    }
                } else if((a is OptionalArgument) && ix>=argCount) {
                    object defVal = ((OptionalArgument)a).DefaultValue;
                    if(!(defVal is string)) {
                        IokeObject m2 = IokeObject.As(defVal, context);
                        locals.SetCell(a.Name, ((Message)IokeObject.dataOf(m2)).EvaluateCompleteWithoutExplicitReceiver(m2, locals, locals.RealContext));
                    }
                } else {
                    locals.SetCell(a.Name, argumentsWithoutKeywords[ix++]);
                }
            }

            if(krest != null) {
                var krests = new SaneHashtable();
                foreach(string s in intersection) {
                    object given = givenKeywords[s];
                    object result = given;
                    krests[runtime.GetSymbol(s.Substring(0, s.Length-1))] = result;
                }

                locals.SetCell(krest, runtime.NewDict(krests));
            }

            if(rest != null) {
                IList rests = new SaneArrayList();
                for(int j=argumentsWithoutKeywords.Count;ix<j;ix++) {
                    rests.Add(argumentsWithoutKeywords[ix]);
                }

                locals.SetCell(rest, runtime.NewList(rests));
            }
        }
Ejemplo n.º 7
0
        public int GetEvaluatedArguments(IokeObject context, IokeObject message, object on, IList argumentsWithoutKeywords, IDictionary<string, object> givenKeywords)
        {
            Runtime runtime = context.runtime;
            IList arguments = message.Arguments;
            int argCount = 0;

            foreach(object o in arguments) {
                if(Message.IsKeyword(o)) {
                    givenKeywords[IokeObject.As(o, context).Name] = Message.GetEvaluatedArgument(((Message)IokeObject.dataOf(o)).next, context);
                } else if(Message.HasName(o, "*") && IokeObject.As(o, context).Arguments.Count == 1) { // Splat
                    object result = Message.GetEvaluatedArgument(IokeObject.As(o, context).Arguments[0], context);
                    if(IokeObject.dataOf(result) is IokeList) {
                        IList elements = IokeList.GetList(result);
                        foreach(object ox in elements) argumentsWithoutKeywords.Add(ox);
                        argCount += elements.Count;
                    } else if(IokeObject.dataOf(result) is Dict) {
                        IDictionary keys = Dict.GetMap(result);
                        foreach(DictionaryEntry me in keys) {
                            givenKeywords[Text.GetText(IokeObject.ConvertToText(me.Key, message, context, true)) + ":"] = me.Value;
                        }
                    } else if(IokeObject.FindCell(result, message, context, "asTuple") != runtime.nul) {
                        object tupledValue = ((Message)IokeObject.dataOf(runtime.asTuple)).SendTo(runtime.asTuple, context, result);
                        object[] values = Tuple.GetElements(tupledValue);
                        foreach(object val in values) argumentsWithoutKeywords.Add(val);
                        argCount += values.Length;
                    } else {
                        IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                                     message,
                                                                                     context,
                                                                                     "Error",
                                                                                     "Invocation",
                                                                                     "NotSpreadable"), context).Mimic(message, context);
                        condition.SetCell("message", message);
                        condition.SetCell("context", context);
                        condition.SetCell("receiver", on);
                        condition.SetCell("given", result);

                        IList outp = IokeList.GetList(runtime.WithRestartReturningArguments(()=>{runtime.ErrorCondition(condition);},
                                                                                            context,
                                                                                            new Restart.DefaultValuesGivingRestart("ignoreArgument", runtime.nil, 0),
                                                                                            new Restart.DefaultValuesGivingRestart("takeArgumentAsIs", IokeObject.As(result, context), 1)
                                                                                            ));

                        foreach(object ox in outp) argumentsWithoutKeywords.Add(ox);
                        argCount += outp.Count;
                    }
                } else {
                    argumentsWithoutKeywords.Add(Message.GetEvaluatedArgument(o, context));
                    argCount++;
                }
            }

            while(argCount < min || (max != -1 && argCount > max)) {
                int finalArgCount = argCount;
                if(argCount < min) {
                    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(min-argCount));

                    IList newArguments = IokeList.GetList(runtime.WithRestartReturningArguments(()=>{runtime.ErrorCondition(condition);},
                                                                                                context,
                                                                                                new NewArgumentGivingRestart("provideExtraArguments"),
                                                                                                new Restart.DefaultValuesGivingRestart("substituteNilArguments", runtime.nil, min-argCount)));

                    foreach(object ox in newArguments) argumentsWithoutKeywords.Add(ox);
                    argCount += newArguments.Count;
                } else {
                    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(argumentsWithoutKeywords).GetRange(max, finalArgCount-max)));

                    runtime.WithReturningRestart("ignoreExtraArguments", context, ()=>{runtime.ErrorCondition(condition);});
                    argCount = max;
                }
            }

            var intersection = new SaneHashSet<string>(givenKeywords.Keys);
            foreach(string k in keywords) intersection.Remove(k);

            if(krest == null && intersection.Count > 0) {
                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);

                IList expected = new SaneArrayList();
                foreach(string s in keywords) {
                    expected.Add(runtime.NewText(s));
                }

                condition.SetCell("expected", runtime.NewList(expected));

                IList extra = new SaneArrayList();
                foreach(string s in intersection) {
                    extra.Add(runtime.NewText(s));
                }
                condition.SetCell("extra", runtime.NewList(extra));
                runtime.WithReturningRestart("ignoreExtraKeywords", context, ()=>{runtime.ErrorCondition(condition);});
            }

            return argCount;
        }
Ejemplo n.º 8
0
        public override void Init(IokeObject obj)
        {
            obj.Kind = "DefaultMethod";

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a list of the keywords this method takes",
                                                           new TypeCheckingNativeMethod.WithNoArguments("keywords", obj,
                                                                                                        (method, on, args, keywords, _context, message) => {
                                                                                                            var keywordList = new SaneArrayList();

                                                                                                            foreach(string keyword in ((DefaultMethod)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 the message chain for this method",
                                                           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 idiomatically formatted code for this method",
                                                           new TypeCheckingNativeMethod.WithNoArguments("formattedCode", obj,
                                                                                                        (method, on, args, keywords, _context, message) => {
                                                                                                            return _context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).FormattedCode(method));
                                                                                                        })));
        }
Ejemplo n.º 9
0
 private static IList Flatten(IList list)
 {
     var result = new SaneArrayList(list.Count*2);
     Flatten(list, result);
     return result;
 }
Ejemplo n.º 10
0
Archivo: Range.cs Proyecto: goking/ioke
        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));
                                                                                        })));
        }
Ejemplo n.º 11
0
        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;
                                                                        })));
        }
Ejemplo n.º 12
0
        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);
                                                                        })));
        }
Ejemplo n.º 13
0
        public bool Use(IokeObject self, IokeObject context, IokeObject message, string name)
        {
            Runtime runtime = context.runtime;
            Builtin b = context.runtime.GetBuiltin(name);
            if(b != null) {
                if(loaded.Contains(name)) {
                    return false;
                } else {
                    try {
                        b.Load(context.runtime, context, message);
                        loaded.Add(name);
                        return true;
                    } catch(Exception e) {
                        IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                                     message,
                                                                                     context,
                                                                                     "Error",
                                                                                     "Load"), context).Mimic(message, context);
                        condition.SetCell("message", message);
                        condition.SetCell("context", context);
                        condition.SetCell("receiver", self);
                        condition.SetCell("moduleName", runtime.NewText(name));
                        condition.SetCell("exceptionMessage", runtime.NewText(e.Message));
                        var st = new System.Diagnostics.StackTrace(e);
                        var ob = new SaneArrayList();
                        foreach(var frame in st.GetFrames()) {
                            ob.Add(runtime.NewText(frame.ToString()));
                        }
                        condition.SetCell("exceptionStackTrace", runtime.NewList(ob));

                        bool[] continueLoadChain = new bool[]{false};

                        runtime.WithRestartReturningArguments(()=>{runtime.ErrorCondition(condition);},
                                                              context,
                                                              new BooleanGivingRestart("continueLoadChain", continueLoadChain, true, runtime),
                                                              new BooleanGivingRestart("ignoreLoadError", continueLoadChain, false, runtime));
                        if(!continueLoadChain[0]) {
                            return false;
                        }
                    }
                }
            }

            var paths = ((IokeList)IokeObject.dataOf(loadPath)).List;

            string[] suffixes = (name.EndsWith(".ik")) ? SUFFIXES_WITH_BLANK : SUFFIXES;

            // Absolute path
            foreach(string suffix in suffixes) {
                string before = "/";
                if(name.StartsWith("/")) {
                    before = "";
                }

                try {
                    FileInfo f = new FileInfo(name + suffix);
                    if(f.Exists) {
                        if(loaded.Contains(f.FullName)) {
                            return false;
                        } else {
                            context.runtime.EvaluateFile(f, message, context);
                        }
                        loaded.Add(f.FullName);
                        return true;
                    }

                    string xname = (before + name + suffix).Replace("/", ".");
                    if(xname.StartsWith("."))
                        xname = xname.Substring(1);
                    Stream s = typeof(IokeSystem).Assembly.GetManifestResourceStream(xname);
                    if(s != null) {
                        if(loaded.Contains(name + suffix)) {
                            return false;
                        } else {
                            context.runtime.EvaluateStream(name+suffix, new StreamReader(s, System.Text.Encoding.UTF8), message, context);
                        }
                        loaded.Add(name + suffix);
                        return true;
                    }
                } catch(FileNotFoundException) {
                    // ignore
                } catch(Exception e) {
                    IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                                 message,
                                                                                 context,
                                                                                 "Error",
                                                                                 "Load"), context).Mimic(message, context);
                    condition.SetCell("message", message);
                    condition.SetCell("context", context);
                    condition.SetCell("receiver", self);
                    condition.SetCell("moduleName", runtime.NewText(name));
                    condition.SetCell("exceptionMessage", runtime.NewText(e.Message));
                    var st = new System.Diagnostics.StackTrace(e);
                    var ob = new SaneArrayList();
                    foreach(var frame in st.GetFrames()) {
                        ob.Add(runtime.NewText(frame.ToString()));
                    }
                    condition.SetCell("exceptionStackTrace", runtime.NewList(ob));

                    bool[] continueLoadChain = new bool[]{false};

                    runtime.WithRestartReturningArguments(()=>{runtime.ErrorCondition(condition);},
                                                          context,
                                                          new BooleanGivingRestart("continueLoadChain", continueLoadChain, true, runtime),
                                                          new BooleanGivingRestart("ignoreLoadError", continueLoadChain, false, runtime));
                    if(!continueLoadChain[0]) {
                        return false;
                    }
                }
            }

            foreach(object o in paths) {
                string currentS = Text.GetText(o);

                foreach(string suffix in suffixes) {
                    string before = "/";
                    if(name.StartsWith("/")) {
                        before = "";
                    }

                    try {
                        FileInfo f;

                        if(IsAbsoluteFileName(currentS)) {
                            f = new FileInfo(Path.Combine(currentS, name + suffix));
                        } else {
                            f = new FileInfo(Path.Combine(Path.Combine(currentWorkingDirectory, currentS), name + suffix));
                        }

                        if(f.Exists) {
                            if(loaded.Contains(f.FullName)) {
                                return false;
                            } else {
                                context.runtime.EvaluateFile(f, message, context);
                                loaded.Add(f.FullName);
                                return true;
                            }
                        }

                        string yname = (before + name + suffix).Replace("/", ".");
                        if(yname.StartsWith("."))
                            yname = yname.Substring(1);

                        Stream ss = typeof(IokeSystem).Assembly.GetManifestResourceStream(yname);
                        if(ss != null) {
                            if(loaded.Contains(name + suffix)) {
                                return false;
                            } else {
                                context.runtime.EvaluateStream(name+suffix, new StreamReader(ss, System.Text.Encoding.UTF8), message, context);
                            }
                            loaded.Add(name + suffix);
                            return true;
                        }
                    } catch(FileNotFoundException) {
                        // ignore
                    } catch(Exception e) {
                        IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                                     message,
                                                                                     context,
                                                                                     "Error",
                                                                                     "Load"), context).Mimic(message, context);
                        condition.SetCell("message", message);
                        condition.SetCell("context", context);
                        condition.SetCell("receiver", self);
                        condition.SetCell("moduleName", runtime.NewText(name));
                        condition.SetCell("exceptionMessage", runtime.NewText(e.Message));
                        var st = new System.Diagnostics.StackTrace(e);
                        var ob = new SaneArrayList();
                        foreach(var frame in st.GetFrames()) {
                            ob.Add(runtime.NewText(frame.ToString()));
                        }
                        condition.SetCell("exceptionStackTrace", runtime.NewList(ob));

                        bool[] continueLoadChain = new bool[]{false};

                        runtime.WithRestartReturningArguments(()=>{runtime.ErrorCondition(condition);},
                                                              context,
                                                              new BooleanGivingRestart("continueLoadChain", continueLoadChain, true, runtime),
                                                              new BooleanGivingRestart("ignoreLoadError", continueLoadChain, false, runtime));
                        if(!continueLoadChain[0]) {
                            return false;
                        }
                    }
                }
            }

            IokeObject condition2 = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                          message,
                                                                          context,
                                                                          "Error",
                                                                          "Load"), context).Mimic(message, context);
            condition2.SetCell("message", message);
            condition2.SetCell("context", context);
            condition2.SetCell("receiver", self);
            condition2.SetCell("moduleName", runtime.NewText(name));

            runtime.WithReturningRestart("ignoreLoadError", context, ()=>{runtime.ErrorCondition(condition2);});
            return false;
        }
Ejemplo n.º 14
0
Archivo: Hook.cs Proyecto: goking/ioke
        public static void Init(Runtime runtime)
        {
            IokeObject obj = new IokeObject(runtime, "A hook allow you to observe what happens to a specific object. All hooks have Hook in their mimic chain.");
            obj.Kind = "Hook";
            obj.MimicsWithoutCheck(runtime.Origin);
            runtime.IokeGround.RegisterCell("Hook", obj);

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one or more arguments to hook into and returns a new Hook connected to them.",
                                                       new TypeCheckingNativeMethod("into", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("firstConnected")
                                                                                    .WithRest("restConnected")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        IokeObject hook = obj.AllocateCopy(context, message);
                                                                                        hook.MimicsWithoutCheck(obj);

                                                                                        IList objs = new SaneArrayList();
                                                                                        foreach(object o in args) {
                                                                                            objs.Add(IokeObject.As(o, context));
                                                                                        }
                                                                                        Hook h = new Hook(objs);
                                                                                        hook.Data = h;
                                                                                        h.Rewire(hook);
                                                                                        return hook;
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the objects this hook is connected to",
                                                       new TypeCheckingNativeMethod.WithNoArguments("connectedObjects", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        Hook h = (Hook)IokeObject.dataOf(on);
                                                                                                        IList l = new SaneArrayList(h.connected);
                                                                                                        return method.runtime.NewList(l);
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one argument and will add that to the list of connected objects",
                                                       new TypeCheckingNativeMethod("hook!", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("objectToHookInto")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        Hook h = (Hook)IokeObject.dataOf(on);
                                                                                        h.connected.Add(IokeObject.As(args[0], context));
                                                                                        h.Rewire(IokeObject.As(on, context));
                                                                                        return on;
                                                                                    })));
        }
Ejemplo n.º 15
0
        public override void Init(IokeObject obj)
        {
            Runtime runtime = obj.runtime;
            obj.Kind = "Regexp Match";

            obj.RegisterMethod(runtime.NewNativeMethod("Returns the target that this match was created against",
                                                       new TypeCheckingNativeMethod.WithNoArguments("target", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        return GetTarget(on);
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a list of all the named groups in the regular expression used to create this match",
                                                       new TypeCheckingNativeMethod.WithNoArguments("names", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        var names = Regexp.GetRegexp(GetRegexp(on)).GroupNames;
                                                                                                        var theNames = new SaneArrayList();
                                                                                                        foreach(object name in names) {
                                                                                                            theNames.Add(context.runtime.GetSymbol(((string)name)));
                                                                                                        }
                                                                                                        return context.runtime.NewList(theNames);
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the part of the target before the text that matched",
                                                       new TypeCheckingNativeMethod.WithNoArguments("beforeMatch", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        return context.runtime.NewText(GetMatchResult(on).Prefix);
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the part of the target after the text that matched",
                                                       new TypeCheckingNativeMethod.WithNoArguments("afterMatch", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        return context.runtime.NewText(GetMatchResult(on).Suffix);
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the text that matched",
                                                       new TypeCheckingNativeMethod.WithNoArguments("match", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        return context.runtime.NewText(GetMatchResult(on).Group(0));
                                                                                                    })));

            obj.AliasMethod("match", "asText", null, null);

            obj.RegisterMethod(runtime.NewNativeMethod("returns the number of groups available in this match",
                                                       new TypeCheckingNativeMethod.WithNoArguments("length", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        return context.runtime.NewNumber(GetMatchResult(on).GroupCount);
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a list of all groups captured in this match. if a group is not matched it will be nil in the list. the actual match text is not included in this list.",
                                                       new TypeCheckingNativeMethod.WithNoArguments("captures", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        var groups = new SaneArrayList();
                                                                                                        MatchResult mr = GetMatchResult(on);
                                                                                                        int len = mr.GroupCount;
                                                                                                        for(int i=1;i<len;i++) {
                                                                                                            if(mr.IsCaptured(i)) {
                                                                                                                groups.Add(context.runtime.NewText(mr.Group(i)));
                                                                                                            } else {
                                                                                                                groups.Add(context.runtime.nil);
                                                                                                            }
                                                                                                        }

                                                                                                        return context.runtime.NewList(groups);
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a list of all groups captured in this match. if a group is not matched it will be nil in the list. the actual match text is the first element in the list.",
                                                       new TypeCheckingNativeMethod.WithNoArguments("asList", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        var groups = new SaneArrayList();
                                                                                                        MatchResult mr = GetMatchResult(on);
                                                                                                        int len = mr.GroupCount;
                                                                                                        for(int i=0;i<len;i++) {
                                                                                                            if(mr.IsCaptured(i)) {
                                                                                                                groups.Add(context.runtime.NewText(mr.Group(i)));
                                                                                                            } else {
                                                                                                                groups.Add(context.runtime.nil);
                                                                                                            }
                                                                                                        }

                                                                                                        return context.runtime.NewList(groups);
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one optional argument that should be either a number or a symbol. this should be the name or index of a group to return the start index for. if no index is supplied, 0 is the default. if the group in question wasn't matched, returns -1.",
                                                       new TypeCheckingNativeMethod("start", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithOptionalPositional("index", "0")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        int index = 0;

                                                                                        if(args.Count > 0) {
                                                                                            object arg = args[0];
                                                                                            if(IokeObject.dataOf(arg) is Number) {
                                                                                                index = Number.ExtractInt(arg, message, context);
                                                                                            } else {
                                                                                                string namedIndex = Text.GetText(((Message)IokeObject.dataOf(context.runtime.asText)).SendTo(context.runtime.asText, context, arg));
                                                                                                int ix = -1;
                                                                                                try {
                                                                                                    ix = Regexp.GetRegexp(GetRegexp(on)).GroupId(namedIndex);
                                                                                                } catch(Exception) {
                                                                                                    return context.runtime.NewNumber(-1);
                                                                                                }
                                                                                                index = ix;
                                                                                            }
                                                                                        }
                                                                                        MatchResult mr = GetMatchResult(on);
                                                                                        if(index < mr.GroupCount && mr.IsCaptured(index)) {
                                                                                            return context.runtime.NewNumber(mr.GetStart(index));
                                                                                        } else {
                                                                                            return context.runtime.NewNumber(-1);
                                                                                        }
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one optional argument that should be either a number or a symbol. this should be the name or index of a group to return the end index for. if no index is supplied, 0 is the default. if the group in question wasn't matched, returns -1.",
                                                       new TypeCheckingNativeMethod("end", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithOptionalPositional("index", "0")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        int index = 0;

                                                                                        if(args.Count > 0) {
                                                                                            object arg = args[0];
                                                                                            if(IokeObject.dataOf(arg) is Number) {
                                                                                                index = Number.ExtractInt(arg, message, context);
                                                                                            } else {
                                                                                                string namedIndex = Text.GetText(((Message)IokeObject.dataOf(context.runtime.asText)).SendTo(context.runtime.asText, context, arg));
                                                                                                int ix = -1;
                                                                                                try {
                                                                                                    ix = Regexp.GetRegexp(GetRegexp(on)).GroupId(namedIndex);
                                                                                                } catch(Exception) {
                                                                                                    return context.runtime.NewNumber(-1);
                                                                                                }
                                                                                                index = ix;
                                                                                            }
                                                                                        }
                                                                                        MatchResult mr = GetMatchResult(on);
                                                                                        if(index < mr.GroupCount && mr.IsCaptured(index)) {
                                                                                            return context.runtime.NewNumber(mr.GetEnd(index));
                                                                                        } else {
                                                                                            return context.runtime.NewNumber(-1);
                                                                                        }
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one optional argument that should be either a number or a symbol. this should be the name or index of a group to return the start and end index for. if no index is supplied, 0 is the default. if the group in question wasn't matched, returns nil, otherwise a pair of the start and end indices.",
                                                       new TypeCheckingNativeMethod("offset", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithOptionalPositional("index", "0")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        int index = 0;

                                                                                        if(args.Count > 0) {
                                                                                            object arg = args[0];
                                                                                            if(IokeObject.dataOf(arg) is Number) {
                                                                                                index = Number.ExtractInt(arg, message, context);
                                                                                            } else {
                                                                                                string namedIndex = Text.GetText(((Message)IokeObject.dataOf(context.runtime.asText)).SendTo(context.runtime.asText, context, arg));
                                                                                                int ix = -1;
                                                                                                try {
                                                                                                    ix = Regexp.GetRegexp(GetRegexp(on)).GroupId(namedIndex);
                                                                                                } catch(Exception) {
                                                                                                    return context.runtime.nil;
                                                                                                }
                                                                                                index = ix;
                                                                                            }
                                                                                        }
                                                                                        MatchResult mr = GetMatchResult(on);
                                                                                        if(index < mr.GroupCount && mr.IsCaptured(index)) {
                                                                                            return context.runtime.NewPair(context.runtime.NewNumber(mr.GetStart(index)), context.runtime.NewNumber(mr.GetEnd(index)));
                                                                                        } else {
                                                                                            return context.runtime.nil;
                                                                                        }
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one indexing argument that should be either a number, a range, a text or a symbol. if it's a number or a range of numbers, these will specify the index of the capture to return. 0 is the whole match. negative indices are interpreted in the usual way. if the range is out of range it will only use as many groups as there are. if it's a text or a sym it will be interpreted as a the name of a named group to return. if an index isn't correct or wasn't matched, it returns nil in those places.",
                                                       new TypeCheckingNativeMethod("[]", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("index")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        object arg = args[0];

                                                                                        MatchResult mr = GetMatchResult(on);

                                                                                        if((IokeObject.dataOf(arg) is Symbol) || (IokeObject.dataOf(arg) is Text)) {
                                                                                            string namedIndex = Text.GetText(((Message)IokeObject.dataOf(context.runtime.asText)).SendTo(context.runtime.asText, context, arg));
                                                                                            int ix = -1;
                                                                                            try {
                                                                                                ix = Regexp.GetRegexp(GetRegexp(on)).GroupId(namedIndex);
                                                                                            } catch(Exception) {
                                                                                                return context.runtime.nil;
                                                                                            }
                                                                                            if(!mr.IsCaptured(ix)) {
                                                                                                return context.runtime.nil;
                                                                                            }
                                                                                            return context.runtime.NewText(mr.Group(ix));
                                                                                        } else {
                                                                                            int size = mr.GroupCount;

                                                                                            if(IokeObject.dataOf(arg) is Range) {
                                                                                                int first = Number.ExtractInt(Range.GetFrom(arg), message, context);

                                                                                                if(first < 0) {
                                                                                                    return context.runtime.NewList(new SaneArrayList());
                                                                                                }

                                                                                                int last = Number.ExtractInt(Range.GetTo(arg), message, context);
                                                                                                bool inclusive = Range.IsInclusive(arg);

                                                                                                if(last < 0) {
                                                                                                    last = size + last;
                                                                                                }

                                                                                                if(last < 0) {
                                                                                                    return context.runtime.NewList(new SaneArrayList());
                                                                                                }

                                                                                                if(last >= size) {
                                                                                                    last = inclusive ? size-1 : size;
                                                                                                }

                                                                                                if(first > last || (!inclusive && first == last)) {
                                                                                                    return context.runtime.NewList(new SaneArrayList());
                                                                                                }

                                                                                                if(!inclusive) {
                                                                                                    last--;
                                                                                                }

                                                                                                var result = new SaneArrayList();
                                                                                                for(int i = first; i < last+1; i++) {
                                                                                                    if(!mr.IsCaptured(i)) {
                                                                                                        result.Add(context.runtime.nil);
                                                                                                    } else {
                                                                                                        result.Add(context.runtime.NewText(mr.Group(i)));
                                                                                                    }
                                                                                                }

                                                                                                return context.runtime.NewList(result);
                                                                                            }

                                                                                            if(!(IokeObject.dataOf(arg) is Number)) {
                                                                                                arg = IokeObject.ConvertToNumber(arg, message, context);
                                                                                            }
                                                                                            int index = ((Number)IokeObject.dataOf(arg)).AsNativeInteger();
                                                                                            if(index < 0) {
                                                                                                index = size + index;
                                                                                            }

                                                                                            if(index >= 0 && index < size && mr.IsCaptured(index)) {
                                                                                                return context.runtime.NewText(mr.Group(index));
                                                                                            } else {
                                                                                                return context.runtime.nil;
                                                                                            }
                                                                                        }
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("will get the named group corresponding to the name of the message, or nil if the named group hasn't been matched. will signal a condition if no such group is defined.",
                                                       new TypeCheckingNativeMethod("pass", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        MatchResult mr = GetMatchResult(on);
                                                                                        string name = Message.GetName(message);

                                                                                        int ix = -1;
                                                                                        try {
                                                                                            ix = Regexp.GetRegexp(GetRegexp(on)).GroupId(name);
                                                                                        } catch(Exception) {
                                                                                            IokeObject condition = IokeObject.As(IokeObject.GetCellChain(message.runtime.Condition,
                                                                                                                                                         message,
                                                                                                                                                         context,
                                                                                                                                                         "Error",
                                                                                                                                                         "NoSuchCell"), context).Mimic(message, context);
                                                                                            condition.SetCell("message", message);
                                                                                            condition.SetCell("context", context);
                                                                                            condition.SetCell("receiver", on);
                                                                                            condition.SetCell("cellName", message.runtime.GetSymbol(name));

                                                                                            message.runtime.WithReturningRestart("ignore", context, ()=>{condition.runtime.ErrorCondition(condition);});
                                                                                            return context.runtime.nil;
                                                                                        }

                                                                                        if(mr.IsCaptured(ix)) {
                                                                                            return context.runtime.NewText(mr.Group(ix));
                                                                                        } else {
                                                                                            return context.runtime.nil;
                                                                                        }
                                                                                    })));
        }
Ejemplo n.º 16
0
        public void AfterInitRuntime(IokeObject obj)
        {
            try {
                using(Stream str = typeof(IokeSystem).Assembly.GetManifestResourceStream("Ioke.Lang.version.properties")) {
                    using(StreamReader sr = new StreamReader(str, NETSystem.Text.Encoding.UTF8)) {
                        var result = new Dictionary<string, string>();
                        while(!sr.EndOfStream) {
                            string ss = sr.ReadLine();
                            if(ss.IndexOf('=') != -1) {
                                string[] parts = ss.Split('=');
                                result[parts[0].Trim()] = parts[1].Trim();
                            }
                        }

                        string version = result["ioke.build.version"];
                        string runtimeVersion = result["ioke.build.runtimeVersion"];
                        string versionString = result["ioke.build.versionString"];
                        string date = result["ioke.build.date"];
                        string commit = result["ioke.build.commit"];

                        IokeObject versionObj = NewFromOrigin();

                        versionObj.SetCell("machine", NewText("ikc"));

                        var versionParts = new SaneArrayList();
                        foreach(var s in runtimeVersion.Split(new Char[] {'.', '-'})) {
                            try {
                                versionParts.Add(NewNumber(s));
                            } catch(System.Exception) {
                                versionParts.Add(NewText(s));
                            }
                        }

                        versionObj.SetCell("versionNumber", NewList(versionParts));
                        versionObj.SetCell("release", NewText(version));
                        versionObj.SetCell("fullVersion", NewText(versionString));
                        versionObj.SetCell("commit", NewText(commit));
                        versionObj.SetCell("date", NewText(date));

                        obj.SetCell("version", versionObj);
                    }
                }
            } catch(System.Exception) {
            }
        }
Ejemplo n.º 17
0
 public object WithReturningRescue(IokeObject context, object toReturn, RunnableWithReturnAndControlFlow nativeRescue)
 {
     IList<RescueInfo> rescues = new SaneList<RescueInfo>();
     IokeObject rr = IokeObject.As(Interpreter.Send(this.mimicMessage, context, this.Rescue), context);
     IList conds = new SaneArrayList();
     conds.Add(this.Condition);
     rescues.Add(new RescueInfo(rr, conds, rescues, GetBindIndex()));
     RegisterRescues(rescues);
     try {
         return nativeRescue();
     } catch(ControlFlow.Rescue e) {
         if(e.GetRescue.token == rescues) {
             return toReturn;
         } else {
             throw e;
         }
     } finally {
         UnregisterRescues(rescues);
     }
 }
Ejemplo n.º 18
0
        public object WithRestartReturningArguments(RunnableWithControlFlow code, IokeObject context, params Restart.NativeRestart[] restarts)
        {
            IList<RestartInfo> rrs = new SaneList<RestartInfo>();
            BindIndex index = GetBindIndex();

            foreach(Restart.NativeRestart rjr in restarts) {
                IokeObject rr = IokeObject.As(Interpreter.Send(this.mimicMessage, context, this.Restart), context);
                IokeObject.SetCell(rr, "name", GetSymbol(rjr.Name), context);

                IList args = new SaneArrayList();
                foreach(string argName in rjr.ArgumentNames) {
                    args.Add(GetSymbol(argName));
                }

                IokeObject.SetCell(rr, "name", GetSymbol(rjr.Name), context);
                IokeObject.SetCell(rr, "argumentNames", NewList(args), context);

                string report = rjr.Report();
                if(report != null) {
                    IokeObject.SetCell(rr, "report", EvaluateString("fn(r, \"" + report + "\")", this.Message, this.Ground), context);
                }

                rrs.Insert(0, new RestartInfo(rjr.Name, rr, rrs, index, rjr));
                index = index.NextCol();
            }
            RegisterRestarts(rrs);

            try {
                code();
                return new SaneArrayList();
            } catch(ControlFlow.Restart e) {
                RestartInfo ri = null;
                if((ri = e.GetRestart).token == rrs) {
                    Restart.NativeRestart currentRjr = (Restart.NativeRestart)ri.data;
                    IokeObject result = currentRjr.Invoke(context, e.Arguments);
                    return result;
                } else {
                    throw e;
                }
            } finally {
                UnregisterRestarts(rrs);
            }
        }
Ejemplo n.º 19
0
        public void ReportNativeException(Exception e, IokeObject message, IokeObject context)
        {
            IokeObject condition = IokeObject.As(IokeObject.GetCellChain(this.Condition,
                                                                         message,
                                                                         context,
                                                                         "Error",
                                                                         "NativeException"), context).Mimic(message, context);
            condition.SetCell("message", message);
            condition.SetCell("context", context);
            condition.SetCell("receiver", context);
            condition.SetCell("exceptionType", NewText(e.GetType().FullName));

            if(e.Message != null) {
                condition.SetCell("exceptionMessage", NewText(e.Message));
            } else {
                condition.SetCell("exceptionMessage", nil);
            }

            var st = new System.Diagnostics.StackTrace(e);
            var ob = new SaneArrayList();
            foreach(var frame in st.GetFrames()) {
                ob.Add(NewText(frame.ToString()));
            }
            condition.SetCell("exceptionStackTrace", NewList(ob));

            this.ErrorCondition(condition);
        }
Ejemplo n.º 20
0
 public IList GetEvaluatedArguments(IokeObject self, IokeObject context)
 {
     IList args = new SaneArrayList(arguments.Count);
     foreach(object o in arguments) {
         args.Add(GetEvaluatedArgument(o, context));
     }
     return args;
 }
Ejemplo n.º 21
0
        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).Cells), 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 = ((Message)IokeObject.dataOf(message)).GetEvaluatedArgument(message, 0, context);
                                                                            string name = Text.GetText(((Message)IokeObject.dataOf(runtime.asText)).SendTo(runtime.asText, context, _name));

                                                                            IokeObject newMessage = Message.DeepCopy(message);
                                                                            newMessage.Arguments.RemoveAt(0);
                                                                            Message.SetName(newMessage, name);
                                                                            return ((Message)IokeObject.dataOf(newMessage)).SendTo(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, ((Message)IokeObject.dataOf(message)).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.IsFrozen(on) ? 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;
                                                           })));
        }
Ejemplo n.º 22
0
        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(((Message)IokeObject.dataOf(runtime.asText)).SendTo(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 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 ((Message)IokeObject.dataOf(msg)).EvaluateCompleteWith(msg, context, context.RealContext);
                                                                            } 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;
                                                                        })));
        }
Ejemplo n.º 23
0
Archivo: Number.cs Proyecto: nope/ioke
        public override void Init(IokeObject obj)
        {
            Runtime runtime = obj.runtime;
            IokeObject number = obj;

            obj.Kind = "Number";
            obj.Mimics(IokeObject.As(runtime.Mixins.GetCell(null, null, "Comparing"), obj), runtime.nul, runtime.nul);

            IokeObject real = new IokeObject(runtime, "A real number can be either a rational number or a decimal number", new Number());
            real.MimicsWithoutCheck(number);
            real.Kind = "Number Real";
            number.RegisterCell("Real", real);

            IokeObject rational = new IokeObject(runtime, "A rational number is either an integer or a ratio", new Number());
            rational.MimicsWithoutCheck(real);
            rational.Kind = "Number Rational";
            number.RegisterCell("Rational", rational);

            IokeObject integer = new IokeObject(runtime, "An integral number", new Number());
            integer.MimicsWithoutCheck(rational);
            integer.Kind = "Number Integer";
            number.RegisterCell("Integer", integer);
            runtime.Integer = integer;

            IokeObject ratio = new IokeObject(runtime, "A ratio of two integral numbers", new Number());
            ratio.MimicsWithoutCheck(rational);
            ratio.Kind = "Number Ratio";
            number.RegisterCell("Ratio", ratio);
            runtime.Ratio = ratio;

            IokeObject _decimal = new IokeObject(runtime, "An exact, unlimited representation of a decimal number", new Decimal(BigDecimal.ZERO));
            _decimal.MimicsWithoutCheck(real);
            _decimal.Init();
            number.RegisterCell("Decimal", _decimal);

            IokeObject infinity = new IokeObject(runtime, "A value representing infinity", new Number(RatNum.infinity(1)));
            infinity.MimicsWithoutCheck(ratio);
            infinity.Kind = "Number Infinity";
            number.RegisterCell("Infinity", infinity);
            runtime.Infinity = infinity;

            IokeObject infinity2 = new IokeObject(runtime, "A value representing infinity", new Number(RatNum.infinity(1)));
            infinity2.MimicsWithoutCheck(ratio);
            infinity2.Kind = "Number \u221E";
            number.RegisterCell("\u221E", infinity2);

            number.RegisterMethod(runtime.NewNativeMethod("returns a hash for the number",
                                                           new NativeMethod.WithNoArguments("hash", (method, context, message, on, outer) => {
                                                                   outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                                                                   return context.runtime.NewNumber(Number.GetValue(on).GetHashCode());
                                                               })));

            number.RegisterMethod(runtime.NewNativeMethod("returns the square root of the receiver. this should return the same result as calling ** with 0.5",
                                                           new NativeMethod.WithNoArguments("sqrt", (method, context, message, on, outer) => {
                                                                   outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);

                                                                   RatNum value = Number.GetValue(on);
                                                                   if(value is IntFraction) {
                                                                       IntNum num = value.numerator();
                                                                       IntNum den = value.denominator();
                                                                       BigDecimal nums = new BigSquareRoot().Get(num.AsBigDecimal());
                                                                       BigDecimal dens = new BigSquareRoot().Get(den.AsBigDecimal());
                                                                       try {
                                                                           num = IntNum.valueOf(nums.toBigIntegerExact().ToString());
                                                                           den = IntNum.valueOf(dens.toBigIntegerExact().ToString());
                                                                           return context.runtime.NewNumber(new IntFraction(num, den));
                                                                       } catch(ArithmeticException e) {
                                                                           // Ignore and fall through
                                                                       }
                                                                   }

                                                                   if(RatNum.compare(value, IntNum.zero()) < 1) {
                                                                       IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                                                                          message,
                                                                                                                                          context,
                                                                                                                                          "Error",
                                                                                                                                          "Arithmetic"), context).Mimic(message, context);
                                                                       condition.SetCell("message", message);
                                                                       condition.SetCell("context", context);
                                                                       condition.SetCell("receiver", on);

                                                                       context.runtime.ErrorCondition(condition);
                                                                   }
                                                                   return context.runtime.NewDecimal(new BigSquareRoot().Get(value.AsBigDecimal()));
                                                               })));

            number.RegisterMethod(runtime.NewNativeMethod("returns true if the left hand side number is equal to the right hand side number.",
                                                       new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(runtime.Number)
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        Number d = (Number)IokeObject.dataOf(on);
                                                                                        object other = args[0];

                                                                                        return ((other is IokeObject) &&
                                                                                                (IokeObject.dataOf(other) is Number)
                                                                                                && (((d.kind || ((Number)IokeObject.dataOf(other)).kind) ? on == other :
                                                                                                     d.value.Equals(((Number)IokeObject.dataOf(other)).value)))) ? context.runtime.True : context.runtime.False;
                                                                                    })));

            rational.RegisterMethod(runtime.NewNativeMethod("compares this number against the argument, returning -1, 0 or 1 based on which one is larger. if the argument is a decimal, the receiver will be converted into a form suitable for comparing against a decimal, and then compared - it's not specified whether this will actually call Decimal#<=> or not. if the argument is neither a Rational nor a Decimal, it tries to call asRational, and if that doesn't work it returns nil.",
                                                            new TypeCheckingNativeMethod("<=>", TypeCheckingArgumentsDefinition.builder()
                                                                                         .ReceiverMustMimic(rational)
                                                                                         .WithRequiredPositional("other")
                                                                                         .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];

                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(data is Decimal) {
                                                                                                 return context.runtime.NewNumber(new BigDecimal(Number.GetValue(on).longValue()).CompareTo(Decimal.GetValue(arg)));
                                                                                             } else {
                                                                                                 if(!(data is Number)) {
                                                                                                     arg = IokeObject.ConvertToRational(arg, message, context, false);
                                                                                                     if(!(IokeObject.dataOf(arg) is Number)) {
                                                                                                         // Can't compare, so bail out
                                                                                                         return context.runtime.nil;
                                                                                                     }
                                                                                                 }

                                                                                                 if(on == rational || arg == rational || on == integer || arg == integer || on == ratio || arg == ratio) {
                                                                                                     if(arg == on) {
                                                                                                         return context.runtime.NewNumber(0);
                                                                                                     }
                                                                                                     return context.runtime.nil;
                                                                                                 }

                                                                                                 return context.runtime.NewNumber(IntNum.compare(Number.GetValue(on),Number.GetValue(arg)));
                                                                                             }
                                                                                         })));

            number.RegisterMethod(runtime.NewNativeMethod("compares this against the argument. should be overridden - in this case only used to check for equivalent number kinds",
                                                          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>());
                                                                               object arg = args[0];
                                                                               if(on == arg) {
                                                                                   return context.runtime.True;
                                                                               } else {
                                                                                   return context.runtime.False;
                                                                               }
                                                                           })));

            rational.RegisterMethod(runtime.NewNativeMethod("compares this number against the argument, true if this number is the same, otherwise false",
                                                            new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder()
                                                                                         .ReceiverMustMimic(number)
                                                                                         .WithRequiredPositional("other")
                                                                                         .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             if(on == rational || arg == rational || on == integer || arg == integer || on == ratio || arg == ratio || on == infinity || arg == infinity || on == infinity2 || arg == infinity2) {
                                                                                                 if(arg == on) {
                                                                                                     return context.runtime.True;
                                                                                                 }
                                                                                                 return context.runtime.False;
                                                                                             }
                                                                                             if(IokeObject.dataOf(arg) is Decimal) {
                                                                                                 return (new BigDecimal(Number.GetValue(on).longValue()).CompareTo(Decimal.GetValue(arg)) == 0) ? context.runtime.True : context.runtime.False;
                                                                                             } else if(IokeObject.dataOf(arg) is Number) {
                                                                                                 return IntNum.compare(Number.GetValue(on),Number.GetValue(arg)) == 0 ? context.runtime.True : context.runtime.False;
                                                                                             } else {
                                                                                                 return context.runtime.False;
                                                                                             }
                                                                                         })));

            rational.RegisterMethod(runtime.NewNativeMethod("returns the difference between this number and the argument. if the argument is a decimal, the receiver will be converted into a form suitable for subtracting against a decimal, and then subtracted. if the argument is neither a Rational nor a Decimal, it tries to call asRational, and if that fails it signals a condition.",
                                                            new TypeCheckingNativeMethod("-", TypeCheckingArgumentsDefinition.builder()
                                                                                         .ReceiverMustMimic(number)
                                                                                         .WithRequiredPositional("subtrahend")
                                                                                         .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(data is Decimal) {
                                                                                                 return ((Message)IokeObject.dataOf(context.runtime.minusMessage)).SendTo(context.runtime.minusMessage, context, context.runtime.NewDecimal(((Number)IokeObject.dataOf(on))), arg);
                                                                                             } else {
                                                                                                 if(!(data is Number)) {
                                                                                                     arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                                 }

                                                                                                 return context.runtime.NewNumber((RatNum)Number.GetValue(on).sub(Number.GetValue(arg)));
                                                                                             }
                                                                                         })));
            integer.RegisterMethod(runtime.NewNativeMethod("Returns the successor of this number", new TypeCheckingNativeMethod.WithNoArguments("succ", integer,
                                                                                                                                                (method, on, args, keywords, context, message) => {
                                                                                                                                                    return runtime.NewNumber(IntNum.add(Number.IntValue(on),IntNum.one()));
                                                                                                                                                })));

            integer.RegisterMethod(runtime.NewNativeMethod("Returns the predecessor of this number", new TypeCheckingNativeMethod.WithNoArguments("pred", integer,
                                                                                                                                                (method, on, args, keywords, context, message) => {
                                                                                                                                                    return runtime.NewNumber(IntNum.sub(Number.IntValue(on),IntNum.one()));
                                                                                                                                                })));

            infinity.RegisterMethod(runtime.NewNativeMethod("Returns a text inspection of the object",
                                                            new TypeCheckingNativeMethod.WithNoArguments("inspect", infinity,
                                                                                                         (method, on, args, keywords, context, message) => {
                                                                                                             return runtime.NewText("Infinity");
                                                                                                         })));

            infinity.RegisterMethod(runtime.NewNativeMethod("Returns a brief text inspection of the object",
                                                            new TypeCheckingNativeMethod.WithNoArguments("notice", infinity,
                                                                                                         (method, on, args, keywords, context, message) => {
                                                                                                             return runtime.NewText("Infinity");
                                                                                                         })));

            infinity2.RegisterMethod(runtime.NewNativeMethod("Returns a text inspection of the object",
                                                            new TypeCheckingNativeMethod.WithNoArguments("inspect", infinity2,
                                                                                                         (method, on, args, keywords, context, message) => {
                                                                                                             return runtime.NewText("\u221E");
                                                                                                         })));

            infinity2.RegisterMethod(runtime.NewNativeMethod("Returns a brief text inspection of the object",
                                                            new TypeCheckingNativeMethod.WithNoArguments("notice", infinity2,
                                                                                                         (method, on, args, keywords, context, message) => {
                                                                                                             return runtime.NewText("\u221E");
                                                                                                         })));

            rational.RegisterMethod(runtime.NewNativeMethod("returns the addition of this number and the argument. if the argument is a decimal, the receiver will be converted into a form suitable for addition against a decimal, and then added. if the argument is neither a Rational nor a Decimal, it tries to call asRational, and if that fails it signals a condition.",
                                                            new TypeCheckingNativeMethod("+", TypeCheckingArgumentsDefinition.builder()
                                                                                         .ReceiverMustMimic(number)
                                                                                         .WithRequiredPositional("addend")
                                                                                         .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(data is Decimal) {
                                                                                                 return ((Message)IokeObject.dataOf(context.runtime.plusMessage)).SendTo(context.runtime.plusMessage, context, context.runtime.NewDecimal(((Number)IokeObject.dataOf(on))), arg);
                                                                                             } else {
                                                                                                 if(!(data is Number)) {
                                                                                                     arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                                 }

                                                                                                 return context.runtime.NewNumber(RatNum.add(Number.GetValue(on),Number.GetValue(arg),1));
                                                                                             }
                                                                                         })));

            rational.RegisterMethod(runtime.NewNativeMethod("returns the product of this number and the argument. if the argument is a decimal, the receiver will be converted into a form suitable for multiplying against a decimal, and then multiplied. if the argument is neither a Rational nor a Decimal, it tries to call asRational, and if that fails it signals a condition.",
                                                            new TypeCheckingNativeMethod("*", TypeCheckingArgumentsDefinition.builder()
                                                                                         .ReceiverMustMimic(number)
                                                                                         .WithRequiredPositional("multiplier")
                                                                                         .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(data is Decimal) {
                                                                                                 return ((Message)IokeObject.dataOf(context.runtime.multMessage)).SendTo(context.runtime.multMessage, context, context.runtime.NewDecimal(((Number)IokeObject.dataOf(on))), arg);
                                                                                             } else {
                                                                                                 if(!(data is Number)) {
                                                                                                     arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                                 }

                                                                                                 return context.runtime.NewNumber(RatNum.times(Number.GetValue(on),Number.GetValue(arg)));
                                                                                             }
                                                                                         })));

            rational.RegisterMethod(runtime.NewNativeMethod("returns the quotient of this number and the argument. if the division is not exact, it will return a Ratio.",
                                                            new TypeCheckingNativeMethod("/", TypeCheckingArgumentsDefinition.builder()
                                                                                         .ReceiverMustMimic(number)
                                                                                         .WithRequiredPositional("dividend")
                                                                                         .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(data is Decimal) {
                                                                                                 return ((Message)IokeObject.dataOf(context.runtime.divMessage)).SendTo(context.runtime.divMessage, context, context.runtime.NewDecimal(((Number)IokeObject.dataOf(on))), arg);
                                                                                             } else {
                                                                                                 if(!(data is Number)) {
                                                                                                     arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                                 }

                                                                                                 while(Number.GetValue(arg).isZero()) {
                                                                                                     IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                                                                                                  message,
                                                                                                                                                                  context,
                                                                                                                                                                  "Error",
                                                                                                                                                                  "Arithmetic",
                                                                                                                                                                  "DivisionByZero"), context).Mimic(message, context);
                                                                                                     condition.SetCell("message", message);
                                                                                                     condition.SetCell("context", context);
                                                                                                     condition.SetCell("receiver", on);

                                                                                                     object[] newCell = new object[]{arg};

                                                                                                     context.runtime.WithRestartReturningArguments(()=>{context.runtime.ErrorCondition(condition);},
                                                                                                                                                   context,
                                                                                                                                                   new IokeObject.UseValue("dividend", newCell));
                                                                                                     arg = newCell[0];
                                                                                                 }

                                                                                                 return context.runtime.NewNumber(RatNum.divide(Number.GetValue(on),Number.GetValue(arg)));
                                                                                             }
                                                                                         })));

            integer.RegisterMethod(runtime.NewNativeMethod("returns the modulo of this number and the argument",
                                                           new TypeCheckingNativeMethod("%", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(integer)
                                                                                        .WithRequiredPositional("dividend")
                                                                                        .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);
                                                                                             if(!(data is Number)) {
                                                                                                 arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                             }

                                                                                             return context.runtime.NewNumber(IntNum.modulo(Number.IntValue(on),Number.IntValue(arg)));
                                                                                        })));

            integer.RegisterMethod(runtime.NewNativeMethod("returns how many times the first number can be divided by the second one",
                                                           new TypeCheckingNativeMethod("div", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(integer)
                                                                                        .WithRequiredPositional("dividend")
                                                                                        .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             while(Number.GetValue(arg).isZero()) {
                                                                                                 IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                                                                                              message,
                                                                                                                                                              context,
                                                                                                                                                              "Error",
                                                                                                                                                              "Arithmetic",
                                                                                                                                                              "DivisionByZero"), context).Mimic(message, context);
                                                                                                 condition.SetCell("message", message);
                                                                                                 condition.SetCell("context", context);
                                                                                                 condition.SetCell("receiver", on);

                                                                                                 object[] newCell = new object[]{arg};

                                                                                                 context.runtime.WithRestartReturningArguments(()=>{context.runtime.ErrorCondition(condition);},
                                                                                                                                               context,
                                                                                                                                               new IokeObject.UseValue("dividend", newCell));
                                                                                                 arg = newCell[0];
                                                                                             }
                                                                                             IokeData data = IokeObject.dataOf(arg);
                                                                                             return context.runtime.NewNumber(IntNum.quotient(Number.IntValue(on),Number.IntValue(arg), IntNum.TRUNCATE));
                                                                                        })));

            integer.RegisterMethod(runtime.NewNativeMethod("returns a tuple of how many times the first number can be divided by the second one, and the remainder",
                                                           new TypeCheckingNativeMethod("divmod", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(integer)
                                                                                        .WithRequiredPositional("dividend")
                                                                                        .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             while(Number.GetValue(arg).isZero()) {
                                                                                                 IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                                                                                              message,
                                                                                                                                                              context,
                                                                                                                                                              "Error",
                                                                                                                                                              "Arithmetic",
                                                                                                                                                              "DivisionByZero"), context).Mimic(message, context);
                                                                                                 condition.SetCell("message", message);
                                                                                                 condition.SetCell("context", context);
                                                                                                 condition.SetCell("receiver", on);

                                                                                                 object[] newCell = new object[]{arg};

                                                                                                 context.runtime.WithRestartReturningArguments(()=>{context.runtime.ErrorCondition(condition);},
                                                                                                                                               context,
                                                                                                                                               new IokeObject.UseValue("dividend", newCell));
                                                                                                 arg = newCell[0];
                                                                                             }
                                                                                             IokeData data = IokeObject.dataOf(arg);
                                                                                             IntNum q = new IntNum();
                                                                                             IntNum r = new IntNum();
                                                                                             IntNum.divide(Number.IntValue(on),Number.IntValue(arg), q, r, IntNum.TRUNCATE);
                                                                                             return context.runtime.NewTuple(context.runtime.NewNumber(q.canonicalize()), context.runtime.NewNumber(r.canonicalize()));
                                                                                        })));

            rational.RegisterMethod(runtime.NewNativeMethod("returns this number to the power of the argument",
                                                            new TypeCheckingNativeMethod("**", TypeCheckingArgumentsDefinition.builder()
                                                                                         .ReceiverMustMimic(rational)
                                                                                         .WithRequiredPositional("exponent")
                                                                                         .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(!(data is Number)) {
                                                                                                 if(data is Decimal) {
                                                                                                     return context.runtime.NewDecimal(((RealNum)(Complex.power(Number.GetValue(on), new DFloNum(Decimal.GetValue(arg).ToString())))).AsBigDecimal());
                                                                                                 } else {
                                                                                                     arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                                 }
                                                                                             }

                                                                                             return context.runtime.NewNumber((RatNum)Number.GetValue(on).power(Number.IntValue(arg)));
                                                                                         })));

            integer.RegisterMethod(runtime.NewNativeMethod("returns this number bitwise and the argument",
                                                           new TypeCheckingNativeMethod("&", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(integer)
                                                                                        .WithRequiredPositional("other")
                                                                                        .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(!(data is Number)) {
                                                                                                 arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                             }

                                                                                             return context.runtime.NewNumber(BitOps.and(Number.IntValue(on), Number.IntValue(arg)));
                                                                                        })));

            integer.RegisterMethod(runtime.NewNativeMethod("returns this number bitwise or the argument",
                                                           new TypeCheckingNativeMethod("|", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(integer)
                                                                                        .WithRequiredPositional("other")
                                                                                        .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(!(data is Number)) {
                                                                                                 arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                             }

                                                                                             return context.runtime.NewNumber(BitOps.ior(Number.IntValue(on), Number.IntValue(arg)));
                                                                                        })));

            integer.RegisterMethod(runtime.NewNativeMethod("returns this number bitwise xor the argument",
                                                           new TypeCheckingNativeMethod("^", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(integer)
                                                                                        .WithRequiredPositional("other")
                                                                                        .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(!(data is Number)) {
                                                                                                 arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                             }

                                                                                             return context.runtime.NewNumber(BitOps.xor(Number.IntValue(on), Number.IntValue(arg)));
                                                                                        })));

            integer.RegisterMethod(runtime.NewNativeMethod("returns this number left shifted by the argument",
                                                           new TypeCheckingNativeMethod("<<", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(integer)
                                                                                        .WithRequiredPositional("other")
                                                                                        .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(!(data is Number)) {
                                                                                                 arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                             }

                                                                                             return context.runtime.NewNumber(IntNum.shift(Number.IntValue(on), Number.IntValue(arg).intValue()));
                                                                                        })));

            integer.RegisterMethod(runtime.NewNativeMethod("returns this number right shifted by the argument",
                                                           new TypeCheckingNativeMethod(">>", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(integer)
                                                                                        .WithRequiredPositional("other")
                                                                                        .Arguments,
                                                                                         (method, on, args, keywords, context, message) => {
                                                                                             object arg = args[0];
                                                                                             IokeData data = IokeObject.dataOf(arg);

                                                                                             if(!(data is Number)) {
                                                                                                 arg = IokeObject.ConvertToRational(arg, message, context, true);
                                                                                             }

                                                                                             return context.runtime.NewNumber(IntNum.shift(Number.IntValue(on), -Number.IntValue(arg).intValue()));
                                                                                        })));

            rational.RegisterMethod(runtime.NewNativeMethod("Returns a text representation of the object",
                                                            new TypeCheckingNativeMethod.WithNoArguments("asText", number,
                                                                                             (method, on, args, keywords, context, message) => {
                                                                                                 return runtime.NewText(on.ToString());
                                                                                             })));

            rational.RegisterMethod(obj.runtime.NewNativeMethod("Returns a text inspection of the object",
                                                                new TypeCheckingNativeMethod.WithNoArguments("inspect", number,
                                                                                                             (method, on, args, keywords, context, message) => {
                                                                                                                 return method.runtime.NewText(Number.GetInspect(on));
                                                                                                             })));

            rational.RegisterMethod(obj.runtime.NewNativeMethod("Returns a brief text inspection of the object",
                                                                new TypeCheckingNativeMethod.WithNoArguments("notice", number,
                                                                                                             (method, on, args, keywords, context, message) => {
                                                                                                                 return method.runtime.NewText(Number.GetInspect(on));
                                                                                                             })));

            integer.RegisterMethod(runtime.NewNativeMethod("Expects one or two arguments. If one argument is given, executes it as many times as the value of the receiving number. If two arguments are given, the first will be an unevaluated name that will receive the current loop value on each repitition. the iteration length is limited to the positive maximum of a Java int",
                                                           new NativeMethod("times", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositionalUnevaluated("argumentNameOrCode")
                                                                            .WithOptionalPositionalUnevaluated("code")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                                                                                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);

                                                                                int num = Number.GetValue(context.runtime.Integer.ConvertToThis(on, message, context)).intValue();
                                                                                if(message.Arguments.Count == 0) {
                                                                                    return runtime.nil;
                                                                                } else if(message.Arguments.Count == 1) {
                                                                                    object result = runtime.nil;
                                                                                    while(num > 0) {
                                                                                        result = ((Message)IokeObject.dataOf(message)).GetEvaluatedArgument(message, 0, context);
                                                                                        num--;
                                                                                    }
                                                                                    return result;
                                                                                } else {
                                                                                    int ix = 0;
                                                                                    string name = ((IokeObject)Message.GetArguments(message)[0]).Name;
                                                                                    object result = runtime.nil;
                                                                                    while(ix<num) {
                                                                                        context.SetCell(name, runtime.NewNumber(IntNum.make(ix)));
                                                                                        result = ((Message)IokeObject.dataOf(message)).GetEvaluatedArgument(message, 1, context);
                                                                                        ix++;
                                                                                    }
                                                                                    return result;
                                                                                }
                                                                            })));

            integer.RegisterMethod(runtime.NewNativeMethod("Returns a Text that represents the character with the same character code of this number",
                                                           new TypeCheckingNativeMethod.WithNoArguments("char", integer,
                                                                                                        (method, on, args, keywords, context, message) => {
                                                                                                            return runtime.NewText(Convert.ToString((char)Number.IntValue(on).intValue()));
                                                                                                        })));
        }
Ejemplo n.º 24
0
        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, 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 = 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 = 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 = 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 = 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 = 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 = ((Message)IokeObject.dataOf(context.runtime.callMessage)).SendTo(context.runtime.callMessage, context, args[1], ff);
                                                                            } finally {
                                                                                ((Message)IokeObject.dataOf(context.runtime.closeMessage)).SendTo(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 = 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 = 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 = 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;
                                                                        })));
        }
Ejemplo n.º 25
0
        public static IokeObject DeepCopy(object message)
        {
            IokeObject copy = IokeObject.As(message, null).Mimic(null, null);
            CopySourceLocation(message, copy);
            Message orgMsg = (Message)IokeObject.dataOf(message);
            Message copyMsg = (Message)IokeObject.dataOf(copy);

            copyMsg.isTerminator = orgMsg.isTerminator;
            copyMsg.cached = orgMsg.cached;

            IList newArgs = new SaneArrayList();
            foreach(object arg in orgMsg.arguments) {
                if(IokeObject.IsObjectMessage(arg)) {
                    newArgs.Add(DeepCopy(arg));
                } else {
                    newArgs.Add(arg);
                }
            }
            copyMsg.arguments = newArgs;

            if(orgMsg.next != null) {
                copyMsg.next = DeepCopy(orgMsg.next);
                Message.SetPrev(orgMsg.next, copy);
            }

            return copy;
        }
Ejemplo n.º 26
0
 public void AssignArgumentValues(IokeObject locals, IokeObject context, IokeObject message, object on, Call call)
 {
     if(call.cachedPositional != null) {
         AssignArgumentValues(locals, context, message, on, call.cachedPositional, call.cachedKeywords, call.cachedArgCount);
     } else {
         IList argumentsWithoutKeywords = new SaneArrayList();
         IDictionary<string, object> givenKeywords = new SaneDictionary<string, object>();
         int argCount = GetEvaluatedArguments(context, message, on, argumentsWithoutKeywords, givenKeywords);
         call.cachedPositional = argumentsWithoutKeywords;
         call.cachedKeywords = givenKeywords;
         call.cachedArgCount = argCount;
         AssignArgumentValues(locals, context, message, on, argumentsWithoutKeywords, givenKeywords, argCount);
     }
 }
Ejemplo n.º 27
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);
                                                                                                    })));
        }
Ejemplo n.º 28
0
 public void AssignArgumentValues(IokeObject locals, IokeObject context, IokeObject message, object on)
 {
     IList argumentsWithoutKeywords = new SaneArrayList();
     IDictionary<string, object> givenKeywords = new SaneDictionary<string, object>();
     int argCount = GetEvaluatedArguments(context, message, on, argumentsWithoutKeywords, givenKeywords);
     AssignArgumentValues(locals, context, message, on, argumentsWithoutKeywords, givenKeywords, argCount);
 }
Ejemplo n.º 29
0
        public override void Init(IokeObject obj)
        {
            Runtime runtime = obj.runtime;

            obj.Kind = "List";
            obj.Mimics(IokeObject.As(IokeObject.FindCell(runtime.Mixins, "Sequenced"), null), runtime.nul, runtime.nul);

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a hash for the list",
                                                           new NativeMethod.WithNoArguments("hash", (method, context, message, on, outer) => {
                                                                   outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                                                                   return context.runtime.NewNumber(((IokeList)IokeObject.dataOf(on)).list.GetHashCode());
                                                               })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if the left hand side list is equal to the right hand side list.",
                                                       new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(runtime.List)
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        IokeList d = (IokeList)IokeObject.dataOf(on);
                                                                                        object other = args[0];
                                                                                        return ((other is IokeObject) &&
                                                                                                (IokeObject.dataOf(other) is IokeList) &&
                                                                                                d.list.Equals(((IokeList)IokeObject.dataOf(other)).list)) ? context.runtime.True : context.runtime.False;
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a new sequence to iterate over this list",
                                                       new TypeCheckingNativeMethod.WithNoArguments("seq", runtime.List,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        IokeObject ob = method.runtime.IteratorSequence.AllocateCopy(null, null);
                                                                                                        ob.MimicsWithoutCheck(method.runtime.IteratorSequence);
                                                                                                        ob.Data = new Sequence.IteratorSequence(IokeList.GetList(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 list. 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 list 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 list.",
                                                       new NativeMethod("each", DefaultArgumentsDefinition.builder()
                                                                        .WithOptionalPositionalUnevaluated("indexOrArgOrCode")
                                                                        .WithOptionalPositionalUnevaluated("argOrCode")
                                                                        .WithOptionalPositionalUnevaluated("code")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                                                                            outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);

                                                                            object onAsList = context.runtime.List.ConvertToThis(on, message, context);
                                                                            var ls = ((IokeList)IokeObject.dataOf(onAsList)).list;
                                                                            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 ls) {
                                                                                    context.runtime.interpreter.Evaluate(code, context, context.RealContext, o);
                                                                                }
                                                                                break;
                                                                            }
                                                                            case 2: {
                                                                                IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for List#each", context);
                                                                                string name = IokeObject.As(message.Arguments[0], context).Name;
                                                                                IokeObject code = IokeObject.As(message.Arguments[1], context);

                                                                                foreach(object o in ls) {
                                                                                    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 List#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 ls) {
                                                                                    c.SetCell(name, o);
                                                                                    c.SetCell(iname, runtime.NewNumber(index++));
                                                                                    context.runtime.interpreter.Evaluate(code, c, c.RealContext, c);
                                                                                }
                                                                                break;
                                                                            }
                                                                            }
                                                                            return onAsList;
                                                                        })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes one argument, the index of the element to be returned. can be negative, and will in that case return indexed from the back of the list. if the index is outside the bounds of the list, will return nil. the argument can also be a range, and will in that case interpret the first index as where to start, and the second the end. the end can be negative and will in that case be from the end. if the first argument is negative, or after the second, an empty list will be returned. if the end point is larger than the list, the size of the list will be used as the end point.",
                                                       new TypeCheckingNativeMethod("at", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(runtime.List)
                                                                                    .WithRequiredPositional("index")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        object arg = args[0];

                                                                                        if(IokeObject.dataOf(arg) is Range) {
                                                                                            int first = Number.ExtractInt(Range.GetFrom(arg), message, context);

                                                                                            if(first < 0) {
                                                                                                return context.runtime.NewList(new SaneArrayList());
                                                                                            }

                                                                                            int last = Number.ExtractInt(Range.GetTo(arg), message, context);
                                                                                            bool inclusive = Range.IsInclusive(arg);

                                                                                            var o = ((IokeList)IokeObject.dataOf(on)).List;
                                                                                            int size = o.Count;

                                                                                            if(last < 0) {
                                                                                                last = size + last;
                                                                                            }

                                                                                            if(last < 0) {
                                                                                                return context.runtime.NewList(new SaneArrayList());
                                                                                            }

                                                                                            if(last >= size) {

                                                                                                last = inclusive ? size-1 : size;
                                                                                            }

                                                                                            if(first > last || (!inclusive && first == last)) {
                                                                                                return context.runtime.NewList(new SaneArrayList());
                                                                                            }

                                                                                            if(!inclusive) {
                                                                                                last--;
                                                                                            }

                                                                                            var l = new SaneArrayList();
                                                                                            for(int i = first; i<last+1; i++) {
                                                                                                l.Add(o[i]);
                                                                                            }

                                                                                            return context.runtime.NewList(l);
                                                                                        }

                                                                                        if(!(IokeObject.dataOf(arg) is Number)) {
                                                                                            arg = IokeObject.ConvertToNumber(arg, message, context);
                                                                                        }
                                                                                        int index = ((Number)IokeObject.dataOf(arg)).AsNativeInteger();
                                                                                        var o2 = ((IokeList)IokeObject.dataOf(on)).List;
                                                                                        if(index < 0) {
                                                                                            index = o2.Count + index;
                                                                                        }

                                                                                        if(index >= 0 && index < o2.Count) {
                                                                                            return o2[index];
                                                                                        } else {
                                                                                            return context.runtime.nil;
                                                                                        }
                                                                                    })));
            obj.AliasMethod("at", "[]", null, null);

            obj.RegisterMethod(runtime.NewNativeMethod("returns the size of this list",
                                                       new TypeCheckingNativeMethod.WithNoArguments("size", runtime.List,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        return context.runtime.NewNumber(((IokeList)IokeObject.dataOf(on)).List.Count);
                                                                                                    })));
            obj.AliasMethod("size", "length", null, null);

            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(IokeList.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(IokeList.GetNotice(on));
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("Compares this object against the argument. The comparison is only based on the elements inside the lists, which are in turn compared using <=>.",
                                                       new TypeCheckingNativeMethod("<=>", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        var one = IokeList.GetList(on);
                                                                                        object arg = args[0];
                                                                                        if(!(IokeObject.dataOf(arg) is IokeList)) {
                                                                                            return context.runtime.nil;
                                                                                        }
                                                                                        var two = IokeList.GetList(arg);

                                                                                        int len = Math.Min(one.Count, two.Count);
                                                                                        SpaceshipComparator sc = new SpaceshipComparator(context, message);

                                                                                        for(int i = 0; i < len; i++) {
                                                                                            int v = sc.Compare(one[i], two[i]);
                                                                                            if(v != 0) {
                                                                                                return context.runtime.NewNumber(v);
                                                                                            }
                                                                                        }

                                                                                        len = one.Count - two.Count;

                                                                                        if(len == 0) return context.runtime.NewNumber(0);
                                                                                        if(len > 0) return context.runtime.NewNumber(1);
                                                                                        return context.runtime.NewNumber(-1);
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes one argument and adds it at the end of the list, and then returns the list",
                                                       new TypeCheckingNativeMethod("<<", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("value")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        IokeList.Add(on, args[0]);
                                                                                        return on;
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes one argument and adds it at the end of the list, and then returns the list",
                                                       new TypeCheckingNativeMethod("append!", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("value")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        object value = args[0];
                                                                                        IokeList.Add(on, value);
                                                                                        return on;
                                                                                    })));

            obj.AliasMethod("append!", "push!", null, null);

            obj.RegisterMethod(runtime.NewNativeMethod("takes one argument and adds it at the beginning of the list, and then returns the list",
                                                       new TypeCheckingNativeMethod("prepend!", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("value")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        object value = args[0];
                                                                                        IokeList.Add(on, 0, value);
                                                                                        return on;
                                                                                    })));

            obj.AliasMethod("prepend!", "unshift!", null, null);

            obj.RegisterMethod(runtime.NewNativeMethod("removes the last element from the list and returns it. returns nil if the list is empty.",
                                                       new TypeCheckingNativeMethod.WithNoArguments("pop!", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        var l = ((IokeList)IokeObject.dataOf(on)).List;
                                                                                                        if(l.Count == 0) {
                                                                                                            return context.runtime.nil;
                                                                                                        }
                                                                                                        object result = l[l.Count-1];
                                                                                                        l.RemoveAt(l.Count-1);
                                                                                                        return result;
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("removes the first element from the list and returns it. returns nil if the list is empty.",
                                                       new TypeCheckingNativeMethod.WithNoArguments("shift!", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        var l = ((IokeList)IokeObject.dataOf(on)).List;
                                                                                                        if(l.Count == 0) {
                                                                                                            return context.runtime.nil;
                                                                                                        }
                                                                                                        object result = l[0];
                                                                                                        l.RemoveAt(0);
                                                                                                        return result;
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("will remove all the entries from the list, and then returns the list",
                                                       new TypeCheckingNativeMethod.WithNoArguments("clear!", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        ((IokeList)IokeObject.dataOf(on)).List.Clear();
                                                                                                        return on;
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if this list is empty, false otherwise",
                                                       new TypeCheckingNativeMethod.WithNoArguments("empty?", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        return ((IokeList)IokeObject.dataOf(on)).List.Count == 0 ? 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 ((IokeList)IokeObject.dataOf(on)).List.Contains(args[0]) ? context.runtime.True : context.runtime.False;
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("adds the elements in the argument list to the current list, and then returns that list",
                                                       new TypeCheckingNativeMethod("concat!", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("otherList").WhichMustMimic(obj)
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        var l = ((IokeList)IokeObject.dataOf(on)).List;
                                                                                        var l2 = ((IokeList)IokeObject.dataOf(args[0])).List;
                                                                                        foreach(object x in l2) l.Add(x);
                                                                                        return on;
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a new list that contains the receivers elements and the elements of the list sent in as the argument.",
                                                       new TypeCheckingNativeMethod("+", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("otherList").WhichMustMimic(obj)
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        var newList = new SaneArrayList();
                                                                                        newList.AddRange(((IokeList)IokeObject.dataOf(on)).List);
                                                                                        newList.AddRange(((IokeList)IokeObject.dataOf(args[0])).List);
                                                                                        return context.runtime.NewList(newList, IokeObject.As(on, context));
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a new list that contains all the elements from the receivers list, except for those that are in the argument list",
                                                       new TypeCheckingNativeMethod("-", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("otherList").WhichMustMimic(obj)
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        var newList = new SaneArrayList();
                                                                                        var l = ((IokeList)IokeObject.dataOf(args[0])).List;
                                                                                        foreach(object x in ((IokeList)IokeObject.dataOf(on)).List) {
                                                                                            if(!l.Contains(x)) {
                                                                                                newList.Add(x);
                                                                                            }
                                                                                        }
                                                                                        return context.runtime.NewList(newList, IokeObject.As(on, context));
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a new sorted version of this list",
                                                       new TypeCheckingNativeMethod.WithNoArguments("sort", obj,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        object newList = IokeObject.Mimic(on, message, context);
                                                                                                        var ll = ((IokeList)IokeObject.dataOf(newList)).List;
                                                                                                        if(ll is ArrayList) {
                                                                                                            ((ArrayList)ll).Sort(new SpaceshipComparator(context, message));
                                                                                                        } else {
                                                                                                            ArrayList second = new SaneArrayList(ll);
                                                                                                            ((ArrayList)second).Sort(new SpaceshipComparator(context, message));
                                                                                                            ((IokeList)IokeObject.dataOf(newList)).List = second;
                                                                                                        }
                                                                                                        return newList;
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("sorts this list in place and then returns it",
                                                       new TypeCheckingNativeMethod.WithNoArguments("sort!", obj,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        var ll = ((IokeList)IokeObject.dataOf(on)).List;
                                                                                                        if(ll is ArrayList) {
                                                                                                            ((ArrayList)ll).Sort(new SpaceshipComparator(context, message));
                                                                                                        } else {
                                                                                                            ArrayList second = new SaneArrayList(ll);
                                                                                                            ((ArrayList)second).Sort(new SpaceshipComparator(context, message));
                                                                                                            ((IokeList)IokeObject.dataOf(on)).List = second;
                                                                                                        }
                                                                                                        return on;
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes an index and zero or more objects to insert at that point. the index can be negative to index from the end of the list. if the index is positive and larger than the size of the list, the list will be filled with nils inbetween.",
                                                       new TypeCheckingNativeMethod("insert!", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("index").WhichMustMimic(runtime.Number)
                                                                                    .WithRest("objects")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        int index = ((Number)IokeObject.dataOf(args[0])).AsNativeInteger();
                                                                                        var l = ((IokeList)IokeObject.dataOf(on)).List;
                                                                                        int size = l.Count;
                                                                                        if(index < 0) {
                                                                                            index = size + index + 1;
                                                                                        }

                                                                                        if(args.Count>1) {
                                                                                            while(index < 0) {
                                                                                                IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                                                                                             message,
                                                                                                                                                             context,
                                                                                                                                                             "Error",
                                                                                                                                                             "Index"), context).Mimic(message, context);
                                                                                                condition.SetCell("message", message);
                                                                                                condition.SetCell("context", context);
                                                                                                condition.SetCell("receiver", on);
                                                                                                condition.SetCell("index", context.runtime.NewNumber(index));

                                                                                                object[] newCell = new object[]{context.runtime.NewNumber(index)};

                                                                                                context.runtime.WithRestartReturningArguments(()=>{context.runtime.ErrorCondition(condition);},
                                                                                                                                              context,
                                                                                                                                              new IokeObject.UseValue("index", newCell));

                                                                                                index = Number.ExtractInt(newCell[0], message, context);
                                                                                                if(index < 0) {
                                                                                                    index = size + index;
                                                                                                }
                                                                                            }

                                                                                            for(int x = (index-size); x>0; x--) {
                                                                                                l.Add(context.runtime.nil);
                                                                                            }

                                                                                            for(int i=1, j=args.Count; i<j; i++) l.Insert(index + i - 1, args[i]);
                                                                                        }

                                                                                        return on;
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes two arguments, the index of the element to set, and the value to set. the index can be negative and will in that case set indexed from the end of the list. if the index is larger than the current size, the list will be expanded with nils. an exception will be raised if a abs(negative index) is larger than the size.",
                                                       new TypeCheckingNativeMethod("at=", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRequiredPositional("index")
                                                                                    .WithRequiredPositional("value")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        object arg = args[0];
                                                                                        object value = args[1];
                                                                                        if(!(IokeObject.dataOf(arg) is Number)) {
                                                                                            arg = IokeObject.ConvertToNumber(arg, message, context);
                                                                                        }
                                                                                        int index = ((Number)IokeObject.dataOf(arg)).AsNativeInteger();
                                                                                        var o = ((IokeList)IokeObject.dataOf(on)).List;
                                                                                        if(index < 0) {
                                                                                            index = o.Count + index;
                                                                                        }

                                                                                        while(index < 0) {
                                                                                            IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                                                                                         message,
                                                                                                                                                         context,
                                                                                                                                                         "Error",
                                                                                                                                                         "Index"), context).Mimic(message, context);
                                                                                            condition.SetCell("message", message);
                                                                                            condition.SetCell("context", context);
                                                                                            condition.SetCell("receiver", on);
                                                                                            condition.SetCell("index", context.runtime.NewNumber(index));

                                                                                            object[] newCell = new object[]{context.runtime.NewNumber(index)};

                                                                                            context.runtime.WithRestartReturningArguments(()=>{context.runtime.ErrorCondition(condition);},
                                                                                                                                          context,
                                                                                                                                          new IokeObject.UseValue("index", newCell));

                                                                                            index = Number.ExtractInt(newCell[0], message, context);
                                                                                            if(index < 0) {
                                                                                                index = o.Count + index;
                                                                                            }
                                                                                        }

                                                                                        if(index >= o.Count) {
                                                                                            int toAdd = (index-o.Count) + 1;
                                                                                            for(int i=0;i<toAdd;i++) {
                                                                                                o.Add(context.runtime.nil);
                                                                                            }
                                                                                        }

                                                                                        o[(int)index] = value;

                                                                                        return value;
                                                                                    })));

            obj.AliasMethod("at=", "[]=", null, null);

            obj.RegisterMethod(runtime.NewNativeMethod(
                                                     "takes as argument the index of the element to be removed and returns it. can be " +
                                                     "negative and will in that case index from the back of the list. if the index is " +
                                                     "outside the bounds of the list, will return nil. the argument can also be a range, " +
                                                     "and will in that case remove the sublist beginning at the first index and extending " +
                                                     "to the position in the list specified by the second index (inclusive or exclusive " +
                                                     "depending on the range). the end of the range can be negative and will in that case " +
                                                     "index from the back of the list. if the start of the range is negative, or greater " +
                                                     "than the end, an empty list will be returned. if the end index exceeds the bounds " +
                                                     "of the list, its size will be used instead.",
                                                     new TypeCheckingNativeMethod("removeAt!", TypeCheckingArgumentsDefinition.builder()
                                                                                  .ReceiverMustMimic(obj)
                                                                                  .WithRequiredPositional("indexOrRange")
                                                                                  .Arguments,
                                                                                  (method, on, args, keywords, context, message) => {
                                                                                      object arg = args[0];

                                                                                      if(IokeObject.dataOf(arg) is Range) {
                                                                                          int first = Number.ExtractInt(Range.GetFrom(arg), message, context);
                                                                                          if(first < 0) {
                                                                                              return EmptyList(context);
                                                                                          }

                                                                                          int last = Number.ExtractInt(Range.GetTo(arg), message, context);
                                                                                          var receiver = GetList(on);
                                                                                          int size = receiver.Count;

                                                                                          if(last < 0) {
                                                                                              last = size + last;
                                                                                          }

                                                                                          if(last < 0) {
                                                                                              return EmptyList(context);
                                                                                          }

                                                                                          bool inclusive = Range.IsInclusive(arg);

                                                                                          if(last >= size) {
                                                                                              last = inclusive ? size-1 : size;
                                                                                          }

                                                                                          if(first > last || (!inclusive && first == last)) {
                                                                                              return EmptyList(context);
                                                                                          }

                                                                                          if(!inclusive) {
                                                                                              last--;
                                                                                          }

                                                                                          var result = new SaneArrayList();
                                                                                          for(int i = 0; i <= last - first; i++) {
                                                                                              result.Add(receiver[first]);
                                                                                              receiver.RemoveAt(first);
                                                                                          }

                                                                                          return CopyList(context, result);
                                                                                      }

                                                                                      if(!(IokeObject.dataOf(arg) is Number)) {
                                                                                          arg = IokeObject.ConvertToNumber(arg, message, context);
                                                                                      }

                                                                                      int index = ((Number)IokeObject.dataOf(arg)).AsNativeInteger();
                                                                                      var receiver2 = GetList(on);
                                                                                      int size2 = receiver2.Count;

                                                                                      if(index < 0) {
                                                                                          index = size2 + index;
                                                                                      }

                                                                                      if(index >= 0 && index < size2) {
                                                                                          object result = receiver2[(int)index];
                                                                                          receiver2.RemoveAt((int)index);
                                                                                          return result;
                                                                                      } else {
                                                                                          return context.runtime.nil;
                                                                                      }
                                                                                  })));

            obj.RegisterMethod(runtime.NewNativeMethod(
                                                     "takes one or more arguments. removes all occurrences of the provided arguments from " +
                                                     "the list and returns the updated list. if an argument is not contained, the list " +
                                                     "remains unchanged. sending this method to an empty list has no effect.",
                                                     new TypeCheckingNativeMethod("remove!", TypeCheckingArgumentsDefinition.builder()
                                                                                  .ReceiverMustMimic(obj)
                                                                                  .WithRequiredPositional("element")
                                                                                  .WithRest("elements")
                                                                                  .Arguments,
                                                                                  (method, on, args, keywords, context, message) => {
                                                                                      var receiver = GetList(on);
                                                                                      if(receiver.Count == 0) {
                                                                                          return on;
                                                                                      }
                                                                                      foreach(object o in args) {
                                                                                          for(int i = 0, j=receiver.Count; i<j; i++) {
                                                                                              if(o.Equals(receiver[i])) {
                                                                                                  receiver.RemoveAt(i);
                                                                                                  i--;
                                                                                                  j--;
                                                                                              }
                                                                                          }
                                                                                      }
                                                                                      return on;
                                                                                  })));

            obj.RegisterMethod(runtime.NewNativeMethod(
                                                     "takes one or more arguments. removes the first occurrence of the provided arguments " +
                                                     "from the list and returns the updated list. if an argument is not contained, the list " +
                                                     "remains unchanged. arguments that are provided multiple times are treated as distinct " +
                                                     "elements. sending this message to an empty list has no effect.",
                                                     new TypeCheckingNativeMethod("removeFirst!", TypeCheckingArgumentsDefinition.builder()
                                                                                  .ReceiverMustMimic(obj)
                                                                                  .WithRequiredPositional("element")
                                                                                  .WithRest("elements")
                                                                                  .Arguments,
                                                                                  (method, on, args, keywords, context, message) => {
                                                                                      var receiver = GetList(on);
                                                                                      if(receiver.Count == 0) {
                                                                                          return on;
                                                                                      }
                                                                                      foreach(object o in args) {
                                                                                          receiver.Remove(o);
                                                                                      }
                                                                                      return on;
                                                                                  })));

            obj.RegisterMethod(runtime.NewNativeMethod("removes all nils in this list, and then returns the list",
                                                       new TypeCheckingNativeMethod.WithNoArguments("compact!", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        var list = GetList(on);
                                                                                                        var newList = new SaneArrayList();
                                                                                                        object nil = context.runtime.nil;
                                                                                                        foreach(object o in list) {
                                                                                                            if(o != nil) {
                                                                                                                newList.Add(o);
                                                                                                            }
                                                                                                        }
                                                                                                        SetList(on, newList);
                                                                                                        return on;
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("reverses the elements in this list, then returns it",
                                                       new TypeCheckingNativeMethod.WithNoArguments("reverse!", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        var list = GetList(on);
                                                                                                        if(list is ArrayList) {
                                                                                                            ((ArrayList)list).Reverse();
                                                                                                        } else {
                                                                                                            ArrayList list2 = new SaneArrayList(list);
                                                                                                            list2.Reverse();
                                                                                                            SetList(on, list2);
                                                                                                        }
                                                                                                        return on;
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("flattens all lists in this list recursively, then returns it",
                                                       new TypeCheckingNativeMethod.WithNoArguments("flatten!", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                                                                                                        SetList(on, Flatten(GetList(on)));
                                                                                                        return on;
                                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a text composed of the asText representation of all elements in the list, separated by the separator. the separator defaults to an empty text.",
                                                       new TypeCheckingNativeMethod("join", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithOptionalPositional("separator", "")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                                                                                        var list = GetList(on);
                                                                                        string result;
                                                                                        if(list.Count == 0) {
                                                                                            result = "";
                                                                                        } else {
                                                                                            string sep = args.Count > 0 ? Text.GetText(args[0]) : "";
                                                                                            StringBuilder sb = new StringBuilder();
                                                                                            Join(list, sb, sep, context.runtime.asText, context);
                                                                                            result = sb.ToString();
                                                                                        }
                                                                                        return context.runtime.NewText(result);
                                                                                    })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes one or two arguments, and will then use these arguments as code to transform each element in this list. the transform happens in place. finally the method will return the receiver.",
                                                       new NativeMethod("map!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositionalUnevaluated("argOrCode")
                                                                        .WithOptionalPositionalUnevaluated("code")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                                                                            outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                                                                            object onAsList = context.runtime.List.ConvertToThis(on, message, context);

                                                                            var ls = ((IokeList)IokeObject.dataOf(onAsList)).list;
                                                                            int size = ls.Count;

                                                                            switch(message.Arguments.Count) {
                                                                            case 1: {
                                                                                IokeObject code = IokeObject.As(message.Arguments[0], context);

                                                                                for(int i = 0; i<size; i++) {
                                                                                    ls[i] = context.runtime.interpreter.Evaluate(code, context, context.RealContext, ls[i]);
                                                                                }
                                                                                break;
                                                                            }
                                                                            case 2: {
                                                                                IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for List#map!", context);
                                                                                string name = IokeObject.As(message.Arguments[0], context).Name;
                                                                                IokeObject code = IokeObject.As(message.Arguments[1], context);

                                                                                for(int i = 0; i<size; i++) {
                                                                                    c.SetCell(name, ls[i]);
                                                                                    ls[i] = context.runtime.interpreter.Evaluate(code, c, c.RealContext, c);
                                                                                }
                                                                                break;
                                                                            }
                                                                            }
                                                                            return on;
                                                                        })));

            obj.AliasMethod("map!", "collect!", null, null);

            obj.RegisterMethod(runtime.NewNativeMethod("takes one or two arguments, and will then use these arguments as code to decide what elements should be removed from the list. the method will return the receiver.",
                                                       new NativeMethod("removeIf!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositionalUnevaluated("argOrCode")
                                                                        .WithOptionalPositionalUnevaluated("code")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                                                                            outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                                                                            object onAsList = context.runtime.List.ConvertToThis(on, message, context);

                                                                            var ls = ((IokeList)IokeObject.dataOf(onAsList)).list;

                                                                            switch(message.Arguments.Count) {
                                                                            case 1: {
                                                                                IokeObject code = IokeObject.As(message.Arguments[0], context);

                                                                                int count = ls.Count;
                                                                                for(int i = 0; i<count; i++) {
                                                                                    object o1 = ls[i];
                                                                                    if(IokeObject.IsObjectTrue(context.runtime.interpreter.Evaluate(code, context, context.RealContext, o1))) {
                                                                                        ls.RemoveAt(i);
                                                                                        i--;
                                                                                        count--;
                                                                                    }
                                                                                }
                                                                                break;
                                                                            }
                                                                            case 2: {
                                                                                IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for List#removeIf!", context);
                                                                                string name = IokeObject.As(message.Arguments[0], context).Name;
                                                                                IokeObject code = IokeObject.As(message.Arguments[1], context);

                                                                                int count = ls.Count;
                                                                                for(int i = 0; i<count; i++) {
                                                                                    object o2 = ls[i];
                                                                                    c.SetCell(name, o2);
                                                                                    if(IokeObject.IsObjectTrue(context.runtime.interpreter.Evaluate(code, c, c.RealContext, c))) {
                                                                                        ls.RemoveAt(i);
                                                                                        i--;
                                                                                        count--;
                                                                                    }
                                                                                }
                                                                                break;
                                                                            }
                                                                            }
                                                                            return on;
                                                                        })));
        }
Ejemplo n.º 30
0
        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 = Message.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 = Message.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 {
                                                                                        sb.Append(Text.GetText(((Message)IokeObject.dataOf(context.runtime.asText)).SendTo(context.runtime.asText, context, o)));
                                                                                    }
                                                                                } 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 = Message.GetEvaluatedArgument(o, context);
                                                                            }
                                                                            if(o2 is IokeObject) {
                                                                                o2 = Message.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 = Message.GetEvaluatedArgument(o, context);
                                                                        }
                                                                        object value = runtime.NewDecimal((string)o);
                                                                        if(cache) {
                                                                            Message.CacheValue(message, value);
                                                                        }
                                                                        return value;
                                                                    })));
        }