Example #1
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)));
            })));
        }
Example #2
0
        private IList ParseCommaSeparatedMessageChains()
        {
            ArrayList chain = new SaneArrayList();

            IokeObject curr = ParseMessageChain();

            while (curr != null)
            {
                chain.Add(curr);
                ReadWhiteSpace();
                int rr = Peek();
                if (rr == ',')
                {
                    Read();
                    curr = ParseMessageChain();
                    if (curr == null)
                    {
                        Fail("Expected expression following comma");
                    }
                }
                else
                {
                    if (curr != null && Message.IsTerminator(curr) && Message.GetNext(curr) == null)
                    {
                        chain.RemoveAt(chain.Count - 1);
                    }
                    curr = null;
                }
            }

            return(chain);
        }
Example #3
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));
        }
        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);
        }
Example #5
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));
        }
Example #6
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));
            }
Example #7
0
        public static IList GetEvaluatedArguments(IokeObject self, IokeObject context)
        {
            IList arguments = self.Arguments;
            IList args      = new SaneArrayList(arguments.Count);

            foreach (object o in arguments)
            {
                args.Add(GetEvaluatedArgument(o, context));
            }
            return(args);
        }
Example #8
0
File: Hook.cs Project: tspring/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);
            })));
        }
 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);
     }
 }
