Exemplo n.º 1
0
        public static object ActivateWithCallAndData(IokeObject receiver, IokeObject context, IokeObject message, object obj, object c, IDictionary <string, object> d1)
        {
            switch (receiver.data.type)
            {
            case IokeData.TYPE_DEFAULT_METHOD:
                return(DefaultMethod.ActivateWithCallAndDataFixed(receiver, context, message, obj, c, d1));

            case IokeData.TYPE_DEFAULT_MACRO:
                return(DefaultMacro.ActivateWithCallAndDataFixed(receiver, context, message, obj, c, d1));

            case IokeData.TYPE_DEFAULT_SYNTAX:
                return(DefaultSyntax.ActivateWithCallAndDataFixed(receiver, context, message, obj, c, d1));

            case IokeData.TYPE_LEXICAL_MACRO:
                return(LexicalMacro.ActivateWithCallAndDataFixed(receiver, context, message, obj, c, d1));

            case IokeData.TYPE_NATIVE_METHOD:
                return(NativeMethod.ActivateFixed(receiver, context, message, obj));

            case IokeData.TYPE_METHOD_PROTOTYPE:
                return(Method.ActivateFixed(receiver, context, message, obj));

            case IokeData.TYPE_LEXICAL_BLOCK:
                return(LexicalBlock.ActivateWithCallAndDataFixed(receiver, context, message, obj, c, d1));

            case IokeData.TYPE_ALIAS_METHOD:
                return(AliasMethod.ActivateFixed(receiver, context, message, obj));

            case IokeData.TYPE_NONE:
            default:
                return(IokeData.ActivateFixed(receiver, context, message, obj));
            }
        }
Exemplo n.º 2
0
        public void Become(IokeObject other, IokeObject message, IokeObject context)
        {
            CheckFrozen("become!", message, context);

            this.runtime = other.runtime;
            this.data    = other.data;
            this.body    = other.body;
        }
Exemplo n.º 3
0
        public IokeObject(Runtime runtime, string documentation, IokeData data)
        {
            this.runtime = runtime;
            this.documentation = documentation;
            this.data = data;

            this.mimics = new SaneList<IokeObject>();
            this.cells = new SaneDictionary<string, object>();
        }
Exemplo n.º 4
0
        public void Become(IokeObject other, IokeObject message, IokeObject context)
        {
            CheckFrozen("become!", message, context);

            this.runtime = other.runtime;
            this.documentation = other.documentation;
            this.cells = other.cells;
            this.mimics = other.mimics;
            this.data = other.data;
            this.frozen = other.frozen;
        }
Exemplo n.º 5
0
 public IokeObject(Runtime runtime, string documentation, IokeData data)
 {
     this.runtime            = runtime;
     this.body.documentation = documentation;
     this.data = data;
 }
Exemplo n.º 6
0
        public override void Init(IokeObject obj)
        {
            obj.Kind = "DefaultSyntax";
            obj.SetActivatable(true);

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the name of the syntax",
                                                           new TypeCheckingNativeMethod.WithNoArguments("name", obj,
                                                                                                        (method, on, args, keywords, _context, message) => {
                return(_context.runtime.NewText(((DefaultSyntax)IokeObject.dataOf(on)).name));
            })));


            obj.RegisterMethod(obj.runtime.NewNativeMethod("activates this syntax with the arguments given to call",
                                                           new NativeMethod("call", DefaultArgumentsDefinition.builder()
                                                                            .WithRestUnevaluated("arguments")
                                                                            .Arguments,
                                                                            (method, _context, message, on, outer) => {
                return(Interpreter.Activate(IokeObject.As(on, _context), _context, message, _context.RealContext));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the result of activating this syntax without actually doing the replacement or execution part.",
                                                           new NativeMethod("expand", DefaultArgumentsDefinition.builder()
                                                                            .WithRestUnevaluated("arguments")
                                                                            .Arguments,
                                                                            (method, _context, message, on, outer) => {
                object onAsSyntax = _context.runtime.DefaultSyntax.ConvertToThis(on, message, _context);
                return(((DefaultSyntax)IokeObject.dataOf(onAsSyntax)).Expand(IokeObject.As(onAsSyntax, context), context, message, context.RealContext, null));
            })));


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

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

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

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


            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the full code of this syntax, as a Text",
                                                           new TypeCheckingNativeMethod.WithNoArguments("code", obj,
                                                                                                        (method, on, args, keywords, _context, message) => {
                IokeData data = IokeObject.dataOf(on);
                if (data is DefaultSyntax)
                {
                    return(_context.runtime.NewText(((DefaultSyntax)data).CodeString));
                }
                else
                {
                    return(_context.runtime.NewText(((AliasMethod)data).CodeString));
                }
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns idiomatically formatted code for this syntax",
                                                           new TypeCheckingNativeMethod.WithNoArguments("formattedCode", obj,
                                                                                                        (method, on, args, keywords, _context, message) => {
                return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).FormattedCode(method)));
            })));
        }
