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] = Interpreter.GetEvaluatedArgument(((Message)IokeObject.dataOf(o)).next, context);
                }
                else if (Message.HasName(o, "*") && IokeObject.As(o, context).Arguments.Count == 1)    // Splat
                {
                    object result = Interpreter.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((IokeObject)result, "asTuple") != runtime.nul)
                    {
                        object   tupledValue = Interpreter.Send(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
                {
                    var xx = Interpreter.GetEvaluatedArgument(o, context);
                    argumentsWithoutKeywords.Add(xx);
                    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);
        }
        public static DefaultArgumentsDefinition CreateFrom(IList args, int start, int end, IokeObject message, object on, IokeObject context)
        {
            Runtime          runtime   = context.runtime;
            IList <Argument> arguments = new SaneList <Argument>();
            IList <string>   keywords  = new SaneList <string>();

            int    min         = 0;
            int    max         = 0;
            bool   hadOptional = false;
            string rest        = null;
            string krest       = null;

            foreach (object obj in ArrayList.Adapter(args).GetRange(start, end - start))
            {
                Message m     = (Message)IokeObject.dataOf(obj);
                string  mname = m.Name;
                if (!"+:".Equals(mname) && m.IsKeyword())
                {
                    string     name   = mname;
                    IokeObject dValue = context.runtime.nilMessage;
                    if (m.next != null)
                    {
                        dValue = m.next;
                    }
                    arguments.Add(new KeywordArgument(name.Substring(0, name.Length - 1), dValue));
                    keywords.Add(name);
                }
                else if (mname.Equals("+"))
                {
                    string name = Message.GetName(m.Arguments(null)[0]);
                    if (name.StartsWith(":"))
                    {
                        krest = name.Substring(1);
                    }
                    else
                    {
                        rest = name;
                        max  = -1;
                    }
                    hadOptional = true;
                }
                else if (mname.Equals("+:"))
                {
                    string name = m.next != null?Message.GetName(m.next) : Message.GetName(m.Arguments(null)[0]);

                    krest       = name;
                    hadOptional = true;
                }
                else if (m.next != null)
                {
                    string name = mname;
                    hadOptional = true;
                    if (max != -1)
                    {
                        max++;
                    }
                    arguments.Add(new OptionalArgument(name, m.next));
                }
                else
                {
                    if (hadOptional)
                    {
                        int index = IndexOf(args, obj) + start;

                        IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                                     message,
                                                                                     context,
                                                                                     "Error",
                                                                                     "Invocation",
                                                                                     "ArgumentWithoutDefaultValue"), context).Mimic(message, context);
                        condition.SetCell("message", message);
                        condition.SetCell("context", context);
                        condition.SetCell("receiver", on);
                        condition.SetCell("argumentName", runtime.GetSymbol(m.Name));
                        condition.SetCell("index", runtime.NewNumber(index));

                        IList newValue = IokeList.GetList(runtime.WithRestartReturningArguments(() => { runtime.ErrorCondition(condition); },
                                                                                                context,
                                                                                                new NewArgumentGivingRestart("provideDefaultValue", "defaultValue"),
                                                                                                new Restart.DefaultValuesGivingRestart("substituteNilDefault", runtime.nil, 1)));
                        if (max != -1)
                        {
                            max++;
                        }

                        arguments.Add(new OptionalArgument(m.Name, runtime.CreateMessage(Message.Wrap(IokeObject.As(newValue[0], context)))));
                    }
                    else
                    {
                        min++;
                        max++;
                        arguments.Add(new Argument(IokeObject.As(obj, context).Name));
                    }
                }
            }

            return(new DefaultArgumentsDefinition(arguments, keywords, rest, krest, min, max, false));
        }
Exemple #3
0
 public void AddArgument(string newArgument)
 {
     IokeList.GetList(programArguments).Add(programArguments.runtime.NewText(newArgument));
 }
Exemple #4
0
 public void AddLoadPath(string newPath)
 {
     IokeList.GetList(loadPath).Add(loadPath.runtime.NewText(newPath));
 }
