Exemple #1
0
        private static void AddRegexp(object o, StringBuilder sb)
        {
            string f      = Regexp.GetFlags(o);
            string nflags = "";

            if (f.IndexOf("i") == -1)
            {
                nflags += "i";
            }
            if (f.IndexOf("x") == -1)
            {
                nflags += "x";
            }
            if (f.IndexOf("m") == -1)
            {
                nflags += "m";
            }
            if (f.IndexOf("u") == -1)
            {
                nflags += "u";
            }
            if (f.IndexOf("s") == -1)
            {
                nflags += "s";
            }
            if (nflags.Length > 0)
            {
                nflags = "-" + nflags;
            }
            sb.Append("(?").Append(f).Append(nflags).Append(":").Append(Regexp.GetPattern(o)).Append(")");
        }
Exemple #2
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);
                }
            })));
        }
Exemple #3
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));
            })));
        }
Exemple #4
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);
            })));
        }
Exemple #5
0
        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))));
            })));
        }