Exemplo n.º 7
0
 public IokeObject NewMacro(string doc, IokeObject tp, IokeData impl)
 {
     IokeObject obj = tp.AllocateCopy(null, null);
     obj.SetDocumentation(doc, null, null);
     obj.MimicsWithoutCheck(tp);
     obj.Data = impl;
     return obj;
 }
Exemplo n.º 8
0
        public void Become(IokeObject other, IokeObject message, IokeObject context)
        {
            CheckFrozen("become!", message, context);

            this.runtime = other.runtime;
            this.data = other.data;
            this.body = other.body;
        }
Exemplo n.º 9
0
 public IokeObject(Runtime runtime, string documentation, IokeData data)
 {
     this.runtime = runtime;
     this.body.documentation = documentation;
     this.data = data;
 }
Exemplo n.º 10
0
        public override void Init(IokeObject obj)
        {
            obj.Kind = "DefaultMacro";
            obj.SetActivatable(true);

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the name of the macro",
                                                           new TypeCheckingNativeMethod.WithNoArguments("name", obj,
                                                                                                        (method, on, args, keywords, _context, message) => {
                return(_context.runtime.NewText(((DefaultMacro)IokeObject.dataOf(on)).name));
            })));



            obj.RegisterMethod(obj.runtime.NewNativeMethod("activates this macro with the arguments given to call",
                                                           new NativeMethod("call", DefaultArgumentsDefinition.builder()
                                                                            .WithRestUnevaluated("arguments")
                                                                            .Arguments,
                                                                            (method, _context, message, on, outer) => {
                return(Interpreter.Activate(IokeObject.As(on, _context), _context, message, _context.RealContext));
            })));


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


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

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

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

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns the full code of this macro, as a Text",
                                                           new TypeCheckingNativeMethod.WithNoArguments("code", obj,
                                                                                                        (method, on, args, keywords, _context, message) => {
                IokeData data = IokeObject.dataOf(on);
                if (data is DefaultMacro)
                {
                    return(_context.runtime.NewText(((DefaultMacro)data).CodeString));
                }
                else
                {
                    return(_context.runtime.NewText(((AliasMethod)data).CodeString));
                }
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("returns idiomatically formatted code for this macro",
                                                           new TypeCheckingNativeMethod.WithNoArguments("formattedCode", obj,
                                                                                                        (method, on, args, keywords, _context, message) => {
                return(_context.runtime.NewText(((AssociatedCode)IokeObject.dataOf(on)).FormattedCode(method)));
            })));
        }
