diff graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StringNodes.java @ 13514:0fbee3eb71f0

Ruby: import project.
author Chris Seaton <chris.seaton@oracle.com>
date Mon, 06 Jan 2014 17:12:09 +0000
parents
children f70c894ae874
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StringNodes.java	Mon Jan 06 17:12:09 2014 +0000
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.nodes.core;
+
+import java.util.*;
+import java.util.regex.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.core.*;
+import com.oracle.truffle.ruby.runtime.core.array.*;
+
+@CoreClass(name = "String")
+public abstract class StringNodes {
+
+    @CoreMethod(names = "+", minArgs = 1, maxArgs = 1)
+    public abstract static class AddNode extends CoreMethodNode {
+
+        public AddNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public AddNode(AddNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString add(RubyString a, RubyString b) {
+            return new RubyString(a.getRubyClass().getContext().getCoreLibrary().getStringClass(), a.toString() + b.toString());
+        }
+    }
+
+    @CoreMethod(names = {"==", "==="}, minArgs = 1, maxArgs = 1)
+    public abstract static class EqualNode extends CoreMethodNode {
+
+        public EqualNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public EqualNode(EqualNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public boolean equal(@SuppressWarnings("unused") RubyString a, @SuppressWarnings("unused") NilPlaceholder b) {
+            return false;
+        }
+
+        @Specialization
+        public boolean equal(RubyString a, RubyString b) {
+            return a.toString().equals(b.toString());
+        }
+    }
+
+    @CoreMethod(names = "!=", minArgs = 1, maxArgs = 1)
+    public abstract static class NotEqualNode extends CoreMethodNode {
+
+        public NotEqualNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public NotEqualNode(NotEqualNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public boolean equal(@SuppressWarnings("unused") RubyString a, @SuppressWarnings("unused") NilPlaceholder b) {
+            return true;
+        }
+
+        @Specialization
+        public boolean notEqual(RubyString a, RubyString b) {
+            return !a.toString().equals(b.toString());
+        }
+
+    }
+
+    @CoreMethod(names = "<=>", minArgs = 1, maxArgs = 1)
+    public abstract static class CompareNode extends CoreMethodNode {
+
+        public CompareNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public CompareNode(CompareNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public int compare(RubyString a, RubyString b) {
+            return a.toString().compareTo(b.toString());
+        }
+    }
+
+    @CoreMethod(names = "<<", minArgs = 1, maxArgs = 1)
+    public abstract static class ConcatNode extends CoreMethodNode {
+
+        public ConcatNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ConcatNode(ConcatNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString concat(RubyString string, RubyString other) {
+            string.replace(string.toString() + other.toString());
+            return string;
+        }
+    }
+
+    @CoreMethod(names = "%", minArgs = 1, maxArgs = 1, isSplatted = true)
+    public abstract static class FormatNode extends CoreMethodNode {
+
+        public FormatNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public FormatNode(FormatNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString format(RubyString format, Object[] args) {
+            final RubyContext context = getContext();
+
+            if (args.length == 1 && args[0] instanceof RubyArray) {
+                return context.makeString(StringFormatter.format(format.toString(), ((RubyArray) args[0]).asList()));
+            } else {
+                return context.makeString(StringFormatter.format(format.toString(), Arrays.asList(args)));
+            }
+        }
+    }
+
+    @CoreMethod(names = "[]", minArgs = 1, maxArgs = 2, isSplatted = true)
+    public abstract static class GetIndexNode extends CoreMethodNode {
+
+        public GetIndexNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public GetIndexNode(GetIndexNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public Object getIndex(RubyString string, Object[] args) {
+            return RubyString.getIndex(getContext(), string.toString(), args);
+        }
+    }
+
+    @CoreMethod(names = "=~", minArgs = 1, maxArgs = 1)
+    public abstract static class MatchOperatorNode extends CoreMethodNode {
+
+        public MatchOperatorNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public MatchOperatorNode(MatchOperatorNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public Object match(VirtualFrame frame, RubyString string, RubyRegexp regexp) {
+            return regexp.matchOperator(frame, string.toString());
+        }
+    }
+
+    @CoreMethod(names = "chomp", maxArgs = 0)
+    public abstract static class ChompNode extends CoreMethodNode {
+
+        public ChompNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ChompNode(ChompNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString chomp(RubyString string) {
+            return string.getRubyClass().getContext().makeString(string.toString().trim());
+        }
+    }
+
+    @CoreMethod(names = "chomp!", maxArgs = 0)
+    public abstract static class ChompBangNode extends CoreMethodNode {
+
+        public ChompBangNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ChompBangNode(ChompBangNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString chompBang(RubyString string) {
+            string.replace(string.toString().trim());
+            return string;
+        }
+    }
+
+    @CoreMethod(names = "downcase", maxArgs = 0)
+    public abstract static class DowncaseNode extends CoreMethodNode {
+
+        public DowncaseNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public DowncaseNode(DowncaseNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString downcase(RubyString string) {
+            return string.getRubyClass().getContext().makeString(string.toString().toLowerCase());
+        }
+    }
+
+    @CoreMethod(names = "downcase!", maxArgs = 0)
+    public abstract static class DowncaseBangNode extends CoreMethodNode {
+
+        public DowncaseBangNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public DowncaseBangNode(DowncaseBangNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString downcase(RubyString string) {
+            string.replace(string.toString().toLowerCase());
+            return string;
+        }
+    }
+
+    @CoreMethod(names = "empty?", maxArgs = 0)
+    public abstract static class EmptyNode extends CoreMethodNode {
+
+        public EmptyNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public EmptyNode(EmptyNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public boolean empty(RubyString string) {
+            return string.toString().isEmpty();
+        }
+    }
+
+    @CoreMethod(names = "end_with?", minArgs = 1, maxArgs = 1)
+    public abstract static class EndWithNode extends CoreMethodNode {
+
+        public EndWithNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public EndWithNode(EndWithNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public boolean endWith(RubyString string, RubyString b) {
+            return string.toString().endsWith(b.toString());
+        }
+    }
+
+    @CoreMethod(names = "gsub", minArgs = 2, maxArgs = 2)
+    public abstract static class GsubNode extends CoreMethodNode {
+
+        public GsubNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public GsubNode(GsubNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString gsub(RubyString string, RubyString regexpString, RubyString replacement) {
+            final RubyRegexp regexp = new RubyRegexp(getContext().getCoreLibrary().getRegexpClass(), regexpString.toString());
+            return gsub(string, regexp, replacement);
+        }
+
+        @Specialization
+        public RubyString gsub(RubyString string, RubyRegexp regexp, RubyString replacement) {
+            return getContext().makeString(regexp.getPattern().matcher(string.toString()).replaceAll(replacement.toString()));
+        }
+    }
+
+    @CoreMethod(names = "inspect", maxArgs = 0)
+    public abstract static class InpsectNode extends CoreMethodNode {
+
+        public InpsectNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public InpsectNode(InpsectNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString inspect(RubyString string) {
+            return getContext().makeString("\"" + string.toString().replace("\\", "\\\\").replace("\"", "\\\"") + "\"");
+        }
+    }
+
+    @CoreMethod(names = "ljust", minArgs = 1, maxArgs = 2)
+    public abstract static class LjustNode extends CoreMethodNode {
+
+        public LjustNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public LjustNode(LjustNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString ljust(RubyString string, int length, @SuppressWarnings("unused") UndefinedPlaceholder padding) {
+            return getContext().makeString(RubyString.ljust(string.toString(), length, " "));
+        }
+
+        @Specialization
+        public RubyString ljust(RubyString string, int length, RubyString padding) {
+            return getContext().makeString(RubyString.ljust(string.toString(), length, padding.toString()));
+        }
+
+    }
+
+    @CoreMethod(names = "size", maxArgs = 0)
+    public abstract static class SizeNode extends CoreMethodNode {
+
+        public SizeNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public SizeNode(SizeNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public int size(RubyString string) {
+            return string.toString().length();
+        }
+    }
+
+    @CoreMethod(names = "match", minArgs = 1, maxArgs = 1)
+    public abstract static class MatchNode extends CoreMethodNode {
+
+        public MatchNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public MatchNode(MatchNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public Object match(RubyString string, RubyString regexpString) {
+            final RubyRegexp regexp = new RubyRegexp(getContext().getCoreLibrary().getRegexpClass(), regexpString.toString());
+            return regexp.match(string.toString());
+        }
+
+        @Specialization
+        public Object match(RubyString string, RubyRegexp regexp) {
+            return regexp.match(string.toString());
+        }
+    }
+
+    @CoreMethod(names = "rjust", minArgs = 1, maxArgs = 2)
+    public abstract static class RjustNode extends CoreMethodNode {
+
+        public RjustNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public RjustNode(RjustNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString rjust(RubyString string, int length, @SuppressWarnings("unused") UndefinedPlaceholder padding) {
+            return getContext().makeString(RubyString.rjust(string.toString(), length, " "));
+        }
+
+        @Specialization
+        public RubyString rjust(RubyString string, int length, RubyString padding) {
+            return getContext().makeString(RubyString.rjust(string.toString(), length, padding.toString()));
+        }
+
+    }
+
+    @CoreMethod(names = "scan", minArgs = 1, maxArgs = 1)
+    public abstract static class ScanNode extends CoreMethodNode {
+
+        public ScanNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ScanNode(ScanNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyArray scan(RubyString string, RubyString regexp) {
+            return RubyString.scan(getContext(), string.toString(), Pattern.compile(regexp.toString()));
+        }
+
+        @Specialization
+        public RubyArray scan(RubyString string, RubyRegexp regexp) {
+            return RubyString.scan(getContext(), string.toString(), regexp.getPattern());
+        }
+
+    }
+
+    @CoreMethod(names = "split", minArgs = 1, maxArgs = 1)
+    public abstract static class SplitNode extends CoreMethodNode {
+
+        public SplitNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public SplitNode(SplitNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyArray split(RubyString string, RubyString sep) {
+            final RubyContext context = getContext();
+
+            final String[] components = string.toString().split(Pattern.quote(sep.toString()));
+
+            final Object[] objects = new Object[components.length];
+
+            for (int n = 0; n < objects.length; n++) {
+                objects[n] = context.makeString(components[n]);
+            }
+
+            return RubyArray.specializedFromObjects(context.getCoreLibrary().getArrayClass(), objects);
+        }
+
+        @Specialization
+        public RubyArray split(RubyString string, RubyRegexp sep) {
+            final RubyContext context = getContext();
+
+            final String[] components = string.toString().split(sep.getPattern().pattern());
+
+            final Object[] objects = new Object[components.length];
+
+            for (int n = 0; n < objects.length; n++) {
+                objects[n] = context.makeString(components[n]);
+            }
+
+            return RubyArray.specializedFromObjects(context.getCoreLibrary().getArrayClass(), objects);
+        }
+    }
+
+    @CoreMethod(names = "start_with?", minArgs = 1, maxArgs = 1)
+    public abstract static class StartWithNode extends CoreMethodNode {
+
+        public StartWithNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public StartWithNode(StartWithNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public boolean endWith(RubyString string, RubyString b) {
+            return string.toString().startsWith(b.toString());
+        }
+    }
+
+    @CoreMethod(names = "to_f", maxArgs = 0)
+    public abstract static class ToFNode extends CoreMethodNode {
+
+        public ToFNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ToFNode(ToFNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public double toF(RubyString string) {
+            return Double.parseDouble(string.toString());
+        }
+    }
+
+    @CoreMethod(names = "to_i", maxArgs = 0)
+    public abstract static class ToINode extends CoreMethodNode {
+
+        public ToINode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ToINode(ToINode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public Object toI(RubyString string) {
+            return string.toInteger();
+        }
+    }
+
+    @CoreMethod(names = "to_s", maxArgs = 0)
+    public abstract static class ToSNode extends CoreMethodNode {
+
+        public ToSNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ToSNode(ToSNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubyString toF(RubyString string) {
+            return string;
+        }
+    }
+
+    @CoreMethod(names = {"to_sym", "intern"}, maxArgs = 0)
+    public abstract static class ToSymNode extends CoreMethodNode {
+
+        public ToSymNode(RubyContext context, SourceSection sourceSection) {
+            super(context, sourceSection);
+        }
+
+        public ToSymNode(ToSymNode prev) {
+            super(prev);
+        }
+
+        @Specialization
+        public RubySymbol toSym(RubyString string) {
+            return new RubySymbol(getContext().getCoreLibrary().getSymbolClass(), string.toString());
+        }
+    }
+
+}