@Specialization(guards = "isIntegerFixnumRange(range)") public Object getIndex(DynamicObject matchData, DynamicObject range, NotProvided len) { final Object[] values = getValues(matchData); final int normalizedIndex = ArrayNodes.normalizeIndex(values.length, Layouts.INTEGER_FIXNUM_RANGE.getBegin(range)); final int end = ArrayNodes.normalizeIndex(values.length, Layouts.INTEGER_FIXNUM_RANGE.getEnd(range)); final int exclusiveEnd = ArrayNodes.clampExclusiveIndex( values.length, Layouts.INTEGER_FIXNUM_RANGE.getExcludedEnd(range) ? end : end + 1); final int length = exclusiveEnd - normalizedIndex; final Object[] store = Arrays.copyOfRange(values, normalizedIndex, normalizedIndex + length); return createArray(store, length); }
@Specialization public DynamicObject toA(DynamicObject matchData) { CompilerDirectives.transferToInterpreter(); return ArrayNodes.fromObjects( getContext().getCoreLibrary().getArrayClass(), getValues(matchData)); }
@TruffleBoundary private Object[] unsplat(Object[] argumentsObjects) { // TOOD(CS): what is the error behaviour here? assert argumentsObjects.length == 1; assert RubyGuards.isRubyArray(argumentsObjects[0]); return ArrayNodes.slowToArray(((RubyBasicObject) argumentsObjects[0])); }
@Specialization public Object getIndex(DynamicObject matchData, int index, int length) { CompilerDirectives.transferToInterpreter(); // TODO BJF 15-May-2015 Need to handle negative indexes and lengths and out of bounds final Object[] values = getValues(matchData); final int normalizedIndex = ArrayNodes.normalizeIndex(values.length, index); final Object[] store = Arrays.copyOfRange(values, normalizedIndex, normalizedIndex + length); return createArray(store, length); }
@Specialization public Object getIndex(DynamicObject matchData, int index, NotProvided length) { CompilerDirectives.transferToInterpreter(); final Object[] values = getValues(matchData); final int normalizedIndex = ArrayNodes.normalizeIndex(values.length, index); if ((normalizedIndex < 0) || (normalizedIndex >= values.length)) { return nil(); } else { return values[normalizedIndex]; } }
public boolean require(String feature, Node currentNode) throws IOException { final RubyConstant dataConstantBefore = ModuleOperations.lookupConstant( context, LexicalScope.NONE, context.getCoreLibrary().getObjectClass(), "DATA"); if (feature.startsWith("./")) { final String cwd = context.getRuntime().getCurrentDirectory(); feature = cwd + "/" + feature.substring(2); } else if (feature.startsWith("../")) { final String cwd = context.getRuntime().getCurrentDirectory(); feature = cwd.substring(0, cwd.lastIndexOf('/')) + "/" + feature.substring(3); } try { if (isAbsolutePath(feature)) { // Try as a full path if (requireInPath(null, feature, currentNode)) { return true; } } else { // Try each load path in turn for (Object pathObject : ArrayNodes.slowToArray(context.getCoreLibrary().getLoadPath())) { String loadPath = pathObject.toString(); if (!isAbsolutePath(loadPath)) { loadPath = expandPath(context, loadPath); } if (requireInPath(loadPath, feature, currentNode)) { return true; } } } throw new RaiseException(context.getCoreLibrary().loadErrorCannotLoad(feature, currentNode)); } finally { if (dataConstantBefore == null) { context.getCoreLibrary().getObjectClass().removeConstant(currentNode, "DATA"); } else { context .getCoreLibrary() .getObjectClass() .setConstant(currentNode, "DATA", dataConstantBefore.getValue()); } } }
private boolean requireFile(String feature, String path, Node currentNode) throws IOException { // We expect '/' in various classpath URLs, so normalize Windows file paths to use '/' path = path.replace('\\', '/'); final RubyBasicObject loadedFeatures = context.getCoreLibrary().getLoadedFeatures(); if (path.startsWith("uri:classloader:/")) { // TODO CS 13-Feb-15 this uri:classloader:/ and core:/ thing is a hack - simplify it for (Object loaded : Arrays.asList(ArrayNodes.slowToArray(loadedFeatures))) { if (loaded.toString().equals(path)) { return true; } } String coreFileName = path.substring("uri:classloader:/".length()); coreFileName = FileSystems.getDefault().getPath(coreFileName).normalize().toString(); if (context .getRuntime() .getLoadService() .getClassPathResource(context.getRuntime().getJRubyClassLoader(), coreFileName) == null) { return false; } if (SHOW_RESOLUTION) { System.err.printf("resolved %s -> %s%n", feature, coreFileName); } context.getCoreLibrary().loadRubyCore(coreFileName, "uri:classloader:/"); ArrayNodes.slowPush( loadedFeatures, StringNodes.createString(context.getCoreLibrary().getStringClass(), path)); return true; } else if (path.startsWith("core:/")) { for (Object loaded : Arrays.asList(ArrayNodes.slowToArray(loadedFeatures))) { if (loaded.toString().equals(path)) { return true; } } final String coreFileName = path.substring("core:/".length()); if (context .getRuntime() .getLoadService() .getClassPathResource(context.getRuntime().getJRubyClassLoader(), coreFileName) == null) { return false; } if (SHOW_RESOLUTION) { System.err.printf("resolved %s -> %s%n", feature, coreFileName); } context.getCoreLibrary().loadRubyCore(coreFileName, "core:/"); ArrayNodes.slowPush( loadedFeatures, StringNodes.createString(context.getCoreLibrary().getStringClass(), path)); return true; } else { final File file = new File(path); assert file.isAbsolute(); if (!file.isAbsolute() || !file.isFile()) { return false; } final String expandedPath = expandPath(context, path); for (Object loaded : Arrays.asList(ArrayNodes.slowToArray(loadedFeatures))) { if (loaded.toString().equals(expandedPath)) { return true; } } if (SHOW_RESOLUTION) { System.err.printf("resolved %s -> %s%n", feature, expandedPath); } // TODO (nirvdrum 15-Jan-15): If we fail to load, we should remove the path from the loaded // features because subsequent requires of the same statement may succeed. final RubyBasicObject pathString = StringNodes.createString(context.getCoreLibrary().getStringClass(), expandedPath); ArrayNodes.slowPush(loadedFeatures, pathString); try { context.loadFile(path, currentNode); } catch (RaiseException e) { final ArrayMirror mirror = ArrayMirror.reflect((Object[]) ArrayNodes.getStore(loadedFeatures)); final int length = ArrayNodes.getSize(loadedFeatures); for (int i = length - 1; i >= 0; i--) { if (mirror.get(i) == pathString) { for (int j = length - 1; j > i; j--) { mirror.set(i - 1, mirror.get(i)); } ArrayNodes.setSize(loadedFeatures, length - 1); break; } } throw e; } } return true; }