Skip to content

Commit

Permalink
[Truffle] String#ljust, #rjust and tons of infrastructure.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Mar 5, 2015
1 parent 8706662 commit 8534d9f
Show file tree
Hide file tree
Showing 13 changed files with 517 additions and 48 deletions.
9 changes: 0 additions & 9 deletions spec/truffle/tags/core/string/ljust_tags.txt

This file was deleted.

9 changes: 0 additions & 9 deletions spec/truffle/tags/core/string/rjust_tags.txt

This file was deleted.

Expand Up @@ -1342,33 +1342,6 @@ public Object rindex(RubyString string, RubyString subString, int endPosition) {
}
}

@CoreMethod(names = "rjust", required = 1, optional = 1, lowerFixnumParameters = 0)
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) {
notDesignedForCompilation();

return getContext().makeString(RubyString.rjust(string.toString(), length, " "));
}

@Specialization
public RubyString rjust(RubyString string, int length, RubyString padding) {
notDesignedForCompilation();

return getContext().makeString(RubyString.rjust(string.toString(), length, padding.toString()));
}

}

@CoreMethod(names = "swapcase")
public abstract static class SwapcaseNode extends CoreMethodNode {
public SwapcaseNode(RubyContext context, SourceSection sourceSection) {
Expand Down
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2015 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 org.jruby.truffle.nodes.rubinius;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.runtime.DebugOperations;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.truffle.runtime.core.RubyString;

public abstract class ModulePrimitiveNodes {

@RubiniusPrimitive(name = "module_mirror")
public abstract static class ModuleMirrorPrimitiveNode extends RubiniusPrimitiveNode {

@CompilerDirectives.CompilationFinal RubyModule stringMirror;

public ModuleMirrorPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public ModuleMirrorPrimitiveNode(ModuleMirrorPrimitiveNode prev) {
super(prev);
}

@Specialization
public RubyModule moduleMirror(RubyString string) {
if (stringMirror == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
final RubyModule rubinius = (RubyModule) getContext().getCoreLibrary().getObjectClass().getConstants().get("Rubinius").getValue();
final RubyModule mirror = (RubyModule) rubinius.getConstants().get("Mirror").getValue();
stringMirror = (RubyModule) mirror.getConstants().get("String").getValue();
}

return stringMirror;
}

}

}
Expand Up @@ -52,6 +52,7 @@ public static RubiniusPrimitiveManager create() {
nodeFactories.addAll(FloatPrimitiveNodesFactory.getFactories());
nodeFactories.addAll(EncodingPrimitiveNodesFactory.getFactories());
nodeFactories.addAll(RegexpPrimitiveNodesFactory.getFactories());
nodeFactories.addAll(ModulePrimitiveNodesFactory.getFactories());

final Map<String, RubiniusPrimitiveConstructor> primitives = new HashMap<>();

Expand Down
Expand Up @@ -6,6 +6,35 @@
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*
* Some of the code in this class is transliterated from C++ code in Rubinius.
*
* Copyright (c) 2007-2014, Evan Phoenix and contributors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Rubinius nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*

This comment has been minimized.

Copy link
@chrisseaton

chrisseaton Mar 5, 2015

Author Contributor

I copied some of the Rubinius C++ code and translated into Java, so I included the license here.

*/
package org.jruby.truffle.nodes.rubinius;

Expand All @@ -14,6 +43,7 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
import org.jcodings.Encoding;
import org.jcodings.exception.EncodingException;
import org.jcodings.specific.ASCIIEncoding;
import org.jruby.truffle.nodes.RubyNode;
Expand Down Expand Up @@ -321,4 +351,197 @@ public Object stringIndex(RubyString string, RubyString pattern, int start) {

}

@RubiniusPrimitive(name = "string_character_byte_index", needsSelf = false)
public static abstract class StringCharacterByteIndexPrimitiveNode extends RubiniusPrimitiveNode {

public StringCharacterByteIndexPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public StringCharacterByteIndexPrimitiveNode(StringCharacterByteIndexPrimitiveNode prev) {
super(prev);
}

@Specialization
public Object stringCharacterByteIndex(RubyString string, Object index, Object start) {
throw new UnsupportedOperationException("string_character_byte_index");
}

}

@RubiniusPrimitive(name = "string_byte_character_index", needsSelf = false)
public static abstract class StringByteCharacterIndexPrimitiveNode extends RubiniusPrimitiveNode {

public StringByteCharacterIndexPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public StringByteCharacterIndexPrimitiveNode(StringByteCharacterIndexPrimitiveNode prev) {
super(prev);
}

@Specialization
public Object stringByteCharacterIndex(RubyString string, Object index, Object start) {
throw new UnsupportedOperationException("string_byte_character_index");
}

}

@RubiniusPrimitive(name = "string_character_index", needsSelf = false)
public static abstract class StringCharacterIndexPrimitiveNode extends RubiniusPrimitiveNode {

public StringCharacterIndexPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public StringCharacterIndexPrimitiveNode(StringCharacterIndexPrimitiveNode prev) {
super(prev);
}

@Specialization
public Object stringCharacterIndex(RubyString string, Object indexedString, Object start) {
throw new UnsupportedOperationException("string_character_index");
}

}

@RubiniusPrimitive(name = "string_byte_index", needsSelf = false)
public static abstract class StringByteIndexPrimitiveNode extends RubiniusPrimitiveNode {

public StringByteIndexPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public StringByteIndexPrimitiveNode(StringByteIndexPrimitiveNode prev) {
super(prev);
}

@Specialization
public Object stringByteIndex(RubyString string, int characters, int start) {
if (string.getByteList().getEncoding().isSingleByte()) {
return characters - start;
} else {
final Encoding encoding = string.getByteList().getEncoding();
final int length = string.getByteList().length();

int count = 0;

int i;

for(i = 0; i < characters && count < length; i++) {
if(!encoding.isMbcHead(string.getByteList().getUnsafeBytes(), count, length)) {
count++;
} else {
count += encoding.codeToMbcLength(string.getByteList().getUnsafeBytes()[count]);
}
}

if(i < characters) {
return getContext().getCoreLibrary().getNilObject();
} else {
return count;
}
}
}

}

@RubiniusPrimitive(name = "string_previous_byte_index", needsSelf = false)
public static abstract class StringPreviousByteIndexPrimitiveNode extends RubiniusPrimitiveNode {

public StringPreviousByteIndexPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public StringPreviousByteIndexPrimitiveNode(StringPreviousByteIndexPrimitiveNode prev) {
super(prev);
}

@Specialization
public Object stringPreviousByteIndex(RubyString string, Object indexedString, Object start) {
throw new UnsupportedOperationException("string_previous_byte_index");
}

}

@RubiniusPrimitive(name = "string_copy_from", needsSelf = false)
public static abstract class StringCopyFromPrimitiveNode extends RubiniusPrimitiveNode {

public StringCopyFromPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public StringCopyFromPrimitiveNode(StringCopyFromPrimitiveNode prev) {
super(prev);
}

@Specialization
public RubyString stringCopyFrom(RubyString string, RubyString other, int start, int size, int dest) {
int src = start;
int dst = dest;
int cnt = size;

int osz = other.getByteList().length();
if(src >= osz) return string;
if(cnt < 0) return string;
if(src < 0) src = 0;
if(cnt > osz - src) cnt = osz - src;

int sz = string.getByteList().length();
if(dst >= sz) return string;
if(dst < 0) dst = 0;
if(cnt > sz - dst) cnt = sz - dst;

System.arraycopy(other.getByteList().unsafeBytes(), src, string.getByteList().getUnsafeBytes(), dest, cnt);

return string;
}

}

@RubiniusPrimitive(name = "string_resize_capacity", needsSelf = false)
public static abstract class StringResizeCapacityPrimitiveNode extends RubiniusPrimitiveNode {

public StringResizeCapacityPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public StringResizeCapacityPrimitiveNode(StringResizeCapacityPrimitiveNode prev) {
super(prev);
}

@Specialization
public Object stringResizeCapacity(RubyString string, Object capacity) {
throw new UnsupportedOperationException("string_resize_capacity");
}

}

@RubiniusPrimitive(name = "string_pattern")
public static abstract class StringPatternPrimitiveNode extends RubiniusPrimitiveNode {

public StringPatternPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public StringPatternPrimitiveNode(StringPatternPrimitiveNode prev) {
super(prev);
}

@Specialization
public RubyString stringPattern(RubyClass stringClass, int size, RubyString string) {
final byte[] bytes = new byte[size];
final byte[] stringBytes = string.getByteList().unsafeBytes();

if (string.getByteList().length() > 0) {
for (int n = 0; n < size; n += string.getByteList().length()) {
System.arraycopy(stringBytes, 0, bytes, n, Math.min(string.getByteList().length(), size - n));
}
}

return new RubyString(stringClass, new ByteList(bytes));
}

}

}
Expand Up @@ -469,8 +469,7 @@ private RubyNode translateRubiniusInvokePrimitive(SourceSection sourceSection, C
}

return new InvokeRubiniusPrimitiveNode(context, sourceSection,
primitive.getFactory().createNode(context, sourceSection, arguments.toArray(new RubyNode[arguments.size()])),
environment.getReturnID());
primitive.getFactory().createNode(context, sourceSection, arguments.toArray(new RubyNode[arguments.size()])));
}