Example #10
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(Interpreter.Send(runtime.asText, context, args[0]));
                if (FEATURES.Contains(name))
                {
                    return(runtime.True);
                }
                else
                {
                    return(runtime.False);
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the current file executing",
                                                       new NativeMethod.WithNoArguments("currentFile",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(runtime.NewText(((IokeSystem)IokeObject.dataOf(on)).currentFile[0]));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if running on windows, otherwise false",
                                                       new NativeMethod.WithNoArguments("windows?",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(DOSISH ? runtime.True : runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the current load path",
                                                       new NativeMethod.WithNoArguments("loadPath",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(((IokeSystem)IokeObject.dataOf(on)).loadPath);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a random number",
                                                       new NativeMethod.WithNoArguments("randomNumber",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(context.runtime.NewNumber(((IokeSystem)IokeObject.dataOf(on)).random.Next()));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the current working directory",
                                                       new NativeMethod.WithNoArguments("currentWorkingDirectory",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(context.runtime.NewText(context.runtime.CurrentWorkingDirectory));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the host name of the local machine",
                                                       new NativeMethod.WithNoArguments("hostName",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                string tt = System.Net.Dns.GetHostName();
                return(context.runtime.NewText(tt));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the current directory that the code is executing in",
                                                       new NativeMethod.WithNoArguments("currentDirectory",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                string name = Message.GetFile(message);
                FileInfo f  = null;
                if (IsAbsoluteFileName(name))
                {
                    f = new FileInfo(name);
                }
                else
                {
                    f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name));
                }

                if (f.Exists)
                {
                    return(context.runtime.NewText(f.Directory.FullName));
                }

                return(context.runtime.nil);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("forcibly exits the currently running interpreter. takes one optional argument that defaults to 1 - which is the value to return from the process, if the process is exited.",
                                                       new NativeMethod("exit", DefaultArgumentsDefinition.builder()
                                                                        .WithOptionalPositional("other", "1")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                int val = 1;
                if (args.Count > 0)
                {
                    object arg = args[0];
                    if (arg == context.runtime.True)
                    {
                        val = 0;
                    }
                    else if (arg == context.runtime.False)
                    {
                        val = 1;
                    }
                    else
                    {
                        val = Number.ExtractInt(arg, message, context);
                    }
                }
                throw new ControlFlow.Exit(val);
            })));

            obj.RegisterCell("programArguments", programArguments);

            obj.RegisterMethod(runtime.NewNativeMethod("returns result of evaluating first argument",
                                                       new NativeMethod("ifMain", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositionalUnevaluated("code")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                if (((IokeSystem)IokeObject.dataOf(on)).CurrentProgram.Equals(message.File))
                {
                    IokeObject msg = ((IokeObject)message.Arguments[0]);
                    return(context.runtime.interpreter.Evaluate(msg, context, context.RealContext, context));
                }
                else
                {
                    return(runtime.nil);
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("adds a new piece of code that should be executed on exit",
                                                       new NativeMethod("atExit", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositionalUnevaluated("code")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                GetAtExits(on).Add(new AtExitInfo(context, IokeObject.As(message.Arguments[0], context)));
                return(context.runtime.nil);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes one evaluated string argument and a boolean of whether loading should be forced or not. will import the file corresponding to the string based on the Ioke loading behavior",
                                                       new NativeMethod("lowLevelLoad!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("module")
                                                                        .WithRequiredPositional("forceReload")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                IList args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                bool forceReload = IokeObject.IsObjectTrue(args[1]);

                string name = Text.GetText(Interpreter.Send(runtime.asText, context, args[0]));
                if (((IokeSystem)IokeObject.dataOf(runtime.System)).Use(IokeObject.As(on, context), context, message, name, forceReload))
                {
                    return(runtime.True);
                }
                else
                {
                    return(runtime.False);
                }
            })));
        }
Example #11
0
        public bool Use(IokeObject self, IokeObject context, IokeObject message, string name, bool forceReload)
        {
            Runtime runtime = context.runtime;
            Builtin b       = context.runtime.GetBuiltin(name);

            if (b != null)
            {
                if (!forceReload && loaded.Contains(name))
                {
                    return(false);
                }
                else
                {
                    try {
                        b.Load(context.runtime, context, message);
                        if (!forceReload)
                        {
                            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 (!forceReload && loaded.Contains(f.FullName))
                        {
                            return(false);
                        }
                        else
                        {
                            context.runtime.EvaluateFile(f, message, context);
                        }
                        if (!forceReload)
                        {
                            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 (!forceReload && loaded.Contains(name + suffix))
                        {
                            return(false);
                        }
                        else
                        {
                            context.runtime.EvaluateStream(name + suffix, new StreamReader(s, System.Text.Encoding.UTF8), message, context);
                        }
                        if (!forceReload)
                        {
                            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 (!forceReload && loaded.Contains(f.FullName))
                            {
                                return(false);
                            }
                            else
                            {
                                context.runtime.EvaluateFile(f, message, context);
                                if (!forceReload)
                                {
                                    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 (!forceReload && loaded.Contains(name + suffix))
                            {
                                return(false);
                            }
                            else
                            {
                                context.runtime.EvaluateStream(name + suffix, new StreamReader(ss, System.Text.Encoding.UTF8), message, context);
                            }
                            if (!forceReload)
                            {
                                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);
        }
Example #12
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     = Interpreter.GetEvaluatedArgument(o, context);
                }
                if (o is string)
                {
                    string s     = (string)o;
                    object value = runtime.NewText(new StringUtils().ReplaceEscapes(s));
                    if (cache)
                    {
                        Message.CacheValue(message, value);
                    }
                    return(value);
                }
                else
                {
                    return(IokeObject.ConvertToText(o, message, context, true));
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("expects one 'strange' argument. creates a new instance of Number that represents the number found in the strange argument.",
                                                       new NativeMethod("internal:createNumber",
                                                                        DefaultArgumentsDefinition
                                                                        .builder()
                                                                        .WithRequiredPositionalUnevaluated("number")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                object o   = Message.GetArguments(message)[0];
                bool cache = true;

                if (o is IokeObject)
                {
                    cache = false;
                    o     = Interpreter.GetEvaluatedArgument(o, context);
                }
                object value = null;
                if (o is string)
                {
                    value = runtime.NewNumber((string)o);
                }
                else if (o is int)
                {
                    value = runtime.NewNumber((int)o);
                }

                if (cache)
                {
                    Message.CacheValue(message, value);
                }
                return(value);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes zero or more arguments, calls asText on non-text arguments, and then concatenates them and returns the result.",
                                                       new NativeMethod("internal:concatenateText", DefaultArgumentsDefinition.builder()
                                                                        .WithRest("textSegments")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                StringBuilder sb = new StringBuilder();

                foreach (object o in args)
                {
                    if (o is IokeObject)
                    {
                        if (IokeObject.dataOf(o) is Text)
                        {
                            sb.Append(Text.GetText(o));
                        }
                        else
                        {
                            var aa = Interpreter.Send(context.runtime.asText, context, o);
                            sb.Append(Text.GetText(aa));
                        }
                    }
                    else
                    {
                        sb.Append(o);
                    }
                }

                return(context.runtime.NewText(sb.ToString()));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes one or more arguments. it expects the last argument to be a text of flags, while the rest of the arguments are either texts or regexps or nil. if text, it will be inserted verbatim into the result regexp. if regexp it will be inserted into a group that make sure the flags of the regexp is preserved. if nil, nothing will be inserted.",
                                                       new NativeMethod("internal:compositeRegexp", DefaultArgumentsDefinition.builder()
                                                                        .WithRest("regexpSegments")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                StringBuilder sb = new StringBuilder();
                if ((IokeObject.dataOf(on) is Text) || (IokeObject.dataOf(on) is Regexp))
                {
                    AddObject(on, sb, context);
                }

                int size = args.Count;

                foreach (object o in ArrayList.Adapter(args).GetRange(0, size - 1))
                {
                    AddObject(o, sb, context);
                }

                object f     = args[size - 1];
                string flags = null;
                if (f is string)
                {
                    flags = (string)f;
                }
                else if (IokeObject.dataOf(f) is Text)
                {
                    flags = Text.GetText(f);
                }
                else if (IokeObject.dataOf(f) is Regexp)
                {
                    sb.Append(Regexp.GetPattern(f));
                    flags = Regexp.GetFlags(f);
                }

                return(context.runtime.NewRegexp(sb.ToString(), flags, context, message));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("expects two 'strange' arguments. creates a new mimic of Regexp with the given Java String backing it.",
                                                       new NativeMethod("internal:createRegexp", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositionalUnevaluated("regexp")
                                                                        .WithRequiredPositionalUnevaluated("flags")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                object o  = Message.GetArguments(message)[0];
                object o2 = Message.GetArguments(message)[1];
                if (o is IokeObject)
                {
                    o = Interpreter.GetEvaluatedArgument(o, context);
                }
                if (o2 is IokeObject)
                {
                    o2 = Interpreter.GetEvaluatedArgument(o2, context);
                }
                if (o is string)
                {
                    string s = (string)o;
                    return(runtime.NewRegexp(new StringUtils().ReplaceRegexpEscapes(s), (string)o2, context, message));
                }
                else
                {
                    return(IokeObject.ConvertToRegexp(o, message, context));
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("expects one 'strange' argument. creates a new instance of Decimal that represents the number found in the strange argument.",
                                                       new NativeMethod("internal:createDecimal", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositionalUnevaluated("decimal")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                object o   = Message.GetArguments(message)[0];
                bool cache = true;
                if (o is IokeObject)
                {
                    cache = false;
                    o     = Interpreter.GetEvaluatedArgument(o, context);
                }
                object value = runtime.NewDecimal((string)o);
                if (cache)
                {
                    Message.CacheValue(message, value);
                }
                return(value);
            })));
        }
Example #13
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).body), 16).ToUpper()));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a textual representation of the object called on.",
                                                       new NativeMethod.WithNoArguments("asText",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(method.runtime.NewText(on.ToString()));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if the evaluated argument is the same reference as the receiver, false otherwise.",
                                                       new NativeMethod("same?", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(IokeObject.Same(on, args[0]) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes the name of a message to send, and the arguments to give it. send should generally behave exactly as if you had sent the message itself - except that you can give a variable containing the name.",
                                                       new NativeMethod("send", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("messageName")
                                                                        .WithRestUnevaluated("arguments")
                                                                        .WithKeywordRestUnevaluated("keywordArguments")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                object _name = Interpreter.GetEvaluatedArgument(message, 0, context);
                string name  = Text.GetText(Interpreter.Send(runtime.asText, context, _name));

                IokeObject newMessage = Message.DeepCopy(message);
                newMessage.Arguments.RemoveAt(0);
                Message.SetName(newMessage, name);
                return(Interpreter.Send(newMessage, context, on));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns false if the left hand side is equal to the right hand side. exactly what this means depend on the object. the default behavior of Ioke objects is to only be equal if they are the same instance.",
                                                       new NativeMethod("!=", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(!IokeObject.Equals(on, Interpreter.GetEvaluatedArgument(message, 0, context)) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated Text argument and returns either true or false if this object or one of it's mimics have the kind of the name specified",
                                                       new TypeCheckingNativeMethod("kind?", TypeCheckingArgumentsDefinition.builder()
                                                                                    .WithRequiredPositional("name").WhichMustMimic(runtime.Text)
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                string kind = Text.GetText(args[0]);
                return(IokeObject.IsKind(on, kind, context) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and returns either true or false if this object or one of it's mimics mimics that argument. exactly the same as 'mimics?'",
                                                       new NativeMethod("is?", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("potentialMimic")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                IokeObject arg = IokeObject.As(args[0], context);
                return(IokeObject.IsMimic(on, arg, context) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a list of all the mimics of the receiver. it will not be the same list as is used to back the object, so modifications to this list will not show up in the object.",
                                                       new NativeMethod.WithNoArguments("mimics",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                var l = new SaneArrayList();
                foreach (object x in IokeObject.GetMimics(on, context))
                {
                    l.Add(x);
                }
                return(context.runtime.NewList(l));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("removes all mimics on the receiver, and returns the receiver",
                                                       new NativeMethod.WithNoArguments("removeAllMimics!",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                IokeObject.RemoveAllMimics(on, message, context);
                return(on);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("removes the argument mimic from the list of all mimics on the receiver. will do nothing if the receiver has no such mimic. it returns the receiver",
                                                       new NativeMethod("removeMimic!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("mimicToRemove")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                IokeObject.RemoveMimic(on, args[0], message, context);
                return(on);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and adds it to the list of mimics for the receiver. the receiver will be returned.",
                                                       new NativeMethod("mimic!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("newMimic")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                IokeObject newMimic = IokeObject.As(args[0], context);
                IokeObject.As(on, context).Mimics(newMimic, message, context);
                return(on);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and prepends it to the list of mimics for the receiver. the receiver will be returned.",
                                                       new NativeMethod("prependMimic!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("newMimic")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                IokeObject newMimic = IokeObject.As(args[0], context);
                IokeObject.As(on, context).Mimics(0, newMimic, message, context);
                return(on);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if the receiver is frozen, otherwise false",
                                                       new NativeMethod.WithNoArguments("frozen?",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(IokeObject.As(on, context).IsFrozen ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("ensures that the receiver is frozen",
                                                       new NativeMethod.WithNoArguments("freeze!",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                IokeObject.Freeze(on);
                return(on);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("ensures that the receiver is not frozen",
                                                       new NativeMethod.WithNoArguments("thaw!",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                IokeObject.Thaw(on);
                return(on);
            })));
        }
Example #14
0
        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));
            }
        }
Example #15
0
        public static void Init(IokeObject obj)
        {
            Runtime runtime = obj.runtime;

            obj.Kind = "DefaultBehavior Literals";

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument that is expected to be a Text, and returns the symbol corresponding to that text",
                                                       new NativeMethod(":", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("symbolText")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string sym = Text.GetText(Interpreter.Send(runtime.asText, context, args[0]));
                return(runtime.GetSymbol(sym));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and returns a new Pair of the receiver and the argument",
                                                       new NativeMethod("=>", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(context.runtime.NewPair(on, args[0]));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a new message with the name given as argument to this method.",
                                                       new NativeMethod("message", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("name")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                object o = args[0];

                string name = null;
                if (IokeObject.dataOf(o) is Text)
                {
                    name = Text.GetText(o);
                }
                else
                {
                    name = Text.GetText(Interpreter.Send(context.runtime.asText, context, o));
                }

                Message m      = new Message(context.runtime, name);
                IokeObject ret = context.runtime.CreateMessage(m);
                if (".".Equals(name))
                {
                    Message.SetIsTerminator(ret, true);
                }
                Message.CopySourceLocation(message, ret);
                return(ret);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("creates a new Set from the result of evaluating all arguments provided.",
                                                       new NativeMethod("set", DefaultArgumentsDefinition.builder()
                                                                        .WithRest("elements")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(context.runtime.NewSet(args));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("creates a new Dict from the arguments provided. these arguments can be two different things - either a keyword argument, or a pair. if it's a keyword argument, the entry added to the dict for it will be a symbol with the name from the keyword, without the ending colon. if it's not a keyword, it is expected to be an evaluated pair, where the first part of the pair is the key, and the second part is the value.",
                                                       new NativeMethod("dict", DefaultArgumentsDefinition.builder()
                                                                        .WithRest("pairs")
                                                                        .WithKeywordRest("keywordPairs")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                var arguments = message.Arguments;
                var moo       = new SaneHashtable(arguments.Count);

                foreach (object o in arguments)
                {
                    object key, value;
                    if (Message.IsKeyword(o))
                    {
                        string str = Message.GetName(o);
                        key        = context.runtime.GetSymbol(str.Substring(0, str.Length - 1));
                        if (Message.GetNext(o) != null)
                        {
                            value = Interpreter.GetEvaluatedArgument(Message.GetNext(o), context);
                        }
                        else
                        {
                            value = context.runtime.nil;
                        }
                    }
                    else
                    {
                        object result = Interpreter.GetEvaluatedArgument(o, context);
                        if ((result is IokeObject) && (IokeObject.dataOf(result) is Pair))
                        {
                            key   = Pair.GetFirst(result);
                            value = Pair.GetSecond(result);
                        }
                        else
                        {
                            key   = result;
                            value = context.runtime.nil;
                        }
                    }

                    moo[key] = value;
                }

                return(context.runtime.NewDict(moo));
            })));
        }
Example #16
0
        private static object RecursiveDestructuring(IList places, int numPlaces, IokeObject message, IokeObject context, object on, object toTuple)
        {
            object tupledValue = Interpreter.Send(context.runtime.asTuple, context, toTuple);

            object[] values    = Tuple.GetElements(tupledValue);
            int      numValues = values.Length;

            int min = System.Math.Min(numValues, numPlaces);

            bool hadEndingUnderscore = false;

            for (int i = 0; i < min; i++)
            {
                IokeObject m1   = IokeObject.As(places[i], context);
                string     name = m1.Name;
                if (name.Equals("_"))
                {
                    if (i == numPlaces - 1)
                    {
                        hadEndingUnderscore = true;
                    }
                }
                else
                {
                    if (m1.Arguments.Count == 0)
                    {
                        object value = values[i];

                        IokeObject.Assign(on, name, value, context, message);

                        if (value is IokeObject)
                        {
                            if ((IokeObject.dataOf(value) is Named) && ((Named)IokeObject.dataOf(value)).Name == null)
                            {
                                ((Named)IokeObject.dataOf(value)).Name = name;
                            }
                            else if (name.Length > 0 && char.IsUpper(name[0]) && !(IokeObject.As(value, context).HasKind))
                            {
                                if (on == context.runtime.Ground || on == context.runtime.IokeGround)
                                {
                                    IokeObject.As(value, context).Kind = name;
                                }
                                else
                                {
                                    IokeObject.As(value, context).Kind = IokeObject.As(on, context).GetKind(message, context) + " " + name;
                                }
                            }
                        }
                    }
                    else if (name.Equals(""))
                    {
                        var newArgs = m1.Arguments;
                        RecursiveDestructuring(newArgs, newArgs.Count, message, context, on, values[i]);
                    }
                    else
                    {
                        string newName   = name + "=";
                        IList  arguments = new SaneArrayList(m1.Arguments);
                        arguments.Add(context.runtime.CreateMessage(Message.Wrap(IokeObject.As(values[i], context))));
                        IokeObject msg = context.runtime.NewMessageFrom(message, newName, arguments);
                        Interpreter.Send(msg, context, on);
                    }
                }
            }

            if (numPlaces > min || (numValues > min && !hadEndingUnderscore))
            {
                IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                             message,
                                                                             context,
                                                                             "Error",
                                                                             "DestructuringMismatch"), context).Mimic(message, context);
                condition.SetCell("message", message);
                condition.SetCell("context", context);
                condition.SetCell("receiver", on);

                context.runtime.ErrorCondition(condition);
            }

            return(tupledValue);
        }
Example #17
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, IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0])));
                var result = new SaneArrayList();
                foreach (string s in dirs)
                {
                    result.Add(context.runtime.NewText(s));
                }
                return(context.runtime.NewList(result));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and returns true if it's the relative or absolute name of a directory, and false otherwise.",
                                                       new NativeMethod("directory?", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("directoryName")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name     = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0]));
                DirectoryInfo f = null;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    f = new DirectoryInfo(name);
                }
                else
                {
                    f = new DirectoryInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name));
                }

                return(f.Exists ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument that should be a file name, and returns a text of the contents of this file.",
                                                       new NativeMethod("readFully", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("fileName")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0]));
                FileInfo f  = null;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    f = new FileInfo(name);
                }
                else
                {
                    f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name));
                }

                return(context.runtime.NewText(File.ReadAllText(f.FullName)));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and returns true if it's the relative or absolute name of a file, and false otherwise.",
                                                       new NativeMethod("file?", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("fileName")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0]));
                FileInfo f  = null;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    f = new FileInfo(name);
                }
                else
                {
                    f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name));
                }

                return(f.Exists ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and returns true if it's the relative or absolute name of something that exists.",
                                                       new NativeMethod("exists?", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("entryName")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0]));
                string nx   = null;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    nx = name;
                }
                else
                {
                    nx = Path.Combine(context.runtime.CurrentWorkingDirectory, name);
                }

                return((new FileInfo(nx).Exists || new DirectoryInfo(nx).Exists) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument that should be the path of a file or directory, and returns the parent of it - or nil if there is no parent.",
                                                       new NativeMethod("parentOf", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("entryName")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = Text.GetText(args[0]);
                string nx;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    nx = name;
                }
                else
                {
                    nx = Path.Combine(context.runtime.CurrentWorkingDirectory, name);
                }

                string parent = Path.GetDirectoryName(nx);
                if (parent == null)
                {
                    return(context.runtime.nil);
                }

                string cwd = context.runtime.CurrentWorkingDirectory;

                if (!IokeSystem.IsAbsoluteFileName(name) && parent.Equals(cwd))
                {
                    return(context.runtime.nil);
                }

                if (parent.StartsWith(cwd))
                {
                    parent = parent.Substring(cwd.Length + 1);
                }

                return(context.runtime.NewText(parent));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes a file name and a lexical block - opens the file, ensures that it exists and then yields the file to the block. Finally it closes the file after the block has finished executing, and then returns the result of the block.",
                                                       new NativeMethod("withOpenFile", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("fileName")
                                                                        .WithRequiredPositional("code")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0]));
                FileInfo f  = null;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    f = new FileInfo(name);
                }
                else
                {
                    f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name));
                }

                try {
                    if (!f.Exists)
                    {
                        using (FileStream fs = File.Create(f.FullName)) {
                        }
                    }
                } catch (IOException) {
                }

                IokeObject ff = context.runtime.NewFile(context, f);
                object result = context.runtime.nil;

                try {
                    result = Interpreter.Send(context.runtime.callMessage, context, args[1], ff);
                } finally {
                    Interpreter.Send(context.runtime.closeMessage, context, ff);
                }

                return(result);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Copies a file. Takes two text arguments, where the first is the name of the file to copy and the second is the name of the destination. If the destination is a directory, the file will be copied with the same name, and if it's a filename, the file will get a new name",
                                                       new NativeMethod("copyFile", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("fileName")
                                                                        .WithRequiredPositional("destination")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = Text.GetText(args[0]);
                FileInfo f  = null;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    f = new FileInfo(name);
                }
                else
                {
                    f = new FileInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name));
                }

                string name2 = Text.GetText(args[1]);
                string nx    = null;
                if (IokeSystem.IsAbsoluteFileName(name2))
                {
                    nx = name2;
                }
                else
                {
                    nx = Path.Combine(context.runtime.CurrentWorkingDirectory, name2);
                }

                if (new DirectoryInfo(nx).Exists)
                {
                    nx = Path.Combine(nx, f.Name);
                }


                try {
                    File.Copy(f.FullName, nx, true);
                } catch (IOException) {
                }

                return(context.runtime.nil);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and creates a directory with that name. It also takes an optional second argument. If it's true, will try to create all necessary directories inbetween. Default is false. Will signal a condition if the directory already exists, or if there's a file with that name.",
                                                       new NativeMethod("createDirectory!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("directoryName")
                                                                        .WithOptionalPositional("createPath", "false")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name     = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0]));
                DirectoryInfo f = null;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    f = new DirectoryInfo(name);
                }
                else
                {
                    f = new DirectoryInfo(Path.Combine(context.runtime.CurrentWorkingDirectory, name));
                }

                if (f.Exists || new FileInfo(f.FullName).Exists)
                {
                    string msg = null;
                    if (f.Exists)
                    {
                        msg = "Can't create directory '" + name + "' since there already exists a directory with that name";
                    }
                    else
                    {
                        msg = "Can't create directory '" + name + "' since there already exists a file with that name";
                    }

                    IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                                 message,
                                                                                 context,
                                                                                 "Error",
                                                                                 "IO"), context).Mimic(message, context);
                    condition.SetCell("message", message);
                    condition.SetCell("context", context);
                    condition.SetCell("receiver", on);
                    condition.SetCell("text", runtime.NewText(msg));

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

                Directory.CreateDirectory(f.FullName);
                return(context.runtime.nil);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and removes a directory with that name. Will signal a condition if the directory doesn't exist, or if there's a file with that name.",
                                                       new NativeMethod("removeDirectory!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("directoryName")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0]));
                string nf   = null;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    nf = name;
                }
                else
                {
                    nf = Path.Combine(context.runtime.CurrentWorkingDirectory, name);
                }

                if (!(new DirectoryInfo(nf).Exists) || new FileInfo(nf).Exists)
                {
                    string msg = null;
                    if (!(new DirectoryInfo(nf).Exists))
                    {
                        msg = "Can't remove directory '" + name + "' since it doesn't exist";
                    }
                    else
                    {
                        msg = "Can't remove directory '" + name + "' since it is a file";
                    }

                    IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                                 message,
                                                                                 context,
                                                                                 "Error",
                                                                                 "IO"), context).Mimic(message, context);
                    condition.SetCell("message", message);
                    condition.SetCell("context", context);
                    condition.SetCell("receiver", on);
                    condition.SetCell("text", runtime.NewText(msg));

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

                Directory.Delete(nf);
                return(context.runtime.nil);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one string argument and removes a file with that name. Will signal a condition if the file doesn't exist, or if there's a directory with that name.",
                                                       new NativeMethod("removeFile!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("fileName")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = IokeSystem.WithReplacedHomeDirectory(Text.GetText(args[0]));
                string nf   = null;
                if (IokeSystem.IsAbsoluteFileName(name))
                {
                    nf = name;
                }
                else
                {
                    nf = Path.Combine(context.runtime.CurrentWorkingDirectory, name);
                }

                if (!(new FileInfo(nf).Exists) || new DirectoryInfo(nf).Exists)
                {
                    string msg = null;
                    if (!(new FileInfo(nf).Exists))
                    {
                        msg = "Can't remove file '" + name + "' since it doesn't exist";
                    }
                    else
                    {
                        msg = "Can't remove file '" + name + "' since it is a directory";
                    }

                    IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                                 message,
                                                                                 context,
                                                                                 "Error",
                                                                                 "IO"), context).Mimic(message, context);
                    condition.SetCell("message", message);
                    condition.SetCell("context", context);
                    condition.SetCell("receiver", on);
                    condition.SetCell("text", runtime.NewText(msg));

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

                File.Delete(nf);

                return(context.runtime.nil);
            })));
        }
        public 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);
        }