Exemple #5
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);
            })));
        }
Exemple #6
0
        public override void Init(IokeObject obj)
        {
            obj.Kind = "LexicalBlock";

            obj.RegisterMethod(obj.runtime.NewNativeMethod("takes two evaluated arguments, where this first one is a list of messages which will be used as the arguments and the code, and the second is the context where this lexical scope should be created in",
                                                           new NativeMethod("createFrom", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("messageList")
                                                                            .WithRequiredPositional("lexicalContext")
                                                                            .Arguments,
                                                                            (method, _context, _message, on, outer) => {
                Runtime runtime    = _context.runtime;
                var positionalArgs = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(_context, _message, on, positionalArgs, new SaneDictionary <string, object>());
                var args          = IokeList.GetList(positionalArgs[0]);
                IokeObject ground = IokeObject.As(positionalArgs[1], _context);

                IokeObject code = IokeObject.As(args[args.Count - 1], _context);

                DefaultArgumentsDefinition def = DefaultArgumentsDefinition.CreateFrom(args, 0, args.Count - 1, _message, on, _context);
                return(runtime.NewLexicalBlock(null, runtime.LexicalBlock, new LexicalBlock(ground, def, code)));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("invokes the block with the arguments provided, returning the result of the last expression in the block",
                                                           new NativeMethod("call", DefaultArgumentsDefinition.builder()
                                                                            .WithRestUnevaluated("arguments")
                                                                            .Arguments,
                                                                            (method, _context, _message, on, outer) => {
                return(Interpreter.Activate(IokeObject.As(on, _context), _context, _message, on));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the full code of this lexical block, as a Text",
                                                           new TypeCheckingNativeMethod.WithNoArguments("code", obj,
                                                                                                        (method, on, args, keywords, _context, _message) => {
                IokeObject objx = IokeObject.As(on, _context);
                string x        = objx.IsActivatable ? "x" : "";

                string argstr = ((LexicalBlock)IokeObject.dataOf(on)).arguments.GetCode();
                return(_context.runtime.NewText("fn" + x + "(" + argstr + Message.Code(((LexicalBlock)IokeObject.dataOf(on)).message) + ")"));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the code for the argument definition",
                                                           new TypeCheckingNativeMethod.WithNoArguments("argumentsCode", obj,
                                                                                                        (method, on, args, keywords, _context, _message) => {
                return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).ArgumentsCode));
            })));

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

                foreach (string keyword in ((LexicalBlock)IokeObject.dataOf(on)).arguments.Keywords)
                {
                    keywordList.Add(_context.runtime.GetSymbol(keyword.Substring(0, keyword.Length - 1)));
                }

                return(_context.runtime.NewList(keywordList));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a list of the argument names the positional arguments this block takes",
                                                           new TypeCheckingNativeMethod.WithNoArguments("argumentNames", obj,
                                                                                                        (method, on, args, keywords, _context, _message) => {
                var names = new SaneArrayList();

                foreach (var arg in ((LexicalBlock)IokeObject.dataOf(on)).arguments.Arguments)
                {
                    if (!(arg is DefaultArgumentsDefinition.KeywordArgument))
                    {
                        names.Add(_context.runtime.GetSymbol(arg.Name));
                    }
                }

                return(_context.runtime.NewList(names));
            })));
            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the message chain for this block",
                                                           new TypeCheckingNativeMethod.WithNoArguments("message", obj,
                                                                                                        (method, on, args, keywords, _context, _message) => {
                return(((AssociatedCode)IokeObject.dataOf(on)).Code);
            })));

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

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

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns idiomatically formatted code for this lexical block",
                                                           new TypeCheckingNativeMethod.WithNoArguments("formattedCode", obj,
                                                                                                        (method, on, args, keywords, _context, message) => {
                return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).FormattedCode(method)));
            })));
        }