Exemplo n.º 11
0
        public override void Init(IokeObject obj)
        {
            Runtime runtime = obj.runtime;

            obj.Kind        = "Number Decimal";
            runtime.Decimal = obj;

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

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

            obj.RegisterMethod(runtime.NewNativeMethod("returns the square root of the receiver. this should return the same result as calling ** with 0.5",
                                                       new TypeCheckingNativeMethod.WithNoArguments("sqrt", obj,
                                                                                                    (method, on, args, keywords, context, message) => {
                BigDecimal value = ((Decimal)IokeObject.dataOf(on)).value;

                if (value.CompareTo(BigDecimal.ZERO) < 1)
                {
                    IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                 message,
                                                                                 context,
                                                                                 "Error",
                                                                                 "Arithmetic"), context).Mimic(message, context);
                    condition.SetCell("message", message);
                    condition.SetCell("context", context);
                    condition.SetCell("receiver", on);

                    context.runtime.ErrorCondition(condition);
                }

                return(runtime.NewDecimal(new BigSquareRoot().Get(value)));
            })));

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

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

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

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

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

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

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

                    return(context.runtime.NewNumber(Decimal.GetValue(on).CompareTo(Decimal.GetValue(arg))));
                }
            })));

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

                IokeData data = IokeObject.dataOf(arg);

                if (data is Number)
                {
                    return(context.runtime.NewDecimal(Decimal.GetValue(on).subtract(Number.GetValue(arg).AsBigDecimal())));
                }
                else
                {
                    if (!(data is Decimal))
                    {
                        arg = IokeObject.ConvertToDecimal(arg, message, context, true);
                    }

                    return(context.runtime.NewDecimal(Decimal.GetValue(on).subtract(Decimal.GetValue(arg))));
                }
            })));

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

                if (data is Number)
                {
                    return(context.runtime.NewDecimal(Decimal.GetValue(on).add(Number.GetValue(arg).AsBigDecimal())));
                }
                else
                {
                    if (!(data is Decimal))
                    {
                        arg = IokeObject.ConvertToDecimal(arg, message, context, true);
                    }

                    return(context.runtime.NewDecimal(Decimal.GetValue(on).add(Decimal.GetValue(arg))));
                }
            })));

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

                IokeData data = IokeObject.dataOf(arg);

                if (data is Number)
                {
                    return(context.runtime.NewDecimal(Decimal.GetValue(on).multiply(Number.GetValue(arg).AsBigDecimal())));
                }
                else
                {
                    if (!(data is Decimal))
                    {
                        arg = IokeObject.ConvertToDecimal(arg, message, context, true);
                    }

                    return(context.runtime.NewDecimal(Decimal.GetValue(on).multiply(Decimal.GetValue(arg))));
                }
            })));

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

                if (!(data is Number))
                {
                    arg = IokeObject.ConvertToRational(arg, message, context, true);
                }
                return(context.runtime.NewDecimal(Decimal.GetValue(on).pow(Number.IntValue(arg).intValue())));
            })));

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

                if (data is Number)
                {
                    return(context.runtime.NewDecimal(Decimal.GetValue(on).divide(Number.GetValue(arg).AsBigDecimal())));
                }
                else
                {
                    if (!(data is Decimal))
                    {
                        arg = IokeObject.ConvertToDecimal(arg, message, context, true);
                    }

                    while (Decimal.GetValue(arg).CompareTo(BigDecimal.ZERO) == 0)
                    {
                        IokeObject condition = IokeObject.As(IokeObject.GetCellChain(context.runtime.Condition,
                                                                                     message,
                                                                                     context,
                                                                                     "Error",
                                                                                     "Arithmetic",
                                                                                     "DivisionByZero"), context).Mimic(message, context);
                        condition.SetCell("message", message);
                        condition.SetCell("context", context);
                        condition.SetCell("receiver", on);

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

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

                    BigDecimal result = null;
                    try {
                        result = Decimal.GetValue(on).divide(Decimal.GetValue(arg), BigDecimal.ROUND_UNNECESSARY);
                    } catch (System.ArithmeticException) {
                        result = Decimal.GetValue(on).divide(Decimal.GetValue(arg), MathContext.DECIMAL128);
                    }
                    return(context.runtime.NewDecimal(result));
                }
            })));
        }