Example #19
0
        public static object Cells(IokeObject context, IokeObject message, object on, bool includeMimics)
        {
            var     cells   = new SaneOrderedDictionary();
            Runtime runtime = context.runtime;

            if (includeMimics)
            {
                var visited   = IdentityHashTable.Create();
                var undefined = new SaneHashSet <string>();
                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;
                        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))
                            {
                                object val = c.value;
                                if (val == runtime.nul)
                                {
                                    undefined.Add(s);
                                }
                                else
                                {
                                    object x = runtime.GetSymbol(s);
                                    if (!cells.Contains(x))
                                    {
                                        cells[x] = val;
                                    }
                                }
                            }
                            c = c.orderedNext;
                        }
                    }
                }
            }
            else
            {
                Cell c = IokeObject.As(on, context).body.firstAdded;
                while (c != null)
                {
                    string s = c.name;
                    if (c.value != runtime.nul)
                    {
                        cells[runtime.GetSymbol(s)] = c.value;
                    }
                    c = c.orderedNext;
                }
            }
            return(runtime.NewDict(cells));
        }
Example #20
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(Interpreter.Send(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(Interpreter.Send(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(Interpreter.Send(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(Interpreter.Send(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);
                }
            })));
        }
Example #21
0
        public override void Init(IokeObject obj)
        {
            Runtime runtime = obj.runtime;

            obj.Kind = "IO";

            obj.RegisterMethod(runtime.NewNativeMethod("Prints a text representation of the argument and a newline to the current IO object",
                                                       new TypeCheckingNativeMethod("println",
                                                                                    TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(runtime.Io)
                                                                                    .WithOptionalPositional("object", "nil")
                                                                                    .Arguments,
                                                                                    (self, on, args, keywords, context, message) => {
                try {
                    if (args.Count > 0)
                    {
                        IokeIO.GetWriter(on).Write(Interpreter.Send(context.runtime.asText, context, args[0]).ToString());
                    }

                    IokeIO.GetWriter(on).Write("\n");
                    IokeIO.GetWriter(on).Flush();
                } catch (IOException e) {
                    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("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));

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

                return(context.runtime.nil);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Prints a text representation of the argument to the current IO object",
                                                       new TypeCheckingNativeMethod("print",
                                                                                    TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(runtime.Io)
                                                                                    .WithRequiredPositional("object")
                                                                                    .Arguments,
                                                                                    (self, on, args, keywords, context, message) => {
                try {
                    IokeIO.GetWriter(on).Write(Interpreter.Send(context.runtime.asText, context, args[0]).ToString());
                    IokeIO.GetWriter(on).Flush();
                } catch (IOException e) {
                    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("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));

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

                return(context.runtime.nil);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("tries to read as much as possible and return a message chain representing what's been read",
                                                       new TypeCheckingNativeMethod.WithNoArguments("read", obj,
                                                                                                    (self, on, args, keywords, context, message) => {
                try {
                    string line = IokeIO.GetReader(on).ReadLine();
                    return(Message.NewFromStream(context.runtime, new StringReader(line), message, context));
                } catch (IOException e) {
                    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("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));

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

                return(context.runtime.nil);
            })));
        }
Example #22
0
        public override void Init(IokeObject obj)
        {
            obj.Kind = "Arity";

            obj.SetCell("taking:nothing", GetArity(obj, Taking.Nothing));
            obj.SetCell("taking:everything", GetArity(obj, Taking.Everything));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Create an Arity object from the given messages. The list of unevaluated messages given to this method will be used as if they were the arguments part of a DefaultMethod definition.",
                                                           new TypeCheckingNativeMethod("from", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(obj)
                                                                                        .WithRestUnevaluated("arguments")
                                                                                        .Arguments,
                                                                                        (self, on, args, keywords, context, message) => {
                if (message.Arguments.Count == 0)
                {
                    return(TakingNothing(self));
                }
                DefaultArgumentsDefinition def = DefaultArgumentsDefinition.CreateFrom(message.Arguments, 0, message.Arguments.Count, message, on, context);
                return(GetArity(self, def));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the names for positional arguments",
                                                           new TypeCheckingNativeMethod("positionals", TypeCheckingArgumentsDefinition.builder()
                                                                                        .WithOptionalPositional("includeOptionals", "true")
                                                                                        .Arguments,
                                                                                        (method, on, args, keywords, context, message) => {
                Arity a              = (Arity)IokeObject.dataOf(on);
                var names            = new SaneArrayList();
                bool includeOptional = args.Count == 0 ? true : IokeObject.IsObjectTrue(args[0]);
                if (a.argumentsDefinition != null)
                {
                    foreach (DefaultArgumentsDefinition.Argument argument in a.argumentsDefinition.Arguments)
                    {
                        if (argument is DefaultArgumentsDefinition.KeywordArgument)
                        {
                            continue;
                        }
                        if (argument is DefaultArgumentsDefinition.OptionalArgument)
                        {
                            if (includeOptional)
                            {
                                names.Add(method.runtime.GetSymbol(argument.Name));
                            }
                        }
                        else
                        {
                            names.Add(method.runtime.GetSymbol(argument.Name));
                        }
                    }
                }
                return(method.runtime.NewList(names));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the names for keyword arguments",
                                                           new TypeCheckingNativeMethod.WithNoArguments("keywords", obj,
                                                                                                        (method, on, args, keywords, context, message) => {
                Arity a   = (Arity)IokeObject.dataOf(on);
                var names = new SaneArrayList();
                if (a.argumentsDefinition != null)
                {
                    foreach (string name in a.argumentsDefinition.Keywords)
                    {
                        names.Add(method.runtime.GetSymbol(name.Substring(0, name.Length - 1)));
                    }
                }
                return(method.runtime.NewList(names));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the symbol name for the krest argument.",
                                                           new TypeCheckingNativeMethod.WithNoArguments("krest", obj,
                                                                                                        (method, on, args, keywords, context, message) => {
                Arity a = (Arity)IokeObject.dataOf(on);
                if (a.argumentsDefinition != null)
                {
                    string name = a.argumentsDefinition.KrestName;
                    if (name == null)
                    {
                        return(method.runtime.nil);
                    }
                    else
                    {
                        return(method.runtime.GetSymbol(name));
                    }
                }
                else
                {
                    return(method.runtime.nil);
                }
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the symbol name for the rest argument.",
                                                           new TypeCheckingNativeMethod.WithNoArguments("rest", obj,
                                                                                                        (method, on, args, keywords, context, message) => {
                Arity a = (Arity)IokeObject.dataOf(on);
                if (a.argumentsDefinition != null)
                {
                    string name = a.argumentsDefinition.RestName;
                    if (name == null)
                    {
                        return(method.runtime.nil);
                    }
                    else
                    {
                        return(method.runtime.GetSymbol(name));
                    }
                }
                else
                {
                    return(method.runtime.nil);
                }
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the text representation of this arity",
                                                           new TypeCheckingNativeMethod.WithNoArguments("asText", obj,
                                                                                                        (method, on, args, keywords, context, message) => {
                Arity a = (Arity)IokeObject.dataOf(on);
                if (a.taking == Taking.Everything)
                {
                    return(method.runtime.NewText("..."));
                }
                else if (a.taking == Taking.Nothing)
                {
                    return(method.runtime.NewText(""));
                }
                return(method.runtime.NewText(a.argumentsDefinition.GetCode(false)));
            })));
        }
Example #23
0
        public static void Init(IokeObject obj)
        {
            obj.Kind = "Base";

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects two or more arguments, the first arguments unevaluated, the last evaluated. assigns the result of evaluating the last argument in the context of the caller, and assigns this result to the name/s provided by the first arguments. the first arguments remains unevaluated. the result of the assignment is the value assigned to the name. if the last argument is a method-like object and it's name is not set, that name will be set to the name of the cell.",
                                                           new NativeMethod("=", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositionalUnevaluated("place")
                                                                            .WithRestUnevaluated("morePlacesForDestructuring")
                                                                            .WithRequiredPositional("value")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);

                var args = message.Arguments;
                if (args.Count == 2)
                {
                    IokeObject m1 = IokeObject.As(Message.GetArguments(message)[0], context);
                    string name   = m1.Name;
                    if (m1.Arguments.Count == 0)
                    {
                        object value = Interpreter.GetEvaluatedArgument(message, 1, context);
                        IokeObject.Assign(on, name, value, context, message);

                        if (value is IokeObject)
                        {
                            if ((IokeObject.dataOf(value) is Named) && ((Named)IokeObject.dataOf(value)).Name == null)
                            {
                                ((Named)IokeObject.dataOf(value)).Name = name;
                            }
                            else if (name.Length > 0 && char.IsUpper(name[0]) && !(IokeObject.As(value, context).HasKind))
                            {
                                if (on == context.runtime.Ground || on == context.runtime.IokeGround)
                                {
                                    IokeObject.As(value, context).Kind = name;
                                }
                                else
                                {
                                    IokeObject.As(value, context).Kind = IokeObject.As(on, context).GetKind(message, context) + " " + name;
                                }
                            }
                        }

                        return(value);
                    }
                    else
                    {
                        string newName  = name + "=";
                        IList arguments = new SaneArrayList(m1.Arguments);
                        arguments.Add(Message.GetArguments(message)[1]);
                        IokeObject msg = context.runtime.NewMessageFrom(message, newName, arguments);
                        return(Interpreter.Send(msg, context, on));
                    }
                }
                else
                {
                    int lastIndex = args.Count - 1;
                    int numPlaces = lastIndex;

                    return(RecursiveDestructuring(args, numPlaces, message, context, on, Interpreter.GetEvaluatedArgument(args[lastIndex], context)));
                }
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("will return a new derivation of the receiving object. Might throw exceptions if the object is an oddball object.",
                                                           new NativeMethod.WithNoArguments("mimic", (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                return(IokeObject.As(on, context).Mimic(message, context));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument that names the cell to set, sets this cell to the result of evaluating the second argument, and returns the value set.",
                                                           new NativeMethod("cell=",
                                                                            DefaultArgumentsDefinition
                                                                            .builder()
                                                                            .WithRequiredPositional("cellName")
                                                                            .WithRequiredPositional("value")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(AssignCell(context, message, on, args[0], args[1]));
            })));
            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns the cell that matches that name, without activating even if it's activatable.",
                                                           new NativeMethod("cell", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0]));
                return(IokeObject.GetCell(on, message, context, name));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a hash for the object",
                                                           new NativeMethod.WithNoArguments("hash", (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                return(context.runtime.NewNumber(System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(IokeObject.As(on, context).body)));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns true if the left hand side is equal to the right hand side. exactly what this means depend on the object. the default behavior of Ioke objects is to only be equal if they are the same instance.",
                                                           new NativeMethod("==", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("other")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                IList args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return((IokeObject.As(on, context).body == IokeObject.As(args[0], context).body) ? context.runtime.True : context.runtime.False);
            })));
            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns a boolean indicating whether such a cell is reachable from this point.",
                                                           new NativeMethod("cell?", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                IList args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0]));
                return(IokeObject.FindCell((IokeObject)on, name) != context.runtime.nul ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the documentation text of the object called on. anything can have a documentation text - this text will initially be nil.",
                                                           new NativeMethod.WithNoArguments("documentation",
                                                                                            (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(Documentation(context, message, on));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a boolean indicating of this object should be activated or not.",
                                                           new NativeMethod.WithNoArguments("activatable",
                                                                                            (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(IokeObject.As(on, context).IsActivatable ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("sets the activatable flag for a specific object. this will not impact objects that mimic this object..",
                                                           new TypeCheckingNativeMethod("activatable=", TypeCheckingArgumentsDefinition.builder()
                                                                                        .WithRequiredPositional("activatableFlag")
                                                                                        .Arguments,
                                                                                        (method, on, args, keywords, context, message) => {
                IokeObject.As(on, context).SetActivatable(IokeObject.IsObjectTrue(args[0]));
                return(args[0]);
            }
                                                                                        )));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns this object",
                                                           new NativeMethod.WithNoArguments("identity",
                                                                                            (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(on);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("sets the documentation string for a specific object.",
                                                           new TypeCheckingNativeMethod("documentation=", TypeCheckingArgumentsDefinition.builder()
                                                                                        .WithRequiredPositional("text").WhichMustMimic(obj.runtime.Text).OrBeNil()
                                                                                        .Arguments,
                                                                                        (method, on, args, keywords, context, message) => {
                return(SetDocumentation(context, message, on, args[0]));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns a boolean indicating whether this cell is owned by the receiver or not. the assumption is that the cell should exist. if it doesn't exist, a NoSuchCell condition will be signalled.",
                                                           new NativeMethod("cellOwner?", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0]));
                return((IokeObject.FindPlace(on, message, context, name) == on) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns the closest object that defines such a cell. if it doesn't exist, a NoSuchCell condition will be signalled.",
                                                           new NativeMethod("cellOwner", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name   = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0]));
                object result = IokeObject.FindPlace(on, message, context, name);
                if (result == context.runtime.nul)
                {
                    return(context.runtime.nil);
                }
                return(result);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and removes that cell from the current receiver. if the current receiver has no such object, signals a condition. note that if another cell with that name is available in the mimic chain, it will still be accessible after calling this method. the method returns the receiver.",
                                                           new NativeMethod("removeCell!", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0]));
                IokeObject.RemoveCell(on, message, context, name);
                return(on);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and makes that cell undefined in the current receiver. what that means is that from now on it will look like this cell doesn't exist in the receiver or any of its mimics. the cell will not show up if you call cellNames on the receiver or any of the receivers mimics. the undefined status can be removed by doing removeCell! on the correct cell name. a cell name that doesn't exist can still be undefined. the method returns the receiver.",
                                                           new NativeMethod("undefineCell!", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[0]));
                IokeObject.UndefineCell(on, message, context, name);
                return(on);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("takes one optional evaluated boolean argument, which defaults to false. if false, this method returns a list of the cell names of the receiver. if true, it returns the cell names of this object and all it's mimics recursively.",
                                                           new NativeMethod("cellNames", DefaultArgumentsDefinition.builder()
                                                                            .WithOptionalPositional("includeMimics", "false")
                                                                            .WithOptionalPositional("cutoff", "nil")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(CellNames(context, message, on, args.Count > 0 && IokeObject.IsObjectTrue(args[0]), (args.Count > 1) ? args[1] : null));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("takes one optional evaluated boolean argument, which defaults to false. if false, this method returns a dict of the cell names and values of the receiver. if true, it returns the cell names and values of this object and all it's mimics recursively.",
                                                           new NativeMethod("cells", DefaultArgumentsDefinition.builder()
                                                                            .WithOptionalPositional("includeMimics", "false")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(Cells(context, message, on, args.Count > 0 && IokeObject.IsObjectTrue(args[0])));
            })));
        }
Example #24
0
        public static void Init(Runtime runtime)
        {
            IokeObject obj = new IokeObject(runtime, "Allows access to the internals of any object without actually using methods on that object");

            obj.Kind = "Reflector";
            obj.MimicsWithoutCheck(runtime.Origin);
            runtime.IokeGround.RegisterCell("Reflector", obj);

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the documentation text of the object given as argument. anything can have a documentation text - this text will initially be nil.",
                                                           new TypeCheckingNativeMethod("other:documentation", TypeCheckingArgumentsDefinition.builder()
                                                                                        .WithRequiredPositional("other")
                                                                                        .Arguments,
                                                                                        (method, on, args, keywords, context, message) => {
                return(Base.Documentation(context, message, args[0]));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("sets the documentation string for a specific object.",
                                                           new TypeCheckingNativeMethod("other:documentation=", TypeCheckingArgumentsDefinition.builder()
                                                                                        .WithRequiredPositional("other")
                                                                                        .WithRequiredPositional("text").WhichMustMimic(obj.runtime.Text).OrBeNil()
                                                                                        .Arguments,
                                                                                        (method, on, args, keywords, context, message) => {
                return(Base.SetDocumentation(context, message, args[0], args[1]));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("will return a new derivation of the receiving object. Might throw exceptions if the object is an oddball object.",
                                                           new TypeCheckingNativeMethod("other:mimic", TypeCheckingArgumentsDefinition.builder()
                                                                                        .WithRequiredPositional("other")
                                                                                        .Arguments,
                                                                                        (method, on, args, keywords, context, message) => {
                return(IokeObject.As(args[0], context).Mimic(message, context));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument that names the cell to set, sets this cell to the result of evaluating the second argument, and returns the value set.",
                                                           new NativeMethod("other:cell=",
                                                                            DefaultArgumentsDefinition
                                                                            .builder()
                                                                            .WithRequiredPositional("other")
                                                                            .WithRequiredPositional("cellName")
                                                                            .WithRequiredPositional("value")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(Base.AssignCell(context, message, args[0], args[1], args[2]));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns the cell that matches that name, without activating even if it's activatable.",
                                                           new NativeMethod("other:cell", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("other")
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1]));
                return(IokeObject.GetCell(args[0], message, context, name));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns a boolean indicating whether such a cell is reachable from this point.",
                                                           new NativeMethod("other:cell?", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("other")
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                IList args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1]));
                return(IokeObject.FindCell((IokeObject)args[0], name) != context.runtime.nul ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns a boolean indicating whether this cell is owned by the receiver or not. the assumption is that the cell should exist. if it doesn't exist, a NoSuchCell condition will be signalled.",
                                                           new NativeMethod("other:cellOwner?", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("other")
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1]));
                return((IokeObject.FindPlace(args[0], message, context, name) == args[0]) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and returns the closest object that defines such a cell. if it doesn't exist, a NoSuchCell condition will be signalled.",
                                                           new NativeMethod("other:cellOwner", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("other")
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name   = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1]));
                object result = IokeObject.FindPlace(args[0], message, context, name);
                if (result == context.runtime.nul)
                {
                    return(context.runtime.nil);
                }
                return(result);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and removes that cell from the current receiver. if the current receiver has no such object, signals a condition. note that if another cell with that name is available in the mimic chain, it will still be accessible after calling this method. the method returns the receiver.",
                                                           new NativeMethod("other:removeCell!", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("other")
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1]));
                IokeObject.RemoveCell(args[0], message, context, name);
                return(args[0]);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("expects one evaluated text or symbol argument and makes that cell undefined in the current receiver. what that means is that from now on it will look like this cell doesn't exist in the receiver or any of its mimics. the cell will not show up if you call cellNames on the receiver or any of the receivers mimics. the undefined status can be removed by doing removeCell! on the correct cell name. a cell name that doesn't exist can still be undefined. the method returns the receiver.",
                                                           new NativeMethod("other:undefineCell!", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("other")
                                                                            .WithRequiredPositional("cellName")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                string name = Text.GetText(Interpreter.Send(context.runtime.asText, context, args[1]));
                IokeObject.UndefineCell(args[0], message, context, name);
                return(args[0]);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("takes one optional evaluated boolean argument, which defaults to false. if false, this method returns a list of the cell names of the receiver. if true, it returns the cell names of this object and all it's mimics recursively.",
                                                           new NativeMethod("other:cellNames", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("other")
                                                                            .WithOptionalPositional("includeMimics", "false")
                                                                            .WithOptionalPositional("cutoff", "nil")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(Base.CellNames(context, message, args[0], args.Count > 1 && IokeObject.IsObjectTrue(args[1]), (args.Count > 2) ? args[2] : null));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("takes one optional evaluated boolean argument, which defaults to false. if false, this method returns a dict of the cell names and values of the receiver. if true, it returns the cell names and values of this object and all it's mimics recursively.",
                                                           new NativeMethod("other:cells", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("other")
                                                                            .WithOptionalPositional("includeMimics", "false")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(Base.Cells(context, message, args[0], args.Count > 1 && IokeObject.IsObjectTrue(args[1])));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and returns either true or false if this object or one of it's mimics mimics that argument",
                                                       new NativeMethod("other:mimics?", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .WithRequiredPositional("potentialMimic")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                IokeObject arg = IokeObject.As(args[1], context);
                if (IokeObject.IsMimic(args[0], arg, context))
                {
                    return(context.runtime.True);
                }
                else
                {
                    return(context.runtime.False);
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("modifies the receiver to be in all ways identical to the argument. if the receiver is nil, true or false, this method can't be used - but those are the only exceptions. it's generally not recommended to use it on kinds and objects that are important for the Ioke runtime, since the result might be highly unpredictable.",
                                                       new NativeMethod("other:become!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .WithRequiredPositional("objectToBecome")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                IokeObject me    = IokeObject.As(args[0], context);
                IokeObject other = IokeObject.As(args[1], context);

                if (args[0] == context.runtime.nil || args[0] == context.runtime.True || args[0] == context.runtime.False)
                {
                    IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                 message,
                                                                                 context,
                                                                                 "Error",
                                                                                 "CantMimicOddball"), context).Mimic(message, context);
                    condition.SetCell("message", message);
                    condition.SetCell("context", context);
                    condition.SetCell("receiver", args[0]);
                    context.runtime.ErrorCondition(condition);
                }

                me.Become(other, message, context);

                return(args[0]);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a text hex representation of the receiver in upper case hex literal, starting with 0x. This value is based on System.identityHashCode, and as such is not totally guaranteed to be totally unique. but almost.",
                                                       new TypeCheckingNativeMethod("other:uniqueHexId", TypeCheckingArgumentsDefinition.builder()
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                return(context.runtime.NewText("0x" + System.Convert.ToString(System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(IokeObject.As(args[0], context).body), 16).ToUpper()));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if the evaluated argument is the same reference as the receiver, false otherwise.",
                                                       new NativeMethod("other:same?", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .WithRequiredPositional("other")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                return(IokeObject.Same(args[0], args[1]) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes the name of a message to send, and the arguments to give it. send should generally behave exactly as if you had sent the message itself - except that you can give a variable containing the name.",
                                                       new NativeMethod("other:send", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .WithRequiredPositional("messageName")
                                                                        .WithRestUnevaluated("arguments")
                                                                        .WithKeywordRestUnevaluated("keywordArguments")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                object _recv = Interpreter.GetEvaluatedArgument(message, 0, context);
                object _name = Interpreter.GetEvaluatedArgument(message, 1, context);
                string name  = Text.GetText(Interpreter.Send(runtime.asText, context, _name));

                IokeObject newMessage = Message.DeepCopy(message);
                newMessage.Arguments.RemoveAt(0);
                newMessage.Arguments.RemoveAt(0);
                Message.SetName(newMessage, name);
                return(Interpreter.Send(newMessage, context, _recv));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated Text argument and returns either true or false if this object or one of it's mimics have the kind of the name specified",
                                                       new TypeCheckingNativeMethod("other:kind?", TypeCheckingArgumentsDefinition.builder()
                                                                                    .WithRequiredPositional("other")
                                                                                    .WithRequiredPositional("name").WhichMustMimic(runtime.Text)
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                string kind = Text.GetText(args[1]);
                return(IokeObject.IsKind(args[0], kind, context) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and returns either true or false if this object or one of it's mimics mimics that argument. exactly the same as 'mimics?'",
                                                       new NativeMethod("other:is?", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .WithRequiredPositional("potentialMimic")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                IokeObject arg = IokeObject.As(args[1], context);
                return(IokeObject.IsMimic(args[0], arg, context) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a list of all the mimics of the receiver. it will not be the same list as is used to back the object, so modifications to this list will not show up in the object.",
                                                       new TypeCheckingNativeMethod("other:mimics", TypeCheckingArgumentsDefinition.builder()
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                var l = new SaneArrayList();
                foreach (object x in IokeObject.GetMimics(args[0], context))
                {
                    l.Add(x);
                }
                return(context.runtime.NewList(l));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("removes all mimics on the receiver, and returns the receiver",
                                                       new TypeCheckingNativeMethod("other:removeAllMimics!", TypeCheckingArgumentsDefinition.builder()
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                IokeObject.RemoveAllMimics(args[0], message, context);
                return(args[0]);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("removes the argument mimic from the list of all mimics on the receiver. will do nothing if the receiver has no such mimic. it returns the receiver",
                                                       new NativeMethod("other:removeMimic!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .WithRequiredPositional("mimicToRemove")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                IokeObject.RemoveMimic(args[0], args[1], message, context);
                return(args[0]);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and adds it to the list of mimics for the receiver. the receiver will be returned.",
                                                       new NativeMethod("other:mimic!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .WithRequiredPositional("newMimic")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                IokeObject newMimic = IokeObject.As(args[1], context);
                IokeObject.As(args[0], context).Mimics(newMimic, message, context);
                return(args[0]);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Takes one evaluated argument and prepends it to the list of mimics for the receiver. the receiver will be returned.",
                                                       new NativeMethod("other:prependMimic!", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .WithRequiredPositional("newMimic")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                IokeObject newMimic = IokeObject.As(args[1], context);
                IokeObject.As(args[0], context).Mimics(0, newMimic, message, context);
                return(args[0]);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if the receiver is frozen, otherwise false",
                                                       new TypeCheckingNativeMethod("other:frozen?", TypeCheckingArgumentsDefinition.builder()
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                return(IokeObject.As(args[0], context).IsFrozen ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("ensures that the receiver is frozen",
                                                       new TypeCheckingNativeMethod("other:freeze!", TypeCheckingArgumentsDefinition.builder()
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                IokeObject.Freeze(args[0]);
                return(args[0]);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("ensures that the receiver is not frozen",
                                                       new TypeCheckingNativeMethod("other:thaw!", TypeCheckingArgumentsDefinition.builder()
                                                                                    .WithRequiredPositional("other")
                                                                                    .Arguments,
                                                                                    (method, on, args, keywords, context, message) => {
                IokeObject.Thaw(args[0]);
                return(args[0]);
            })));
        }
Example #25
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);
            })));
        }
Example #26
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);
            })));
        }
Example #27
0
        public static void Init(IokeObject rl)
        {
            Runtime runtime = rl.runtime;

            rl.Kind = "Readline";
            rl.MimicsWithoutCheck(runtime.Origin);
            runtime.Ground.SetCell("Readline", rl);
            rl.SetCell("VERSION", runtime.NewText("Mono.Terminal.LineEditor wrapper"));

            ConsoleHolder holder = new ConsoleHolder();

            holder.history = new History("ioke", 10);

            IokeObject history = runtime.NewFromOrigin();

            rl.SetCell("HISTORY", history);

            rl.RegisterMethod(runtime.NewNativeMethod("will print a prompt to standard out and then try to read a line with working readline functionality. takes two arguments, the first is the string to prompt, the second is a boolean that says whether we should add the read string to history or not",
                                                      new NativeMethod("readline", DefaultArgumentsDefinition.builder()
                                                                       .WithRequiredPositional("prompt")
                                                                       .WithRequiredPositional("addToHistory?")
                                                                       .Arguments,
                                                                       (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                object line = method.runtime.nil;
                try {
                    if (holder.readline == null)
                    {
                        InitReadline(method.runtime, holder);
                    }
                    string v = holder.readline.Edit(Text.GetText(args[0]), "");
                    if (null != v)
                    {
                        if (IokeObject.IsObjectTrue(args[1]))
                        {
                            holder.history.Append(v);
                        }

                        line = method.runtime.NewText(v);
                    }
                } catch (IOException e) {
                    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("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));

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

            history.RegisterMethod(runtime.NewNativeMethod("will add a new line to the history",
                                                           new NativeMethod("<<", DefaultArgumentsDefinition.builder()
                                                                            .WithRequiredPositional("line")
                                                                            .Arguments,
                                                                            (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                foreach (object o in args)
                {
                    holder.history.Append(Text.GetText(o));
                }
                return(context.runtime.nil);
            })));
        }
Example #28
0
        public override void Init(IokeObject obj)
        {
            Runtime runtime = obj.runtime;

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

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

                return(((other is IokeObject) &&
                        (IokeObject.dataOf(other) is Range) &&
                        d.inclusive == ((Range)IokeObject.dataOf(other)).inclusive &&
                        d.from.Equals(((Range)IokeObject.dataOf(other)).from) &&
                        d.to.Equals(((Range)IokeObject.dataOf(other)).to)) ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("will return a new inclusive Range based on the two arguments",
                                                       new NativeMethod("inclusive", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("from")
                                                                        .WithRequiredPositional("to")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                object from = args[0];
                object to   = args[1];

                bool comparing = IokeObject.IsMimic(from, IokeObject.As(context.runtime.Mixins.body.Get("Comparing"), context), context);
                bool inverted  = false;

                if (comparing)
                {
                    object result = Interpreter.Send(context.runtime.spaceShipMessage, context, from, to);
                    if (result != context.runtime.nil && Number.ExtractInt(result, message, context) == 1)
                    {
                        inverted = true;
                    }
                }

                return(runtime.NewRange(IokeObject.As(from, context), IokeObject.As(to, context), true, inverted));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("will return a new exclusive Range based on the two arguments",
                                                       new NativeMethod("exclusive", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("from")
                                                                        .WithRequiredPositional("to")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());

                object from = args[0];
                object to   = args[1];

                bool comparing = IokeObject.IsMimic(from, IokeObject.As(context.runtime.Mixins.body.Get("Comparing"), context), context);
                bool inverted  = false;

                if (comparing)
                {
                    object result = Interpreter.Send(context.runtime.spaceShipMessage, context, from, to);
                    if (result != context.runtime.nil && Number.ExtractInt(result, message, context) == 1)
                    {
                        inverted = true;
                    }
                }

                return(runtime.NewRange(IokeObject.As(from, context), IokeObject.As(to, context), false, inverted));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if the receiver is an exclusive range, false otherwise",
                                                       new NativeMethod.WithNoArguments("exclusive?",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(((Range)IokeObject.dataOf(on)).inclusive ? context.runtime.False : context.runtime.True);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if the receiver is an inclusive range, false otherwise",
                                                       new NativeMethod.WithNoArguments("inclusive?",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(((Range)IokeObject.dataOf(on)).inclusive ? context.runtime.True : context.runtime.False);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the 'from' part of the range",
                                                       new TypeCheckingNativeMethod.WithNoArguments("from", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                return(((Range)IokeObject.dataOf(on)).from);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns the 'to' part of the range",
                                                       new NativeMethod.WithNoArguments("to",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(((Range)IokeObject.dataOf(on)).to);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns a new sequence to iterate over this range",
                                                       new TypeCheckingNativeMethod.WithNoArguments("seq", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                IokeObject ob = method.runtime.Iterator2Sequence.AllocateCopy(null, null);
                ob.MimicsWithoutCheck(method.runtime.Iterator2Sequence);
                Range r = ((Range)IokeObject.dataOf(on));
                ob.Data = new Sequence.Iterator2Sequence(new RangeIterator(r.from, r.to, r.inclusive, r.inverted, context, message));
                return(ob);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("takes either one or two or three arguments. if one argument is given, it should be a message chain that will be sent to each object in the range. the result will be thrown away. if two arguments are given, the first is an unevaluated name that will be set to each of the values in the range in succession, and then the second argument will be evaluated in a scope with that argument in it. if three arguments is given, the first one is an unevaluated name that will be set to the index of each element, and the other two arguments are the name of the argument for the value, and the actual code. the code will evaluate in a lexical context, and if the argument name is available outside the context, it will be shadowed. the method will return the range.",
                                                       new NativeMethod("each", DefaultArgumentsDefinition.builder()
                                                                        .WithOptionalPositionalUnevaluated("indexOrArgOrCode")
                                                                        .WithOptionalPositionalUnevaluated("argOrCode")
                                                                        .WithOptionalPositionalUnevaluated("code")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.CheckArgumentCount(context, message, on);
                IokeObject from = IokeObject.As(((Range)IokeObject.dataOf(on)).from, context);
                IokeObject to   = IokeObject.As(((Range)IokeObject.dataOf(on)).to, context);
                bool inclusive  = ((Range)IokeObject.dataOf(on)).inclusive;

                IokeObject messageToSend = context.runtime.succMessage;
                if (((Range)IokeObject.dataOf(on)).inverted)
                {
                    messageToSend = context.runtime.predMessage;
                }

                switch (message.Arguments.Count)
                {
                case 0: {
                    return(Interpreter.Send(runtime.seqMessage, context, on));
                }

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

                    object current = from;

                    while (!IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, to)))
                    {
                        context.runtime.interpreter.Evaluate(code, context, context.RealContext, current);
                        current = Interpreter.Send(messageToSend, context, current);
                    }
                    if (inclusive)
                    {
                        context.runtime.interpreter.Evaluate(code, context, context.RealContext, current);
                    }

                    break;
                }

                case 2: {
                    IokeObject c    = context.runtime.NewLexicalContext(context, "Lexical activation context for Range#each", context);
                    string name     = IokeObject.As(message.Arguments[0], context).Name;
                    IokeObject code = IokeObject.As(message.Arguments[1], context);

                    object current = from;

                    while (!IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, to)))
                    {
                        c.SetCell(name, current);
                        context.runtime.interpreter.Evaluate(code, c, c.RealContext, c);
                        current = Interpreter.Send(messageToSend, context, current);
                    }
                    if (inclusive)
                    {
                        c.SetCell(name, current);
                        context.runtime.interpreter.Evaluate(code, c, c.RealContext, c);
                    }

                    break;
                }

                case 3: {
                    IokeObject c    = context.runtime.NewLexicalContext(context, "Lexical activation context for Range#each", context);
                    string iname    = IokeObject.As(message.Arguments[0], context).Name;
                    string name     = IokeObject.As(message.Arguments[1], context).Name;
                    IokeObject code = IokeObject.As(message.Arguments[2], context);

                    int index = 0;

                    object current = from;

                    while (!IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, to)))
                    {
                        c.SetCell(name, current);
                        c.SetCell(iname, runtime.NewNumber(index++));
                        context.runtime.interpreter.Evaluate(code, c, c.RealContext, c);
                        current = Interpreter.Send(messageToSend, context, current);
                    }
                    if (inclusive)
                    {
                        c.SetCell(name, current);
                        c.SetCell(iname, runtime.NewNumber(index++));
                        context.runtime.interpreter.Evaluate(code, c, c.RealContext, c);
                    }

                    break;
                }
                }
                return(on);
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("returns true if the argument is within the confines of this range. how this comparison is done depends on if the object mimics Comparing. If it does, < and > will be used. If not, all the available entries in this range will be enumerated using 'succ'/'pred' until either the end or the element we're looking for is found. in that case, comparison is done with '=='",
                                                       new NativeMethod("===", DefaultArgumentsDefinition.builder()
                                                                        .WithRequiredPositional("other")
                                                                        .Arguments,
                                                                        (method, context, message, on, outer) => {
                var args = new SaneArrayList();
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, args, new SaneDictionary <string, object>());
                object other = args[0];

                IokeObject from = IokeObject.As(((Range)IokeObject.dataOf(on)).from, context);
                IokeObject to   = IokeObject.As(((Range)IokeObject.dataOf(on)).to, context);
                bool comparing  = IokeObject.IsMimic(from, IokeObject.As(context.runtime.Mixins.body.Get("Comparing"), context));
                bool inclusive  = ((Range)IokeObject.dataOf(on)).inclusive;

                if (comparing)
                {
                    IokeObject firstMessage           = context.runtime.lteMessage;
                    IokeObject secondMessageInclusive = context.runtime.gteMessage;
                    IokeObject secondMessageExclusive = context.runtime.gtMessage;

                    if (((Range)IokeObject.dataOf(on)).inverted)
                    {
                        firstMessage           = context.runtime.gteMessage;
                        secondMessageInclusive = context.runtime.lteMessage;
                        secondMessageExclusive = context.runtime.ltMessage;
                    }

                    if (IokeObject.IsObjectTrue(Interpreter.Send(firstMessage, context, from, other)) &&
                        ((inclusive &&
                          IokeObject.IsObjectTrue(Interpreter.Send(secondMessageInclusive, context, to, other))) ||
                         IokeObject.IsObjectTrue(Interpreter.Send(secondMessageExclusive, context, to, other))))
                    {
                        return(context.runtime.True);
                    }
                    else
                    {
                        return(context.runtime.False);
                    }
                }
                else
                {
                    IokeObject messageToSend = context.runtime.succMessage;
                    if (((Range)IokeObject.dataOf(on)).inverted)
                    {
                        messageToSend = context.runtime.predMessage;
                    }

                    object current = from;

                    while (!IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, to)))
                    {
                        if (IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, current, other)))
                        {
                            return(context.runtime.True);
                        }
                        current = Interpreter.Send(messageToSend, context, current);
                    }

                    if (inclusive && IokeObject.IsObjectTrue(Interpreter.Send(context.runtime.eqMessage, context, to, other)))
                    {
                        return(context.runtime.True);
                    }
                    return(context.runtime.False);
                }
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Returns a text inspection of the object",
                                                       new NativeMethod.WithNoArguments("inspect",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(method.runtime.NewText(Range.GetInspect(on)));
            })));

            obj.RegisterMethod(runtime.NewNativeMethod("Returns a brief text inspection of the object",
                                                       new NativeMethod.WithNoArguments("notice",
                                                                                        (method, context, message, on, outer) => {
                outer.ArgumentsDefinition.GetEvaluatedArguments(context, message, on, new SaneArrayList(), new SaneDictionary <string, object>());
                return(method.runtime.NewText(Range.GetNotice(on)));
            })));
        }
        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 = runtime.interpreter.Evaluate(m1, locals, locals.RealContext, locals);
                            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, runtime.interpreter.Evaluate(m2, locals, locals.RealContext, locals));
                    }
                }
                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));
            }
        }
Example #30
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));
            })));
        }