Exemple #7
0
        private static int FormatString(string format, int index, IokeObject message, IokeObject context, IList positionalArgs, StringBuilder result)
        {
            int           argIndex        = 0;
            int           formatIndex     = index;
            int           justify         = 0;
            bool          splat           = false;
            bool          splatPairs      = false;
            bool          negativeJustify = false;
            bool          doAgain         = false;
            int           formatLength    = format.Length;
            object        arg             = null;
            StringBuilder missingText     = new StringBuilder();
            object        seq             = null;
            IList         args            = null;

            while (formatIndex < formatLength)
            {
                char c = format[formatIndex++];
                switch (c)
                {
                case '%':
                    justify = 0;
                    missingText.Append(c);
                    do
                    {
                        doAgain = false;
                        if (formatIndex < formatLength)
                        {
                            c = format[formatIndex++];
                            missingText.Append(c);

                            switch (c)
                            {
                            case '*':
                                splat   = true;
                                doAgain = true;
                                break;

                            case ':':
                                splatPairs = true;
                                doAgain    = true;
                                break;

                            case ']':
                                return(formatIndex);

                            case '[':
                                arg = positionalArgs[argIndex++];
                                int endLoop = -1;

                                seq = Interpreter.Send(context.runtime.seqMessage, context, arg);

                                while (IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.nextPMessage, context, seq)))
                                {
                                    object receiver = Interpreter.Send(context.runtime.nextMessage, context, seq);

                                    if (splat)
                                    {
                                        args = IokeList.GetList(receiver);
                                    }
                                    else if (splatPairs)
                                    {
                                        args = new SaneArrayList()
                                        {
                                            Pair.GetFirst(receiver), Pair.GetSecond(receiver)
                                        };
                                    }
                                    else
                                    {
                                        args = new SaneArrayList()
                                        {
                                            receiver
                                        };
                                    }

                                    int newVal = FormatString(format, formatIndex, message, context, args, result);
                                    endLoop = newVal;
                                }

                                splat      = false;
                                splatPairs = false;

                                if (endLoop == -1)
                                {
                                    int opened = 1;
                                    while (opened > 0 && formatIndex < formatLength)
                                    {
                                        char c2 = format[formatIndex++];
                                        if (c2 == '%' && formatIndex < formatLength)
                                        {
                                            c2 = format[formatIndex++];
                                            if (c2 == '[')
                                            {
                                                opened++;
                                            }
                                            else if (c2 == ']')
                                            {
                                                opened--;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    formatIndex = endLoop;
                                }
                                break;

                            case 's':
                                arg = positionalArgs[argIndex++];
                                object txt = IokeObject.TryConvertToText(arg, message, context);
                                if (txt == null)
                                {
                                    txt = Interpreter.Send(context.runtime.asText, context, arg);
                                }
                                string outTxt = Text.GetText(txt);

                                if (outTxt.Length < justify)
                                {
                                    int    missing = justify - outTxt.Length;
                                    char[] spaces  = new char[missing];
                                    for (int ixx = 0; ixx < spaces.Length; ixx++)
                                    {
                                        spaces[ixx] = ' ';
                                    }
                                    if (negativeJustify)
                                    {
                                        result.Append(outTxt);
                                        result.Append(spaces);
                                    }
                                    else
                                    {
                                        result.Append(spaces);
                                        result.Append(outTxt);
                                    }
                                }
                                else
                                {
                                    result.Append(outTxt);
                                }
                                break;

                            case '0':
                            case '1':
                            case '2':
                            case '3':
                            case '4':
                            case '5':
                            case '6':
                            case '7':
                            case '8':
                            case '9':
                                justify *= 10;
                                justify += (c - '0');
                                doAgain  = true;
                                break;

                            case '-':
                                negativeJustify = !negativeJustify;
                                doAgain         = true;
                                break;

                            default:
                                result.Append(missingText);
                                missingText = new StringBuilder();
                                break;
                            }
                        }
                        else
                        {
                            result.Append(missingText);
                            missingText = new StringBuilder();
                        }
                    } while(doAgain);
                    break;

                default:
                    result.Append(c);
                    break;
                }
            }
            return(formatLength);
        }