Exemplo n.º 12
0
Arquivo: Text.cs Projeto: tspring/ioke
        public override void Init(IokeObject obj)
        {
            Runtime runtime = obj.runtime;

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

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

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

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

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

            obj.RegisterMethod(runtime.NewNativeMethod("Takes any number of arguments, and expects the text receiver to contain format specifications. The currently supported specifications are only %s and %{, %}. These have several parameters that can be used. See the spec for more info about these. The format method will return a new text based on the content of the receiver, and the arguments given.",
                                                       new TypeCheckingNativeMethod("format", TypeCheckingArgumentsDefinition.builder()
                                                                                    .ReceiverMustMimic(obj)
                                                                                    .WithRest("replacements")
                                                                                    .Arguments,
                                                                                    (self, on, args, keywords, context, message) => {
                StringBuilder result = new StringBuilder();
                Format(on, message, context, args, result);
                return(context.runtime.NewText(result.ToString()));
            })));


            obj.RegisterMethod(obj.runtime.NewNativeMethod("Converts the content of this text into a rational value",
                                                           new TypeCheckingNativeMethod.WithNoArguments("toRational", obj,
                                                                                                        (self, on, args, keywords, context, message) => {
                return(Text.ToRational(on, context, message));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Converts the content of this text into a decimal value",
                                                           new TypeCheckingNativeMethod.WithNoArguments("toDecimal", obj,
                                                                                                        (self, on, args, keywords, context, message) => {
                return(Text.ToDecimal(on, context, message));
            })));

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

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

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a text where all non-safe characters have been replaced with safe ones",
                                                           new TypeCheckingNativeMethod.WithNoArguments("makeXMLSafe", obj,
                                                                                                        (self, on, args, keywords, context, message) => {
                return(self.runtime.NewText(new StringUtils().XmlSafe(Text.GetText(on))));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a lower case version of this text",
                                                           new TypeCheckingNativeMethod.WithNoArguments("lower", obj,
                                                                                                        (self, on, args, keywords, context, message) => {
                return(self.runtime.NewText(Text.GetText(on).ToLower()));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns an upper case version of this text",
                                                           new TypeCheckingNativeMethod.WithNoArguments("upper", obj,
                                                                                                        (self, on, args, keywords, context, message) => {
                return(self.runtime.NewText(Text.GetText(on).ToUpper()));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a version of this text with leading and trailing whitespace removed",
                                                           new TypeCheckingNativeMethod.WithNoArguments("trim", obj,
                                                                                                        (self, on, args, keywords, context, message) => {
                return(self.runtime.NewText(Text.GetText(on).Trim()));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns an array of texts split around the argument",
                                                           new TypeCheckingNativeMethod("split", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(obj)
                                                                                        .WithOptionalPositional("splitAround", "")
                                                                                        .Arguments,
                                                                                        (self, on, args, keywords, context, message) => {
                string real = Text.GetText(on);
                var r       = new SaneArrayList();
                Pattern p   = null;

                if (args.Count == 0)
                {
                    p = new Pattern("\\s");
                }
                else
                {
                    object arg = args[0];
                    if (IokeObject.dataOf(arg) is Regexp)
                    {
                        p = Regexp.GetRegexp(arg);
                    }
                    else
                    {
                        string around = Text.GetText(arg);
                        p             = new Pattern(Pattern.Quote(around));
                    }
                }

                RETokenizer tok  = new RETokenizer(p, real);
                tok.EmptyEnabled = false;
                while (tok.HasMore)
                {
                    r.Add(context.runtime.NewText(tok.NextToken));
                }

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

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Takes two text arguments where the first is the substring to replace, and the second is the replacement to insert. Will only replace the first match, if any is found, and return a new Text with the result.",
                                                           new TypeCheckingNativeMethod("replace", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(obj)
                                                                                        .WithRequiredPositional("pattern")
                                                                                        .WithRequiredPositional("replacement")
                                                                                        .Arguments,
                                                                                        (self, on, args, keywords, context, message) => {
                string initial = Text.GetText(on);
                string repl    = Text.GetText(args[1]);

                object arg = args[0];

                Pattern pat = null;
                if (IokeObject.dataOf(arg) is Regexp)
                {
                    pat = Regexp.GetRegexp(arg);
                }
                else
                {
                    string around = Text.GetText(arg);
                    pat           = new Pattern(Pattern.Quote(around));
                }

                Replacer r    = pat.Replacer(repl);
                string result = r.ReplaceFirst(initial);

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

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Takes two text arguments where the first is the substring to replace, and the second is the replacement to insert. Will replace all matches, if any is found, and return a new Text with the result.",
                                                           new TypeCheckingNativeMethod("replaceAll", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(obj)
                                                                                        .WithRequiredPositional("pattern")
                                                                                        .WithRequiredPositional("replacement")
                                                                                        .Arguments,
                                                                                        (self, on, args, keywords, context, message) => {
                string initial = Text.GetText(on);
                string repl    = Text.GetText(args[1]);

                object arg = args[0];

                Pattern pat = null;
                if (IokeObject.dataOf(arg) is Regexp)
                {
                    pat = Regexp.GetRegexp(arg);
                }
                else
                {
                    string around = Text.GetText(arg);
                    pat           = new Pattern(Pattern.Quote(around));
                }

                Replacer r    = pat.Replacer(repl);
                String result = r.Replace(initial);

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

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns the length of this text",
                                                           new TypeCheckingNativeMethod.WithNoArguments("length", obj,
                                                                                                        (self, on, args, keywords, context, message) => {
                return(context.runtime.NewNumber(GetText(on).Length));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("compares this text against the argument, returning -1, 0 or 1 based on which one is lexically larger",
                                                           new TypeCheckingNativeMethod("<=>", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(obj)
                                                                                        .WithRequiredPositional("other")
                                                                                        .Arguments,
                                                                                        (self, on, args, keywords, context, message) => {
                object arg = args[0];

                if (!(IokeObject.dataOf(arg) is Text))
                {
                    arg = IokeObject.ConvertToText(arg, message, context, false);
                    if (!(IokeObject.dataOf(arg) is Text))
                    {
                        // Can't compare, so bail out
                        return(context.runtime.nil);
                    }
                }

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

                int result = string.CompareOrdinal(Text.GetText(on), Text.GetText(arg));
                if (result < 0)
                {
                    result = -1;
                }
                else if (result > 0)
                {
                    result = 1;
                }

                return(context.runtime.NewNumber(result));
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("takes one argument, that can be either an index or a range of two indicis. this slicing works the same as for Lists, so you can index from the end, both with the single index and with the range.",
                                                           new TypeCheckingNativeMethod("[]", TypeCheckingArgumentsDefinition.builder()
                                                                                        .ReceiverMustMimic(obj)
                                                                                        .WithRequiredPositional("index")
                                                                                        .Arguments,
                                                                                        (self, on, args, keywords, context, message) => {
                object arg    = args[0];
                IokeData data = IokeObject.dataOf(arg);

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

                    if (first < 0)
                    {
                        return(context.runtime.NewText(""));
                    }

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

                    string str = GetText(on);
                    int size   = str.Length;

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

                    if (last < 0)
                    {
                        return(context.runtime.NewText(""));
                    }

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

                    if (first > last || (!inclusive && first == last))
                    {
                        return(context.runtime.NewText(""));
                    }

                    if (!inclusive)
                    {
                        last--;
                    }

                    return(context.runtime.NewText(str.Substring(first, (last + 1) - first)));
                }
                else if (data is Number)
                {
                    string str = GetText(on);
                    int len    = str.Length;

                    int ix = ((Number)data).AsNativeInteger();

                    if (ix < 0)
                    {
                        ix = len + ix;
                    }

                    if (ix >= 0 && ix < len)
                    {
                        return(context.runtime.NewNumber(str[ix]));
                    }
                    else
                    {
                        return(context.runtime.nil);
                    }
                }

                return(on);
            })));

            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a symbol representing the Unicode category of the character",
                                                           new TypeCheckingNativeMethod.WithNoArguments("category", obj,
                                                                                                        (self, on, args, keywords, context, message) => {
                string character = GetText(on);
                if (character.Length == 1)
                {
                    return(context.runtime.GetSymbol(UnicodeBlock.Of(character[0])));
                }

                IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition,
                                                                             message,
                                                                             context,
                                                                             "Error",
                                                                             "Default"), context).Mimic(message, context);
                condition.SetCell("message", message);
                condition.SetCell("context", context);
                condition.SetCell("receiver", on);
                condition.SetCell("text", context.runtime.NewText("Text does not contain exactly one character"));

                runtime.ErrorCondition(condition);
                return(null);
            })));
            obj.RegisterMethod(obj.runtime.NewNativeMethod("Returns a new text where all the escapes in the current text have been evaluated - exactly as if another parsing step had been applied. This does not evaluate embedded code, though.",
                                                           new TypeCheckingNativeMethod.WithNoArguments("evaluateEscapes", obj,
                                                                                                        (self, on, args, keywords, context, message) => {
                return(context.runtime.NewText(new StringUtils().ReplaceEscapes(GetText(on))));
            })));
        }