From 84c6cdd4d3470d510bf9f9aa5ed6663aab699f90 Mon Sep 17 00:00:00 2001 From: "Prahlad Joshi joshi18@purdue.edu" <Prahlad Joshi joshi18@purdue.edu> Date: Sun, 23 Feb 2014 21:58:32 -0500 Subject: [PATCH] Adding support for S3 class attribute --- .../r/nodes/builtin/base/BasePackage.java | 2 + .../r/nodes/builtin/base/GetClass.java | 29 +++ .../r/nodes/builtin/base/IsObject.java | 3 +- .../r/nodes/builtin/base/UpdateAttr.java | 3 + .../r/nodes/builtin/base/UpdateClass.java | 217 ++++++++++++++++++ .../r/nodes/builtin/base/UseMethod.java | 185 +++++++++++---- .../com/oracle/truffle/r/runtime/RError.java | 18 +- .../oracle/truffle/r/runtime/RRuntime.java | 6 + .../r/runtime/data/RComplexVector.java | 6 + .../r/runtime/data/RDoubleSequence.java | 12 + .../truffle/r/runtime/data/RDoubleVector.java | 6 + .../truffle/r/runtime/data/RIntSequence.java | 11 + .../truffle/r/runtime/data/RIntVector.java | 7 + .../oracle/truffle/r/runtime/data/RList.java | 7 + .../r/runtime/data/RLogicalVector.java | 7 + .../truffle/r/runtime/data/RRawVector.java | 7 + .../truffle/r/runtime/data/RSequence.java | 8 + .../truffle/r/runtime/data/RStringVector.java | 7 + .../truffle/r/runtime/data/RVector.java | 20 ++ .../data/closures/RToVectorClosure.java | 11 + .../r/runtime/data/model/RAbstractVector.java | 6 + mx.fastr/copyrights/overrides | 2 + 22 files changed, 527 insertions(+), 53 deletions(-) create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java index 987847822b..5c9bfbb185 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java @@ -88,6 +88,7 @@ public class BasePackage extends RPackage { load(Exists.class); load(Floor.class); load(Get.class); + load(GetClass.class); load(Gregexpr.class); load(GSub.class); load(Ifelse.class); @@ -166,6 +167,7 @@ public class BasePackage extends RPackage { load(Unlist.class); load(UpdateAttr.class); load(UpdateAttributes.class); + load(UpdateClass.class); load(UpdateDiag.class); load(UpdateDim.class); load(UpdateDimNames.class); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java new file mode 100644 index 0000000000..edb1088261 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java @@ -0,0 +1,29 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (c) 2014, Purdue University + * Copyright (c) 2014, Oracle and/or its affiliates + * + * All rights reserved. + */ + +package com.oracle.truffle.r.nodes.builtin.base; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.data.model.*; + +@RBuiltin(value = "class") +public abstract class GetClass extends RBuiltinNode { + @Specialization + public Object getClass(VirtualFrame frame, RAbstractVector arg) { + if (arg.isObject()) { + return arg.getAttributes().get(RRuntime.CLASS_ATTR_KEY); + } + return arg.getClassHierarchy().get(0); + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsObject.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsObject.java index 9726598a29..33e2ac4c34 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsObject.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/IsObject.java @@ -40,9 +40,8 @@ public abstract class IsObject extends RBuiltinNode { } @Specialization - @SuppressWarnings("unused") public byte isObject(RAbstractVector arg) { Map<String, Object> attributes = arg.getAttributes(); - return (attributes != null && attributes.get(RRuntime.CLASS_ATTR_KEY) != null) ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; + return arg.isObject() ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java index ce0694b512..f55139c0bb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java @@ -120,6 +120,9 @@ public abstract class UpdateAttr extends RBuiltinNode { } else if (name.equals(RRuntime.DIMNAMES_ATTR_KEY)) { return updateDimNames(frame, resultVector, value); } else { + if (name.equals(RRuntime.CLASS_ATTR_KEY) && !(value instanceof RString && value instanceof RStringVector)) { + RError.getInvalidClassAttr(getEncapsulatingSourceSection()); + } if (resultVector.getAttributes() == null) { resultVector.setAttributes(new LinkedHashMap<String, Object>()); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java new file mode 100644 index 0000000000..9d51e8beef --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java @@ -0,0 +1,217 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (c) 2014, Purdue University + * Copyright (c) 2014, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.nodes.builtin.base; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.r.nodes.unary.*; +import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; + +@RBuiltin(value = "class<-") +public abstract class UpdateClass extends RBuiltinNode { + + private RVector resultVector; + @Child private CastStringNode castStringNode; + @Child private CastComplexNode castComplexNode; + @Child private CastDoubleNode castDoubleNode; + @Child private CastIntegerNode castIntegerNode; + @Child private CastLogicalNode castLogicalNode; + @Child private CastRawNode castRawNode; + + private void initCastString() { + if (castStringNode == null) { + CompilerDirectives.transferToInterpreter(); + castStringNode = adoptChild(CastStringNodeFactory.create(null, false, false, false)); + } + } + + private void initCastComplex() { + if (castComplexNode == null) { + CompilerDirectives.transferToInterpreter(); + castComplexNode = adoptChild(CastComplexNodeFactory.create(null, false, false)); + } + } + + private void initCastDouble() { + if (castDoubleNode == null) { + CompilerDirectives.transferToInterpreter(); + castDoubleNode = adoptChild(CastDoubleNodeFactory.create(null, false, false)); + } + } + + private void initCastInteger() { + if (castIntegerNode == null) { + CompilerDirectives.transferToInterpreter(); + castIntegerNode = adoptChild(CastIntegerNodeFactory.create(null, false, false)); + } + } + + private void initCastLogical() { + if (castLogicalNode == null) { + CompilerDirectives.transferToInterpreter(); + castLogicalNode = adoptChild(CastLogicalNodeFactory.create(null, false, false)); + } + } + + private void initCastRaw() { + if (castRawNode == null) { + CompilerDirectives.transferToInterpreter(); + castRawNode = adoptChild(CastRawNodeFactory.create(null, false, false)); + } + } + + private RStringVector castStringVector(VirtualFrame frame, RAbstractVector o) { + initCastString(); + return (RStringVector) castStringNode.executeStringVector(frame, o); + } + + @Specialization + public Object setClass(VirtualFrame frame, RAbstractVector arg, RAbstractVector className) { + if (className.getLength() == 0) { + return setClass(frame, arg, RNull.instance); + } + return setClass(frame, arg, castStringVector(frame, className)); + } + + @Specialization + public Object setClass(VirtualFrame frame, RAbstractVector arg, RStringVector className) { + if (className.getLength() > 1) { + Map<String, Object> attrb = getAttributes(arg); + attrb.put(RRuntime.CLASS_ATTR_KEY, className); + return resultVector; + } + return setClassHelper(frame, arg, className.getDataAt(0)); + } + + @Specialization + public Object setClass(VirtualFrame frame, RAbstractVector arg, RNull className) { + Map<String, Object> attrb = getAttributes(arg); + if (attrb != null) { + attrb.remove(RRuntime.CLASS_ATTR_KEY); + } + return resultVector; + } + + @Specialization + public Object setClass(VirtualFrame frame, RAbstractLogicalVector arg, String className) { + if (className.equals(RRuntime.TYPE_LOGICAL)) { + return arg; + } + return setClassHelper(frame, arg, className); + } + + @Specialization + public Object setClass(VirtualFrame frame, RAbstractStringVector arg, String className) { + if (className.equals(RRuntime.TYPE_CHARACTER)) { + return arg; + } + return setClassHelper(frame, arg, className); + } + + @Specialization + public Object setClass(VirtualFrame frame, RAbstractComplexVector arg, String className) { + if (className.equals(RRuntime.TYPE_COMPLEX)) { + return arg; + } + return setClassHelper(frame, arg, className); + } + + @Specialization + public Object setClass(VirtualFrame frame, RAbstractDoubleVector arg, String className) { + if (className.equals(RRuntime.TYPE_DOUBLE) || className.equals(RRuntime.TYPE_NUMERIC)) { + return arg; + } + return setClassHelper(frame, arg, className); + } + + @Specialization + public Object setClass(VirtualFrame frame, RAbstractIntVector arg, String className) { + if (className.equals(RRuntime.TYPE_INTEGER) || className.equals(RRuntime.TYPE_NUMERIC)) { + return arg; + } + return setClassHelper(frame, arg, className); + } + + @Specialization + public Object setClass(VirtualFrame frame, RAbstractRawVector arg, String className) { + if (className.equals(RRuntime.TYPE_RAW)) { + return arg; + } + return setClassHelper(frame, arg, className); + } + + @Specialization + public Object setClassHelper(VirtualFrame frame, RAbstractVector arg, String className) { + if (className.equals(RRuntime.TYPE_CHARACTER)) { + initCastString(); + return castStringNode.executeString(frame, arg); + } + if (className.equals(RRuntime.TYPE_COMPLEX)) { + initCastComplex(); + return castComplexNode.executeComplex(frame, arg); + } + if (className.equals(RRuntime.TYPE_DOUBLE)) { + initCastDouble(); + return castDoubleNode.executeDouble(frame, arg); + } + if (className.equals(RRuntime.TYPE_INTEGER)) { + initCastInteger(); + return castIntegerNode.executeInt(frame, arg); + } + if (className.equals(RRuntime.TYPE_LOGICAL)) { + initCastLogical(); + return castLogicalNode.executeCast(frame, arg); + } + if (className.equals(RRuntime.TYPE_RAW)) { + initCastRaw(); + return castRawNode.executeRaw(frame, arg); + } + if (className.equals(RRuntime.TYPE_NUMERIC)) { + initCastDouble(); + return castDoubleNode.executeDouble(frame, arg); + } + if (className.equals(RRuntime.TYPE_MATRIX)) { + if (RRuntime.isMatrix(arg)) { + return setClass(frame, arg, RNull.instance); + } + throw RError.getNotMatixUpdateClass(getEncapsulatingSourceSection(), arg.getDimensions().length); + + } + if (className.equals(RRuntime.TYPE_ARRAY)) { + if (arg.getDimensions().length > 0) { + return setClass(frame, arg, RNull.instance); + } + throw RError.getNotArrayUpdateClass(getEncapsulatingSourceSection()); + } + Map<String, Object> attrb = getAttributes(arg); + attrb.put(RRuntime.CLASS_ATTR_KEY, className); + return resultVector; + } + + private Map<String, Object> getAttributes(RAbstractVector arg) { + resultVector = arg.materialize(); + if (resultVector.isShared()) { + resultVector = resultVector.copy(); + } + Map<String, Object> attrb = resultVector.getAttributes(); + if (attrb == null) { + attrb = new LinkedHashMap<>(); + resultVector.setAttributes((LinkedHashMap<String, Object>) attrb); + } + return attrb; + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java index 6fb71d3af2..79fb89a1be 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java @@ -49,73 +49,125 @@ public abstract class UseMethod extends RBuiltinNode { return new RNode[]{ConstantNode.create(RMissing.instance), ConstantNode.create(RMissing.instance)}; } - // TODO: Matrix, arrays, integers, strings etc have default class types so there should be a -// specialization for each one of them. - @Specialization public Object useMethod(VirtualFrame frame, String generic, RAbstractVector arg) { + if (arg.isObject()) { + final Object classAttrb = arg.getAttributes().get(RRuntime.CLASS_ATTR_KEY); + if (classAttrb instanceof RStringVector) { + RStringVector classNames = (RStringVector) classAttrb; + return useMethodHelper(frame, generic, classNames); + } + return useMethodHelper(frame, generic, (String) classAttrb); + } else { + return useMethodHelper(frame, generic, arg.getClassHierarchy()); + } + } - final Map<String, Object> attributes = arg.getAttributes(); - final Object classAttrb = attributes.get(RRuntime.CLASS_ATTR_KEY); - VirtualFrame newFrame = null; - if (classAttrb instanceof RStringVector) { - RStringVector classNames = (RStringVector) classAttrb; - for (int i = 0; i < classNames.getLength() && newFrame == null; ++i) { - newFrame = findFunction(classNames.getDataAt(i), generic, frame); + /* + * If only one argument is passed to UseMethod, the first argument of enclosing function is used + * to resolve the generic. + */ + @Specialization + public Object useMethod(VirtualFrame frame, String generic, @SuppressWarnings("unused") RMissing arg) { + RArguments args = frame.getArguments(RArguments.class); + if (args == null || args.getLength() == 0 || args.getArgument(0) == null) { + throw RError.getUnknownFunctionUseMethod(getEncapsulatingSourceSection(), generic, RNull.instance.toString()); + } + Object enclosingArg = args.getArgument(0); + if (enclosingArg instanceof Byte) { + return useMethod(frame, generic, (byte) enclosingArg); + } + if (enclosingArg instanceof String) { + return useMethod(frame, generic, (String) enclosingArg); + } + if (enclosingArg instanceof Integer) { + return useMethod(frame, generic, (int) enclosingArg); + } + if (enclosingArg instanceof Double) { + return useMethod(frame, generic, (double) enclosingArg); + } + return useMethod(frame, generic, (RAbstractVector) enclosingArg); + } + + @Specialization + public Object useMethod(VirtualFrame frame, String generic, byte arg) { + return useMethodHelper(frame, generic, RRuntime.TYPE_LOGICAL); + } + + @Specialization + public Object useMethod(VirtualFrame frame, String generic, String arg) { + return useMethodHelper(frame, generic, RRuntime.TYPE_CHARACTER); + } + + @Specialization + public Object useMethod(VirtualFrame frame, String generic, int arg) { + return useMethodHelper(frame, generic, RRuntime.CLASS_INTEGER); + } + + @Specialization + public Object useMethod(VirtualFrame frame, String generic, double arg) { + return useMethodHelper(frame, generic, RRuntime.CLASS_DOUBLE); + } + + private Object useMethodHelper(VirtualFrame frame, String generic, String className) { + VirtualFrame newFrame = findFunction(className, generic, frame); + if (newFrame == null) { + newFrame = findFunction(RRuntime.DEFAULT, generic, frame); + if (newFrame == null) { + throw RError.getUnknownFunctionUseMethod(getEncapsulatingSourceSection(), generic, className); } } - if (classAttrb instanceof String) { - newFrame = findFunction((String) classAttrb, generic, frame); + return dispatchMethod(frame, newFrame); + } + + private Object useMethodHelper(VirtualFrame frame, String generic, String[] classNames) { + VirtualFrame newFrame = null; + for (final String className : classNames) { + newFrame = findFunction(className, generic, frame); + if (newFrame != null) { + break; + } } if (newFrame == null) { newFrame = findFunction(RRuntime.DEFAULT, generic, frame); if (newFrame == null) { - throw RError.getUnknownFunctionUseMethod(getEncapsulatingSourceSection(), generic, classAttrb.toString()); + throw RError.getUnknownFunctionUseMethod(getEncapsulatingSourceSection(), generic, Arrays.toString(classNames)); } } - // Copy the variables defined(prior to call to UseMethod) in the current frame to the new - // frame - for (FrameSlot fs : frame.getFrameDescriptor().getSlots()) { - switch (fs.getKind()) { - case Object: - newFrame.setObject(fs, FrameUtil.getObjectSafe(frame, fs)); - break; - case Int: - newFrame.setInt(fs, FrameUtil.getIntSafe(frame, fs)); - break; - case Byte: - newFrame.setByte(fs, FrameUtil.getByteSafe(frame, fs)); - break; - case Long: - newFrame.setLong(fs, FrameUtil.getLongSafe(frame, fs)); - break; - case Double: - newFrame.setDouble(fs, FrameUtil.getDoubleSafe(frame, fs)); - break; - case Float: - newFrame.setFloat(fs, FrameUtil.getFloatSafe(frame, fs)); - break; - case Boolean: - newFrame.setBoolean(fs, FrameUtil.getBooleanSafe(frame, fs)); - break; + return dispatchMethod(frame, newFrame); + } + + private Object useMethodHelper(VirtualFrame frame, String generic, List<String> classNames) { + VirtualFrame newFrame = null; + for (final String className : classNames) { + newFrame = findFunction(className, generic, frame); + if (newFrame != null) { + break; } } - return funcDefnNode.execute(newFrame); + if (newFrame == null) { + newFrame = findFunction(RRuntime.DEFAULT, generic, frame); + if (newFrame == null) { + throw RError.getUnknownFunctionUseMethod(getEncapsulatingSourceSection(), generic, classNames.toString()); + } + } + return dispatchMethod(frame, newFrame); } - /* - * If only one argument is passed to UseMethod, the first argument of enclosing function is used - * to resolve the generic. - */ - @Specialization - public Object useMethod(VirtualFrame frame, String generic, RMissing arg) { - RAbstractVector enclosingArg = (RAbstractVector) frame.getArguments(RArguments.class).getArgument(0); - return useMethod(frame, generic, enclosingArg); + private Object useMethodHelper(VirtualFrame frame, String generic, RStringVector classNames) { + VirtualFrame newFrame = null; + for (int i = 0; i < classNames.getLength() && newFrame == null; ++i) { + newFrame = findFunction(classNames.getDataAt(i), generic, frame); + } + if (newFrame == null) { + newFrame = findFunction(RRuntime.DEFAULT, generic, frame); + if (newFrame == null) { + throw RError.getUnknownFunctionUseMethod(getEncapsulatingSourceSection(), generic, classNames.toString()); + } + } + return dispatchMethod(frame, newFrame); } - /* - * @Specialization public Object useMethod(VirtualFrame frame, String generic, RDouble arg) { } - */ private VirtualFrame findFunction(final String className, final String generic, VirtualFrame frame) { StringBuilder sbFuncName = new StringBuilder(generic); sbFuncName.append("."); @@ -142,4 +194,37 @@ public abstract class UseMethod extends RBuiltinNode { } return null; } + + private Object dispatchMethod(VirtualFrame frame, VirtualFrame newFrame) { + + // Copy the variables defined(prior to call to UseMethod) in the current frame to the new + // frame + for (FrameSlot fs : frame.getFrameDescriptor().getSlots()) { + switch (fs.getKind()) { + case Object: + newFrame.setObject(fs, FrameUtil.getObjectSafe(frame, fs)); + break; + case Int: + newFrame.setInt(fs, FrameUtil.getIntSafe(frame, fs)); + break; + case Byte: + newFrame.setByte(fs, FrameUtil.getByteSafe(frame, fs)); + break; + case Long: + newFrame.setLong(fs, FrameUtil.getLongSafe(frame, fs)); + break; + case Double: + newFrame.setDouble(fs, FrameUtil.getDoubleSafe(frame, fs)); + break; + case Float: + newFrame.setFloat(fs, FrameUtil.getFloatSafe(frame, fs)); + break; + case Boolean: + newFrame.setBoolean(fs, FrameUtil.getBooleanSafe(frame, fs)); + break; + } + } + return funcDefnNode.execute(newFrame); + } + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index 7615ab94dd..9d9bb5ea6d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -208,7 +208,11 @@ public abstract class RError extends RuntimeException { public static final String FORMAL_MATCHED_MULTIPLE = "formal argument \"%s\" matched by multiple actual arguments"; public static final String ARGUMENT_MATCHES_MULTIPLE = "argument %d matches multiple formal arguments"; public static final String ARGUMENT_EMPTY = "argument %d is empty"; - public static final String REPEATED_FORMAL = "repeated formal argument '%s'"; // not exactly + public static final String REPEATED_FORMAL = "repeated formal argument '%s'"; + public static final String NOT_A_MATRIX_UPDATE_CLASS = "invalid to set the class to matrix unless the dimension attribute is of length 2 (was '%d')"; + public static final String NOT_ARRAY_UPDATE_CLASS = "cannot set class to \"array\" unless the dimension attribute has length > 0"; + public static final String SET_INVALID_CLASS_ATTR = "attempt to set invalid 'class' attribute"; + // not exactly // GNU-R message public static final String DOTS_BOUNDS = "The ... list does not contain %s elements"; public static final String REFERENCE_NONEXISTENT = "reference to non-existent argument %d"; @@ -1906,6 +1910,18 @@ public abstract class RError extends RuntimeException { return getGenericError(ast, stringFormat(RError.RECURSIVE_INDEXING_FAILED, level)); } + public static RError getNotMatixUpdateClass(SourceSection ast, int dim) { + return getGenericError(ast, stringFormat(RError.NOT_A_MATRIX_UPDATE_CLASS, dim)); + } + + public static RError getNotArrayUpdateClass(SourceSection ast) { + return getGenericError(ast, RError.NOT_ARRAY_UPDATE_CLASS); + } + + public static RError getInvalidClassAttr(SourceSection ast) { + return getGenericError(ast, RError.SET_INVALID_CLASS_ATTR); + } + @SlowPath private static String stringFormat(String format, Object... args) { return String.format(format, args); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java index 2a2af7f760..f6c74006b7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java @@ -83,6 +83,9 @@ public class RRuntime { public static final String TYPE_CHARACTER = new String("character"); public static final String TYPE_LOGICAL = new String("logical"); public static final String TYPE_RAW = new String("raw"); + public static final String TYPE_MATRIX = new String("matrix"); + public static final String TYPE_ARRAY = new String("array"); + public static final String TYPE_LIST = new String("list"); public static final String TYPE_NUMERIC_CAP = new String("Numeric"); public static final String TYPE_INTEGER_CAP = new String("Integer"); @@ -107,6 +110,9 @@ public class RRuntime { public static final String CLASS_ATTR_KEY = "class"; + public static final String[] CLASS_INTEGER = new String[]{TYPE_INTEGER, TYPE_NUMERIC}; + public static final String[] CLASS_DOUBLE = new String[]{TYPE_DOUBLE, TYPE_NUMERIC}; + public static RComplex createComplexNA() { return RDataFactory.createComplex(DOUBLE_NA, 0.0); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java index 1995e5406c..ef2f71108e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java @@ -164,4 +164,10 @@ public final class RComplexVector extends RVector implements RAbstractComplexVec return getDataAt(index); } + @Override + public List<String> getClassHierarchy() { + List<String> klass = super.getClassHierarchy(); + klass.add(RRuntime.TYPE_COMPLEX); + return klass; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java index e94b2c9a53..718e1b933a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java @@ -30,6 +30,13 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV private final double start; private final double stride; + private static final List<String> klass; + static { + klass = new ArrayList<>(); + klass.add(RRuntime.TYPE_DOUBLE); + klass.add(RRuntime.TYPE_NUMERIC); + } + RDoubleSequence(double start, double stride, int length) { super(length); assert length > 0; @@ -91,4 +98,9 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV public Object getDataAtAsObject(int index) { return getDataAt(index); } + + @Override + public List<String> getClassHierarchy() { + return klass; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java index 3c42287a00..1cfe02a8d3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java @@ -174,4 +174,10 @@ public final class RDoubleVector extends RVector implements RAbstractDoubleVecto this.data = newData; } + @Override + public List<String> getClassHierarchy() { + final List<String> classHr = super.getClassHierarchy(); + classHr.addAll(Arrays.asList(RRuntime.CLASS_DOUBLE)); + return classHr; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java index 6ed1b9f30f..b97f889f4b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java @@ -30,6 +30,13 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector private final int start; private final int stride; + private static final List<String> klass; + static { + klass = new ArrayList<>(); + klass.add(RRuntime.TYPE_INTEGER); + klass.add(RRuntime.TYPE_NUMERIC); + } + RIntSequence(int start, int stride, int length) { super(length); assert length > 0; @@ -93,4 +100,8 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector public Object getDataAtAsObject(int index) { return getDataAt(index); } + + public List<String> getClassHierarchy() { + return klass; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java index 523fcedcc1..3168c7ae71 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java @@ -157,4 +157,11 @@ public final class RIntVector extends RVector implements RAbstractIntVector { public Object getDataAtAsObject(int index) { return getDataAt(index); } + + @Override + public List<String> getClassHierarchy() { + final List<String> classHr = super.getClassHierarchy(); + classHr.addAll(Arrays.asList(RRuntime.CLASS_INTEGER)); + return classHr; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java index 12c0c8ec94..98442acf93 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java @@ -163,4 +163,11 @@ public final class RList extends RVector implements RAbstractVector { protected void resizeInternal(int size) { this.data = createResizedData(size, true); } + + @Override + public List<String> getClassHierarchy() { + List<String> klass = super.getClassHierarchy(); + klass.add(RRuntime.TYPE_LIST); + return klass; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java index 9ebd72632a..12f69444e4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java @@ -148,4 +148,11 @@ public final class RLogicalVector extends RVector implements RAbstractLogicalVec public Object getDataAtAsObject(int index) { return getDataAt(index); } + + @Override + public List<String> getClassHierarchy() { + final List<String> classHr = super.getClassHierarchy(); + classHr.add(RRuntime.TYPE_LOGICAL); + return classHr; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java index 6cce99315a..12781ebf97 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java @@ -143,4 +143,11 @@ public final class RRawVector extends RVector implements RAbstractRawVector { public Object getDataAtAsObject(int index) { return getDataAt(index); } + + @Override + public List<String> getClassHierarchy() { + final List<String> classHr = super.getClassHierarchy(); + classHr.add(RRuntime.TYPE_RAW); + return classHr; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java index 410fbb261d..5d786a08b2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java @@ -84,4 +84,12 @@ public abstract class RSequence extends RBounded implements RAbstractVector { public boolean isMatrix() { return false; } + + public boolean isArray() { + return false; + } + + public boolean isObject() { + return false; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java index a5bb3b6340..b8f903dcc1 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java @@ -148,4 +148,11 @@ public final class RStringVector extends RVector implements RAbstractStringVecto public Object getDataAtAsObject(int index) { return getDataAt(index); } + + @Override + public List<String> getClassHierarchy() { + final List<String> classHr = super.getClassHierarchy(); + classHr.add(RRuntime.TYPE_CHARACTER); + return classHr; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java index 6a3df393d4..9100d2d063 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java @@ -212,6 +212,10 @@ public abstract class RVector extends RBounded implements RAbstractVector { return matrixDimension != 0; } + public final boolean isArray() { + return dimensions != null && dimensions.length > 0; + } + public final int[] getDimensions() { if (hasDimensions()) { return Arrays.copyOf(dimensions, dimensions.length); @@ -382,4 +386,20 @@ public abstract class RVector extends RBounded implements RAbstractVector { } } } + + public boolean isObject() { + return (this.attributes != null && this.attributes.get(RRuntime.CLASS_ATTR_KEY) != null) ? true : false; + } + + // As shape of the vector may change at run-time we need to compute + // class hierarchy on the fly. + public List<String> getClassHierarchy() { + List<String> klass = new ArrayList<>(); + if (this.isMatrix()) { + klass.add(RRuntime.TYPE_MATRIX); + } else if (this.isArray()) { + klass.add(RRuntime.TYPE_ARRAY); + } + return klass; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java index f505beffb5..049b8db2ed 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java @@ -80,4 +80,15 @@ public abstract class RToVectorClosure implements RAbstractVector { return vector.isMatrix(); } + public boolean isArray() { + return vector.isArray(); + } + + public List<String> getClassHierarchy() { + return vector.getClassHierarchy(); + } + + public boolean isObject() { + return vector.isObject(); + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java index 4b59ab5cc0..5c72de906b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java @@ -56,4 +56,10 @@ public interface RAbstractVector { RList getDimNames(); boolean isMatrix(); + + boolean isArray(); + + boolean isObject(); + + List<String> getClassHierarchy(); } diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index c45f835b92..59914d2e24 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -1,6 +1,8 @@ com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Base.r,gnu_r.copyright com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Covcor.java,gnu_r.copyright +com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java,purdue.copyright com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/Rnorm.java,gnu_r.copyright +com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java,purdue.copyright com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/base/UseMethod.java,purdue.copyright com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseException.java,purdue.copyright com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseUtil.java,purdue.copyright -- GitLab