private RubyNode translateRubiniusPrivately(SourceSection sourceSection, CallNode node) {
Expand Down
3 changes: 3 additions & 0 deletions truffle/src/main/ruby/core.rb
Expand Up @@ -12,6 +12,7 @@
require_relative 'core/rubinius/api/kernel/common/type'

# Patch rubinius-core-api to make it work for us
require_relative 'core/rubinius/api/shims/lookuptable'
require_relative 'core/rubinius/api/shims/array'
require_relative 'core/rubinius/api/shims/rubinius'
require_relative 'core/rubinius/api/shims/lookuptable'
Expand All @@ -22,6 +23,7 @@

# Load bootstrap (ordered according to Rubinius' load_order.txt)
require_relative 'core/rubinius/bootstrap/basic_object'
require_relative 'core/rubinius/bootstrap/mirror'
require_relative 'core/rubinius/bootstrap/false'
require_relative 'core/rubinius/bootstrap/gc'
require_relative 'core/rubinius/bootstrap/kernel'
Expand All @@ -35,6 +37,7 @@
require_relative 'core/rubinius/bootstrap/type'

# Load common (ordered according to Rubinius' load_order.txt)
require_relative 'core/rubinius/common/string_mirror'
require_relative 'core/rubinius/common/enumerator'
require_relative 'core/rubinius/common/enumerable'
require_relative 'core/rubinius/common/exception'
Expand Down
2 changes: 1 addition & 1 deletion truffle/src/main/ruby/core/rubinius/api/shims/array.rb
Expand Up @@ -7,7 +7,7 @@
# GNU Lesser General Public License version 2.1

module Rubinius
module Mirror
class Mirror
class Array

def self.reflect(array)
Expand Down

1 comment on commit 8534d9f

@chrisseaton
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nirvdrum take a look over the mirrors and new primitives and things in this commit

Please sign in to comment.