Пример #1
0
// TODO Figure out how to distinguish f(,,a) from f(a) - RMissing is used in both contexts
@RBuiltin(
    name = "nargs",
    kind = PRIMITIVE,
    parameterNames = {})
public abstract class NArgs extends RBuiltinNode {

  private final BranchProfile isPromiseProfile = BranchProfile.create();

  @Specialization
  protected int doNArgs(VirtualFrame frame) {
    int result = 0;
    if (RArguments.getFunction(frame) == null) {
      return RRuntime.INT_NA;
    }
    int l = RArguments.getArgumentsLength(frame);
    for (int i = 0; i < l; i++) {
      Object arg = RArguments.getArgument(frame, i);
      if (arg instanceof RPromise) {
        isPromiseProfile.enter();
        RPromise promise = (RPromise) arg;
        if (!promise.isDefault()) {
          result++;
        }
      } else if (arg instanceof RArgsValuesAndNames) {
        result += ((RArgsValuesAndNames) arg).getLength();
      } else if (!(arg instanceof RMissing)) {
        result++;
      }
    }
    return result;
  }
}
Пример #2
0
@NodeChild(value = "lexicalParentModule", type = RubyNode.class)
public abstract class DefineModuleNode extends RubyNode {

  private final String name;

  @Child LookupForExistingModuleNode lookupForExistingModuleNode;

  private final ConditionProfile needToDefineProfile = ConditionProfile.createBinaryProfile();
  private final BranchProfile errorProfile = BranchProfile.create();

  public DefineModuleNode(RubyContext context, SourceSection sourceSection, String name) {
    super(context, sourceSection);
    this.name = name;
  }

  @Specialization(guards = "isRubyModule(lexicalParentModule)")
  public Object defineModule(VirtualFrame frame, DynamicObject lexicalParentModule) {
    final RubyConstant constant = lookupForExistingModule(frame, name, lexicalParentModule);

    final DynamicObject definingModule;

    if (needToDefineProfile.profile(constant == null)) {
      definingModule =
          ModuleNodes.createModule(
              getContext(), coreLibrary().getModuleClass(), lexicalParentModule, name, this);
    } else {
      final Object constantValue = constant.getValue();

      if (!RubyGuards.isRubyModule(constantValue) || RubyGuards.isRubyClass(constantValue)) {
        errorProfile.enter();
        throw new RaiseException(coreExceptions().typeErrorIsNotA(name, "module", this));
      }

      definingModule = (DynamicObject) constantValue;
    }

    return definingModule;
  }

  @Specialization(guards = "!isRubyModule(lexicalParentObject)")
  public Object defineModuleWrongParent(VirtualFrame frame, Object lexicalParentObject) {
    throw new RaiseException(coreExceptions().typeErrorIsNotA(lexicalParentObject, "module", this));
  }

  private RubyConstant lookupForExistingModule(
      VirtualFrame frame, String name, DynamicObject lexicalParent) {
    if (lookupForExistingModuleNode == null) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      lookupForExistingModuleNode = insert(LookupForExistingModuleNodeGen.create(null, null));
    }
    return lookupForExistingModuleNode.executeLookupForExistingModule(frame, name, lexicalParent);
  }
}
Пример #3
0
@RBuiltin(
    name = "dimnames",
    kind = PRIMITIVE,
    parameterNames = {"x"},
    dispatch = INTERNAL_GENERIC)
public abstract class DimNames extends RBuiltinNode {

  private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
  private final ConditionProfile nullProfile = ConditionProfile.createBinaryProfile();
  private final BranchProfile dataframeProfile = BranchProfile.create();
  private final BranchProfile factorProfile = BranchProfile.create();
  private final BranchProfile otherProfile = BranchProfile.create();

  @Specialization
  protected RNull getDimNames(@SuppressWarnings("unused") RNull operand) {
    controlVisibility();
    return RNull.instance;
  }

  @Specialization
  protected Object getDimNames(RAbstractContainer container) {
    controlVisibility();
    RList names;
    if (container instanceof RDataFrame) {
      dataframeProfile.enter();
      names = ((RDataFrame) container).getVector().getDimNames();
    } else if (container instanceof RFactor) {
      factorProfile.enter();
      names = ((RFactor) container).getVector().getDimNames();
    } else {
      otherProfile.enter();
      names = container.getDimNames(attrProfiles);
    }
    return nullProfile.profile(names == null) ? RNull.instance : names;
  }
}
  @NodeChildren({
    @NodeChild(value = "enclosingFrame", type = AccessEnclosingFrameNode.class),
    @NodeChild(value = "frameSlotNode", type = FrameSlotNode.class)
  })
  protected abstract static class ResolvedWriteSuperFrameVariableNode
      extends WriteSuperFrameVariableNode {

    private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile();
    private final BranchProfile invalidateProfile = BranchProfile.create();
    private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile();

    private final Mode mode;

    public ResolvedWriteSuperFrameVariableNode(Mode mode) {
      this.mode = mode;
    }

    protected abstract FrameSlotNode getFrameSlotNode();

    @Specialization(guards = "isLogicalKind(enclosingFrame, frameSlot)")
    protected void doLogical(byte value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
      FrameSlotChangeMonitor.setByteAndInvalidate(
          enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile);
    }

    @Specialization(guards = "isIntegerKind(enclosingFrame, frameSlot)")
    protected void doInteger(int value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
      FrameSlotChangeMonitor.setIntAndInvalidate(
          enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile);
    }

    @Specialization(guards = "isDoubleKind(enclosingFrame, frameSlot)")
    protected void doDouble(double value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
      FrameSlotChangeMonitor.setDoubleAndInvalidate(
          enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile);
    }

    @Specialization
    protected void doObject(Object value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
      MaterializedFrame profiledFrame = enclosingFrameProfile.profile(enclosingFrame);
      Object newValue =
          shareObjectValue(
              profiledFrame, frameSlot, storedObjectProfile.profile(value), mode, true);
      FrameSlotChangeMonitor.setObjectAndInvalidate(
          profiledFrame, frameSlot, newValue, true, invalidateProfile);
    }
  }
Пример #5
0
public class TryNode extends RubyNode {

  @Child private RubyNode tryPart;
  @Children private final RescueNode[] rescueParts;
  @Child private RubyNode elsePart;

  @Child private SetExceptionVariableNode setExceptionVariableNode;

  private final BranchProfile elseProfile = BranchProfile.create();
  private final BranchProfile controlFlowProfile = BranchProfile.create();
  private final BranchProfile raiseExceptionProfile = BranchProfile.create();

  public TryNode(
      RubyContext context,
      SourceSection sourceSection,
      ExceptionTranslatingNode tryPart,
      RescueNode[] rescueParts,
      RubyNode elsePart) {
    super(context, sourceSection);
    this.tryPart = tryPart;
    this.rescueParts = rescueParts;
    this.elsePart = elsePart;
  }

  @Override
  public Object execute(VirtualFrame frame) {
    while (true) {
      Object result;

      try {
        result = tryPart.execute(frame);
      } catch (RaiseException exception) {
        raiseExceptionProfile.enter();

        try {
          return handleException(frame, exception);
        } catch (RetryException e) {
          getContext().getSafepointManager().poll(this);
          continue;
        }
      } catch (ControlFlowException exception) {
        controlFlowProfile.enter();
        throw exception;
      }

      elseProfile.enter();

      if (elsePart != null) {
        result = elsePart.execute(frame);
      }

      return result;
    }
  }

  @ExplodeLoop
  private Object handleException(VirtualFrame frame, RaiseException exception) {
    for (RescueNode rescue : rescueParts) {
      if (rescue.canHandle(frame, exception.getException())) {
        return setLastExceptionAndRunRescue(frame, exception, rescue);
      }
    }

    throw exception;
  }

  private Object setLastExceptionAndRunRescue(
      VirtualFrame frame, RaiseException exception, RubyNode rescue) {
    if (setExceptionVariableNode == null) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      setExceptionVariableNode = insert(new SetExceptionVariableNode(getContext()));
    }

    return setExceptionVariableNode.setLastExceptionAndRun(frame, exception, rescue);
  }
}
Пример #6
0
final class PositionsCheckNode extends Node {

  @Children private final PositionCheckNode[] positionsCheck;

  private final ElementAccessMode mode;
  private final BranchProfile errorBranch = BranchProfile.create();
  private final VectorLengthProfile selectedPositionsCountProfile = VectorLengthProfile.create();
  private final VectorLengthProfile maxOutOfBoundsProfile = VectorLengthProfile.create();
  private final ConditionProfile containsNAProfile = ConditionProfile.createBinaryProfile();
  private final BranchProfile unsupportedProfile = BranchProfile.create();
  private final boolean replace;
  private final int positionsLength;

  PositionsCheckNode(
      ElementAccessMode mode,
      RType containerType,
      Object[] positions,
      boolean exact,
      boolean replace,
      boolean recursive) {
    this.mode = mode;
    this.replace = replace;
    this.positionsCheck = new PositionCheckNode[positions.length];
    for (int i = 0; i < positions.length; i++) {
      positionsCheck[i] =
          PositionCheckNode.createNode(
              mode, containerType, positions[i], i, positions.length, exact, replace, recursive);
    }
    this.positionsLength = positions.length;
  }

  public PositionCheckNode getPositionCheckAt(int index) {
    return positionsCheck[index];
  }

  @ExplodeLoop
  public boolean isSupported(Object[] positions) {
    if (positionsCheck.length != positions.length) {
      unsupportedProfile.enter();
      return false;
    }
    for (int i = 0; i < positionsCheck.length; i++) {
      if (!positionsCheck[i].isSupported(positions[i])) {
        unsupportedProfile.enter();
        return false;
      }
    }
    return true;
  }

  public int getDimensions() {
    return positionsCheck.length;
  }

  public boolean isSingleDimension() {
    return positionsCheck.length == 1;
  }

  public boolean isMultiDimension() {
    return positionsCheck.length > 1;
  }

  @ExplodeLoop
  public PositionProfile[] executeCheck(
      RAbstractContainer vector, int[] vectorDimensions, int vectorLength, Object[] positions) {
    assert isSupported(positions);
    verifyDimensions(vectorDimensions);

    PositionProfile[] statistics = new PositionProfile[positionsLength];
    for (int i = 0; i < positionsLength; i++) {
      Object position = positions[i];
      PositionProfile profile = new PositionProfile();
      positions[i] =
          positionsCheck[i].execute(profile, vector, vectorDimensions, vectorLength, position);
      statistics[i] = profile;
    }
    return statistics;
  }

  @TruffleBoundary
  private void print() {
    System.out.println(positionsCheck.length);
  }

  private void verifyDimensions(int[] vectorDimensions) {
    if (vectorDimensions == null) {
      if (isMultiDimension()) {
        errorBranch.enter();
        throw dimensionsError();
      }
    } else {
      if (getDimensions() > vectorDimensions.length || getDimensions() < vectorDimensions.length) {
        errorBranch.enter();
        throw dimensionsError();
      }
    }
  }

  private RError dimensionsError() {
    if (replace) {
      if (mode.isSubset()) {
        if (getDimensions() == 2) {
          return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS_MATRIX);
        } else {
          return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS);
        }
      } else {
        return RError.error(this, RError.Message.IMPROPER_SUBSCRIPT);
      }
    } else {
      return RError.error(this, RError.Message.INCORRECT_DIMENSIONS);
    }
  }

  @ExplodeLoop
  public int getSelectedPositionsCount(PositionProfile[] profiles) {
    if (positionsCheck.length == 1) {
      return selectedPositionsCountProfile.profile(profiles[0].selectedPositionsCount);
    } else {
      int newSize = 1;
      for (int i = 0; i < positionsCheck.length; i++) {
        newSize *= profiles[i].selectedPositionsCount;
      }
      return selectedPositionsCountProfile.profile(newSize);
    }
  }

  public int getCachedSelectedPositionsCount() {
    return selectedPositionsCountProfile.getCachedLength();
  }

  @ExplodeLoop
  public boolean getContainsNA(PositionProfile[] profiles) {
    if (positionsCheck.length == 1) {
      return containsNAProfile.profile(profiles[0].containsNA);
    } else {
      boolean containsNA = false;
      for (int i = 0; i < positionsCheck.length; i++) {
        containsNA |= profiles[i].containsNA;
      }
      return containsNAProfile.profile(containsNA);
    }
  }

  @ExplodeLoop
  public int getMaxOutOfBounds(PositionProfile[] replacementStatistics) {
    if (positionsCheck.length == 1) {
      return maxOutOfBoundsProfile.profile(replacementStatistics[0].maxOutOfBoundsIndex);
    } else {
      // impossible to be relevant as position check will throw an error in this case.
      return 0;
    }
  }

  public boolean isMissing() {
    return positionsCheck.length == 1
        && //
        (positionsCheck[0].getPositionClass() == RMissing.class
            || positionsCheck[0].getPositionClass() == REmpty.class
            || //
            positionsCheck[0].getPositionClass() == RSymbol.class);
  }

  final class PositionProfile {

    int selectedPositionsCount;

    int maxOutOfBoundsIndex;

    boolean containsNA;
  }
}
Пример #7
0
  @RBuiltin(
      name = ".Call.graphics",
      kind = RBuiltinKind.PRIMITIVE,
      parameterNames = {".NAME", "...", "PACKAGE"})
  public abstract static class DotCallGraphics extends LookupAdapter {

    private final BranchProfile errorProfile = BranchProfile.create();

    @Override
    public Object[] getDefaultParameterValues() {
      return new Object[] {RMissing.instance, RArgsValuesAndNames.EMPTY, RMissing.instance};
    }

    @Override
    protected RExternalBuiltinNode lookupBuiltin(RList f) {
      switch (lookupName(f)) {
        default:
          return null;
      }
    }

    @SuppressWarnings("unused")
    @Specialization(
        limit = "1",
        guards = {"cached == f", "builtin != null"})
    protected Object doExternal(
        RList f,
        RArgsValuesAndNames args,
        RMissing packageName, //
        @Cached("f") RList cached, //
        @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) {
      controlVisibility();
      return builtin.call(args);
    }

    @Specialization
    public Object callNamedFunction(
        VirtualFrame frame,
        RList symbol,
        RArgsValuesAndNames args,
        @SuppressWarnings("unused") Object packageName) {
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(
              getAddressFromSymbolInfo(frame, symbol),
              getNameFromSymbolInfo(frame, symbol),
              args.getArguments());
    }

    @Specialization
    public Object callNamedFunction(
        String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) {
      return callNamedFunctionWithPackage(name, args, null);
    }

    @Specialization
    public Object callNamedFunctionWithPackage(
        String name, RArgsValuesAndNames args, String packageName) {
      controlVisibility();
      SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName);
      if (symbolInfo == null) {
        errorProfile.enter();
        throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name);
      }
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(symbolInfo.address, symbolInfo.symbol, args.getArguments());
    }

    @Fallback
    protected Object dotCallFallback(
        Object fobj,
        @SuppressWarnings("unused") Object args,
        @SuppressWarnings("unused") Object packageName) {
      throw fallback(fobj);
    }
  }
Пример #8
0
  @RBuiltin(
      name = ".External.graphics",
      kind = RBuiltinKind.PRIMITIVE,
      parameterNames = {".NAME", "...", "PACKAGE"})
  public abstract static class DotExternalGraphics extends LookupAdapter {

    private final BranchProfile errorProfile = BranchProfile.create();

    @Override
    protected RExternalBuiltinNode lookupBuiltin(RList f) {
      if (FastROptions.UseInternalGraphics.getBooleanValue()) {
        switch (lookupName(f)) {
          case "C_mtext":
            return new GraphicsCCalls.C_mtext();
          case "C_plotXY":
            return new C_PlotXY();
        }
      }
      return null;
    }

    @SuppressWarnings("unused")
    @Specialization(
        limit = "1",
        guards = {"cached == f", "builtin != null"})
    protected Object doExternal(
        RList f,
        RArgsValuesAndNames args,
        RMissing packageName, //
        @Cached("f") RList cached, //
        @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) {
      controlVisibility();
      return builtin.call(args);
    }

    @Specialization
    public Object callNamedFunction(
        VirtualFrame frame,
        RList symbol,
        RArgsValuesAndNames args,
        @SuppressWarnings("unused") Object packageName) {
      String name = getNameFromSymbolInfo(frame, symbol);
      Object list = encodeArgumentPairList(args, name);
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(getAddressFromSymbolInfo(frame, symbol), name, new Object[] {list});
    }

    @Specialization
    public Object callNamedFunction(
        String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) {
      return callNamedFunctionWithPackage(name, args, null);
    }

    @Specialization
    public Object callNamedFunctionWithPackage(
        String name, RArgsValuesAndNames args, String packageName) {
      controlVisibility();
      SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName);
      if (symbolInfo == null) {
        errorProfile.enter();
        throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name);
      }
      Object list = encodeArgumentPairList(args, symbolInfo.symbol);
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(symbolInfo.address, symbolInfo.symbol, new Object[] {list});
    }

    @Fallback
    protected Object fallback(
        Object f,
        @SuppressWarnings("unused") Object args,
        @SuppressWarnings("unused") Object packageName) {
      throw fallback(f);
    }
  }
Пример #9
0
  @RBuiltin(
      name = ".External2",
      kind = RBuiltinKind.PRIMITIVE,
      parameterNames = {".NAME", "...", "PACKAGE"})
  public abstract static class DotExternal2 extends LookupAdapter {
    private static final Object CALL = "call";
    private static final Object OP = "op";
    private static final Object RHO = "rho";

    private final BranchProfile errorProfile = BranchProfile.create();

    @Override
    protected RExternalBuiltinNode lookupBuiltin(RList f) {
      if (FastROptions.UseInternalGraphics.getBooleanValue()) {
        switch (lookupName(f)) {
          case "C_par":
            return new C_Par();
        }
      }
      String name = lookupName(f);
      switch (name) {
          // tools
        case "writetable":
          return new WriteTable();
        case "typeconvert":
          return TypeConvertNodeGen.create();
        case "C_parseRd":
          return C_ParseRdNodeGen.create();
        default:
          return null;
      }
    }

    @SuppressWarnings("unused")
    @Specialization(
        limit = "1",
        guards = {"cached == f", "builtin != null"})
    protected Object doExternal(
        RList f,
        RArgsValuesAndNames args,
        RMissing packageName, //
        @Cached("f") RList cached, //
        @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) {
      controlVisibility();
      return builtin.call(args);
    }

    @Specialization
    public Object callNamedFunction(
        VirtualFrame frame,
        RList symbol,
        RArgsValuesAndNames args,
        @SuppressWarnings("unused") Object packageName) {
      String name = getNameFromSymbolInfo(frame, symbol);
      Object list = encodeArgumentPairList(args, name);
      // TODO: provide proper values for the CALL, OP and RHO parameters
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(
              getAddressFromSymbolInfo(frame, symbol), name, new Object[] {CALL, OP, list, RHO});
    }

    @Specialization
    public Object callNamedFunction(
        String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) {
      return callNamedFunctionWithPackage(name, args, null);
    }

    @Specialization
    public Object callNamedFunctionWithPackage(
        String name, RArgsValuesAndNames args, String packageName) {
      controlVisibility();
      SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName);
      if (symbolInfo == null) {
        errorProfile.enter();
        throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name);
      }
      Object list = encodeArgumentPairList(args, symbolInfo.symbol);
      // TODO: provide proper values for the CALL, OP and RHO parameters
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(symbolInfo.address, symbolInfo.symbol, new Object[] {CALL, OP, list, RHO});
    }

    @Fallback
    protected Object fallback(
        Object f,
        @SuppressWarnings("unused") Object args,
        @SuppressWarnings("unused") Object packageName) {
      throw fallback(f);
    }
  }
Пример #10
0
  @RBuiltin(
      name = ".External",
      kind = RBuiltinKind.PRIMITIVE,
      parameterNames = {".NAME", "...", "PACKAGE"})
  public abstract static class DotExternal extends LookupAdapter {

    private final BranchProfile errorProfile = BranchProfile.create();

    @Override
    protected RExternalBuiltinNode lookupBuiltin(RList f) {
      String name = lookupName(f);
      if (FastROptions.UseInternalGraphics.getBooleanValue()) {
        switch (name) {
          case "PDF":
            return new DevicesCCalls.C_PDF();
          case "devoff":
            return new DevicesCCalls.C_DevOff();
          case "devcur":
            return new DevicesCCalls.C_DevCur();
        }
      }
      switch (name) {
        case "compcases":
          return new CompleteCases();
          // utils
        case "countfields":
          return new CountFields();
        case "readtablehead":
          return new ReadTableHead();
        case "rnorm":
          return RnormNodeGen.create();
        case "runif":
          return RunifNodeGen.create();
        case "qgamma":
          return QgammaNodeGen.create();
        case "download":
          return new Download();
        case "unzip":
        case "Rprof":
        case "Rprofmem":
        case "addhistory":
        case "loadhistory":
        case "savehistory":
        case "dataentry":
        case "dataviewer":
        case "edit":
        case "fileedit":
        case "selectlist":
          return new UnimplementedExternal(name);
        default:
          return null;
      }
    }

    @SuppressWarnings("unused")
    @Specialization(
        limit = "1",
        guards = {"cached == f", "builtin != null"})
    protected Object doExternal(
        RList f,
        RArgsValuesAndNames args,
        RMissing packageName, //
        @Cached("f") RList cached, //
        @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) {
      controlVisibility();
      return builtin.call(args);
    }

    @Specialization
    public Object callNamedFunction(
        VirtualFrame frame,
        RList symbol,
        RArgsValuesAndNames args,
        @SuppressWarnings("unused") Object packageName) {
      String name = getNameFromSymbolInfo(frame, symbol);
      Object list = encodeArgumentPairList(args, name);
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(getAddressFromSymbolInfo(frame, symbol), name, new Object[] {list});
    }

    @Specialization
    public Object callNamedFunction(
        String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) {
      return callNamedFunctionWithPackage(name, args, null);
    }

    @Specialization
    public Object callNamedFunctionWithPackage(
        String name, RArgsValuesAndNames args, String packageName) {
      controlVisibility();
      SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName);
      if (symbolInfo == null) {
        errorProfile.enter();
        throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name);
      }
      Object list = encodeArgumentPairList(args, symbolInfo.symbol);
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(symbolInfo.address, symbolInfo.symbol, new Object[] {list});
    }

    @Fallback
    protected Object fallback(
        Object f,
        @SuppressWarnings("unused") Object args,
        @SuppressWarnings("unused") Object packageName) {
      throw fallback(f);
    }
  }
Пример #11
0
  /**
   * Handles the generic case, but also many special case functions that are called from the default
   * packages.
   */
  @RBuiltin(
      name = ".Call",
      kind = RBuiltinKind.PRIMITIVE,
      parameterNames = {".NAME", "...", "PACKAGE"})
  public abstract static class DotCall extends LookupAdapter {

    private final BranchProfile errorProfile = BranchProfile.create();

    @Override
    public Object[] getDefaultParameterValues() {
      return new Object[] {RMissing.instance, RArgsValuesAndNames.EMPTY, RMissing.instance};
    }

    @Override
    protected RExternalBuiltinNode lookupBuiltin(RList f) {
      String name = lookupName(f);
      switch (name) {
          // methods
        case "R_initMethodDispatch":
          return R_initMethodDispatchNodeGen.create();
        case "R_methodsPackageMetaName":
          return R_methodsPackageMetaNameNodeGen.create();
        case "R_set_method_dispatch":
          return R_set_method_dispatchNodeGen.create();
        case "R_M_setPrimitiveMethods":
          return R_M_setPrimitiveMethodsNodeGen.create();
        case "R_getClassFromCache":
          return R_getClassFromCacheNodeGen.create();
        case "R_clear_method_selection":
        case "R_dummy_extern_place":
        case "R_el_named":
          return new UnimplementedExternal(name);
        case "R_externalptr_prototype_object":
          return R_externalPtrPrototypeObjectNodeGen.create();
        case "R_getGeneric":
          return R_getGenericNodeGen.create();
        case "R_get_slot":
          return R_getSlotNodeGen.create();
        case "R_hasSlot":
          return new UnimplementedExternal(name);
        case "R_identC":
          return R_identCNodeGen.create();
        case "R_methods_test_MAKE_CLASS":
        case "R_methods_test_NEW":
        case "R_missingArg":
        case "R_nextMethodCall":
          return R_nextMethodCallNodeGen.create();
        case "R_quick_method_check":
        case "R_selectMethod":
        case "R_set_el_named":
          return new UnimplementedExternal(name);
        case "R_set_slot":
          return R_setSlotNodeGen.create();
        case "R_standardGeneric":
          return new UnimplementedExternal(name);
        case "do_substitute_direct":
          return SubstituteDirectNodeGen.create();
        case "Rf_allocS4Object":
        case "R_get_primname":
          return new UnimplementedExternal(name);
        case "new_object":
          return NewObjectNodeGen.create();

          // stats

        case "fft":
          return new Fft();
        case "cov":
          return new Covcor(false);
        case "cor":
          return new Covcor(true);
        case "SplineCoef":
          return SplineCoefNodeGen.create();
        case "SplineEval":
          return SplineEvalNodeGen.create();
        case "cutree":
        case "isoreg":
        case "monoFC_m":
        case "numeric_deriv":
        case "nls_iter":
        case "setup_starma":
        case "free_starma":
        case "set_trans":
        case "arma0fa":
        case "get_s2":
        case "get_resid":
        case "Dotrans":
        case "arma0_kfore":
        case "Starma_method":
        case "Invtrans":
        case "Gradtrans":
        case "ARMAtoMA":
        case "KalmanLike":
        case "KalmanFore":
        case "KalmanSmooth":
        case "ARIMA_undoPars":
        case "ARIMA_transPars":
        case "ARIMA_Invtrans":
        case "ARIMA_Gradtrans":
        case "ARIMA_Like":
        case "ARIMA_CSS":
        case "TSconv":
        case "getQ0":
        case "getQ0bis":
        case "port_ivset":
        case "port_nlminb":
        case "port_nlsb":
        case "logit_link":
        case "logit_linkinv":
        case "logit_mu_eta":
        case "binomial_dev_resids":
        case "rWishart":
        case "Cdqrls":
        case "Cdist":
        case "updateform":
        case "mvfft":
        case "nextn":
        case "r2dtable":
        case "cfilter":
        case "rfilter":
        case "lowess":
        case "DoubleCentre":
        case "BinDist":
        case "Rsm":
        case "tukeyline":
        case "runmed":
        case "influence":
        case "pSmirnov2x":
        case "pKolmogorov2x":
        case "pKS2":
        case "ksmooth":
        case "Approx":
        case "ApproxTest":
        case "LogLin":
        case "pAnsari":
        case "qAnsari":
        case "pKendall":
        case "pRho":
        case "SWilk":
        case "bw_den":
        case "bw_ucv":
        case "bw_bcv":
        case "bw_phi4":
        case "bw_phi6":
        case "acf":
        case "pacf1":
        case "ar2ma":
        case "Burg":
        case "intgrt_vec":
        case "pp_sum":
        case "Fexact":
        case "Fisher_sim":
        case "chisq_sim":
        case "d2x2xk":
          return new UnimplementedExternal(name);

          // tools
        case "doTabExpand":
          return DoTabExpandNodeGen.create();
        case "codeFilesAppend":
          return CodeFilesAppendNodeGen.create();
        case "Rmd5":
          return Rmd5NodeGen.create();
        case "dirchmod":
          return DirChmodNodeGen.create();
        case "delim_match":
        case "C_getfmts":
        case "check_nonASCII":
        case "check_nonASCII2":
        case "ps_kill":
        case "ps_sigs":
        case "ps_priority":
        case "startHTTPD":
        case "stopHTTPD":
        case "C_deparseRd":
          return new UnimplementedExternal(name);

          // utils
        case "crc64":
          return Crc64NodeGen.create();
        case "flushconsole":
          return new Flushconsole();
        case "menu":
          return MenuNodeGen.create();
        case "nsl":
        case "objectSize":
        case "processevents":
        case "octsize":
        case "sockconnect":
        case "sockread":
        case "sockclose":
        case "sockopen":
        case "socklisten":
        case "sockwrite":
          return new UnimplementedExternal(name);

          // grDevices
        case "cairoProps":
          return CairoPropsNodeGen.create();
        case "makeQuartzDefault":
          return new MakeQuartzDefault();

          // grid
        case "L_initGrid":
          return InitGridNodeGen.create();
        default:
          return null;
      }
    }

    @SuppressWarnings("unused")
    @Specialization(
        limit = "1",
        guards = {"cached == f", "builtin != null"})
    protected Object doExternal(
        RList f,
        RArgsValuesAndNames args,
        RMissing packageName, //
        @Cached("f") RList cached, //
        @Cached("lookupBuiltin(f)") RExternalBuiltinNode builtin) {
      controlVisibility();
      return builtin.call(args);
    }

    @Specialization
    public Object callNamedFunction(
        VirtualFrame frame,
        RList symbol,
        RArgsValuesAndNames args,
        @SuppressWarnings("unused") Object packageName) {
      controlVisibility();
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(
              getAddressFromSymbolInfo(frame, symbol),
              getNameFromSymbolInfo(frame, symbol),
              args.getArguments());
    }

    @Specialization
    public Object callNamedFunction(
        String name, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) {
      return callNamedFunctionWithPackage(name, args, null);
    }

    @Specialization
    public Object callNamedFunctionWithPackage(
        String name, RArgsValuesAndNames args, String packageName) {
      controlVisibility();
      SymbolInfo symbolInfo = DLL.findSymbolInfo(name, packageName);
      if (symbolInfo == null) {
        errorProfile.enter();
        throw RError.error(this, Message.C_SYMBOL_NOT_IN_TABLE, name);
      }
      return RFFIFactory.getRFFI()
          .getCallRFFI()
          .invokeCall(symbolInfo.address, symbolInfo.symbol, args.getArguments());
    }

    @Fallback
    protected Object dotCallFallback(
        Object fobj,
        @SuppressWarnings("unused") Object args,
        @SuppressWarnings("unused") Object packageName) {
      throw fallback(fobj);
    }
  }
Пример #12
0
/**
 * {@link WriteSuperFrameVariableNode} captures a write to a variable in some parent frame.
 *
 * <p>The state starts out a "unresolved" and transforms to "resolved".
 */
@SuppressWarnings("unused")
@NodeChildren({
  @NodeChild(value = "enclosingFrame", type = AccessEnclosingFrameNode.class),
  @NodeChild(value = "frameSlotNode", type = FrameSlotNode.class)
})
@NodeField(name = "mode", type = Mode.class)
public abstract class WriteSuperFrameVariableNode extends WriteSuperFrameVariableNodeHelper {
  private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile();
  private final BranchProfile invalidateProfile = BranchProfile.create();
  private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile();

  protected abstract FrameSlotNode getFrameSlotNode();

  public abstract Mode getMode();

  public static WriteVariableNode create(String name, RNode rhs, Mode mode) {
    return new UnresolvedWriteSuperFrameVariableNode(name, rhs, mode);
  }

  @Specialization(guards = "isLogicalKind(frame, frameSlot)")
  protected void doLogical(
      VirtualFrame frame, byte value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
    FrameSlotChangeMonitor.setByteAndInvalidate(
        enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile);
  }

  @Specialization(guards = "isIntegerKind(frame, frameSlot)")
  protected void doInteger(
      VirtualFrame frame, int value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
    FrameSlotChangeMonitor.setIntAndInvalidate(
        enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile);
  }

  @Specialization(guards = "isDoubleKind(frame, frameSlot)")
  protected void doDouble(
      VirtualFrame frame, double value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
    FrameSlotChangeMonitor.setDoubleAndInvalidate(
        enclosingFrameProfile.profile(enclosingFrame), frameSlot, value, true, invalidateProfile);
  }

  @Specialization
  protected void doObject(
      VirtualFrame frame, Object value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
    MaterializedFrame profiledFrame = enclosingFrameProfile.profile(enclosingFrame);
    Object newValue =
        shareObjectValue(
            profiledFrame, frameSlot, storedObjectProfile.profile(value), getMode(), true);
    FrameSlotChangeMonitor.setObjectAndInvalidate(
        profiledFrame, frameSlot, newValue, true, invalidateProfile);
  }

  public static class UnresolvedWriteSuperFrameVariableNode
      extends WriteSuperFrameVariableNodeHelper {

    @Child private RNode rhs;
    private final String symbol;
    private final BaseWriteVariableNode.Mode mode;

    public UnresolvedWriteSuperFrameVariableNode(
        String symbol, RNode rhs, BaseWriteVariableNode.Mode mode) {
      this.rhs = rhs;
      this.symbol = symbol;
      this.mode = mode;
    }

    @Override
    public String getName() {
      return symbol;
    }

    @Override
    public RNode getRhs() {
      return rhs;
    }

    @Override
    public void execute(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      if (getName().isEmpty()) {
        throw RError.error(this, RError.Message.ZERO_LENGTH_VARIABLE);
      }
      final WriteSuperFrameVariableNodeHelper writeNode;
      if (REnvironment.isGlobalEnvFrame(enclosingFrame)) {
        /*
         * we've reached the global scope, do unconditional write. if this is the first node
         * in the chain, needs the rhs and enclosingFrame nodes
         */
        AccessEnclosingFrameNode enclosingFrameNode =
            RArguments.getEnclosingFrame(frame) == enclosingFrame
                ? new AccessEnclosingFrameNode()
                : null;
        writeNode =
            WriteSuperFrameVariableNodeGen.create(
                getRhs(),
                enclosingFrameNode,
                FrameSlotNode.create(
                    findOrAddFrameSlot(
                        enclosingFrame.getFrameDescriptor(), symbol, FrameSlotKind.Illegal)),
                getName(),
                mode);
      } else {
        WriteSuperFrameVariableNode actualWriteNode =
            WriteSuperFrameVariableNodeGen.create(
                null, null, FrameSlotNode.create(symbol), this.getName(), mode);
        writeNode =
            new WriteSuperFrameVariableConditionalNode(
                actualWriteNode,
                new UnresolvedWriteSuperFrameVariableNode(symbol, null, mode),
                getRhs());
      }
      replace(writeNode).execute(frame, value, enclosingFrame);
    }

    @Override
    public void execute(VirtualFrame frame, Object value) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      MaterializedFrame enclosingFrame = RArguments.getEnclosingFrame(frame);
      if (enclosingFrame != null) {
        execute(frame, value, enclosingFrame);
      } else {
        // we're in global scope, do a local write instead
        replace(UnresolvedWriteLocalFrameVariableNodeGen.create(getRhs(), symbol, mode))
            .execute(frame, value);
      }
    }
  }

  public static class WriteSuperFrameVariableConditionalNode
      extends WriteSuperFrameVariableNodeHelper {

    @Child private WriteSuperFrameVariableNode writeNode;
    @Child private WriteSuperFrameVariableNodeHelper nextNode;
    @Child private RNode rhs;

    private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile();
    private final ConditionProfile hasValueProfile = ConditionProfile.createBinaryProfile();
    private final ConditionProfile nullSuperFrameProfile = ConditionProfile.createBinaryProfile();

    WriteSuperFrameVariableConditionalNode(
        WriteSuperFrameVariableNode writeNode,
        WriteSuperFrameVariableNodeHelper nextNode,
        RNode rhs) {
      this.writeNode = writeNode;
      this.nextNode = nextNode;
      this.rhs = rhs;
    }

    @Override
    public Object getName() {
      return writeNode.getName();
    }

    @Override
    public RNode getRhs() {
      return rhs;
    }

    @Override
    public void execute(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame) {
      MaterializedFrame profiledEnclosingFrame = enclosingFrameProfile.profile(enclosingFrame);
      if (hasValueProfile.profile(writeNode.getFrameSlotNode().hasValue(profiledEnclosingFrame))) {
        writeNode.execute(frame, value, profiledEnclosingFrame);
      } else {
        MaterializedFrame superFrame = RArguments.getEnclosingFrame(profiledEnclosingFrame);
        if (nullSuperFrameProfile.profile(superFrame == null)) {
          // Might be the case if "{ x <<- 42 }": This is in globalEnv!
          superFrame = REnvironment.globalEnv().getFrame();
        }
        nextNode.execute(frame, value, superFrame);
      }
    }

    @Override
    public void execute(VirtualFrame frame, Object value) {
      assert RArguments.getEnclosingFrame(frame) != null;
      execute(frame, value, RArguments.getEnclosingFrame(frame));
    }
  }
}
Пример #13
0
/**
 * The {@code .Internal} builtin. In {@code .Internal(func(args))} we have an AST where the
 * RCallNode.Uninitialized and the function child should be a {@link ReadVariableNode} node with
 * symbol {@code func}. We want to rewrite the AST as if the {@code func} had been called directly.
 * However, we must do this in a non-destructive way otherwise deparsing and serialization will
 * fail.
 *
 * <p>A note on {@link RInstrumentableNode}. Since both the {@code .Internal} and the argument are
 * {@link RCallNode}s both may have been wrapped. The call to {@link RASTUtils#unwrap} will go
 * through any {@code RNodeWrapper} and the rewrite will remove one level of wrapping. However the
 * parent of the the {@code .Internal}, which will be an {@code RNodeWrapper}, will remain so any
 * instrumentation at that level will remain in place.
 */
@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
@NodeInfo(cost = NONE)
@RBuiltin(
    name = ".Internal",
    visibility = CUSTOM,
    kind = PRIMITIVE,
    parameterNames = {"call"},
    nonEvalArgs = 0,
    behavior = COMPLEX)
public abstract class Internal extends RBuiltinNode {

  private final BranchProfile errorProfile = BranchProfile.create();

  @Child private RNode builtinCallNode;

  @Specialization
  protected Object doInternal(@SuppressWarnings("unused") RMissing x) {
    errorProfile.enter();
    throw RError.error(this, RError.Message.ARGUMENTS_PASSED_0_1, getRBuiltin().name());
  }

  @Specialization
  protected Object doInternal(VirtualFrame frame, RPromise x) {
    if (builtinCallNode == null) {
      RNode call = (RNode) x.getRep();
      RNode operand = (RNode) RASTUtils.unwrap(call);

      if (!(operand instanceof RCallNode)) {
        errorProfile.enter();
        throw RError.error(this, RError.Message.INVALID_INTERNAL);
      }

      RCallNode callNode = (RCallNode) operand;
      RNode func = callNode.getFunctionNode();
      String name = ((ReadVariableNode) func).getIdentifier();
      RFunction function = RContext.lookupBuiltin(name);
      if (function == null
          || function.isBuiltin() && function.getRBuiltin().getKind() != RBuiltinKind.INTERNAL) {
        errorProfile.enter();
        if (function == null && notImplemented(name)) {
          throw RInternalError.unimplemented(".Internal " + name);
        }
        throw RError.error(this, RError.Message.NO_SUCH_INTERNAL, name);
      }

      // .Internal function is validated
      CompilerDirectives.transferToInterpreterAndInvalidate();
      builtinCallNode = insert(RCallNode.createInternalCall(callNode, function));
    }
    return builtinCallNode.execute(frame);
  }

  private static boolean notImplemented(String name) {
    for (String internal : NOT_IMPLEMENTED) {
      if (internal.equals(name)) {
        return true;
      }
    }
    return false;
  }

  // TODO check this; it is out of date
  private static final String[] NOT_IMPLEMENTED =
      new String[] {
        ".addTryHandlers",
        "interruptsSuspended",
        "restart",
        "backsolve",
        "max.col",
        "row",
        "all.names",
        "comment",
        "`comment<-`",
        "list2env",
        "tcrossprod",
        "lbeta",
        "beta",
        "lchoose",
        "choose",
        "dchisq",
        "pchisq",
        "qchisq",
        "dexp",
        "pexp",
        "qexp",
        "dgeom",
        "pgeom",
        "qgeom",
        "dpois",
        "ppois",
        "qpois",
        "dt",
        "pt",
        "qt",
        "dsignrank",
        "psignrank",
        "qsignrank",
        "besselJ",
        "besselY",
        "psigamma",
        "dbeta",
        "pbeta",
        "qbeta",
        "dbinom",
        "pbinom",
        "qbinom",
        "dcauchy",
        "pcauchy",
        "qcauchy",
        "df",
        "pf",
        "qf",
        "dgamma",
        "pgamma",
        "qgamma",
        "dlnorm",
        "plnorm",
        "qlnorm",
        "dlogis",
        "plogis",
        "qlogis",
        "dnbinom",
        "pnbinom",
        "qnbinom",
        "dnorm",
        "pnorm",
        "qnorm",
        "dunif",
        "punif",
        "qunif",
        "dweibull",
        "pweibull",
        "qweibull",
        "dnchisq",
        "pnchisq",
        "qnchisq",
        "dnt",
        "pnt",
        "qnt",
        "dwilcox",
        "pwilcox",
        "qwilcox",
        "besselI",
        "besselK",
        "dnbinom_mu",
        "pnbinom_mu",
        "qnbinom_mu",
        "dhyper",
        "phyper",
        "qhyper",
        "dnbeta",
        "pnbeta",
        "qnbeta",
        "dnf",
        "pnf",
        "qnf",
        "dtukey",
        "ptukey",
        "qtukey",
        "rchisq",
        "rexp",
        "rgeom",
        "rpois",
        "rt",
        "rsignrank",
        "rbeta",
        "rbinom",
        "rcauchy",
        "rf",
        "rgamma",
        "rlnorm",
        "rlogis",
        "rnbinom",
        "rnbinom_mu",
        "rnchisq",
        "rnorm",
        "runif",
        "rweibull",
        "rwilcox",
        "rhyper",
        "sample2",
        "format.info",
        "grepRaw",
        "regexec",
        "adist",
        "aregexec",
        "chartr",
        "intToBits",
        "rawToBits",
        "packBits",
        "utf8ToInt",
        "intToUtf8",
        "strtrim",
        "eapply",
        "machine",
        "save",
        "saveToConn",
        "dput",
        "dump",
        "prmatrix",
        "gcinfo",
        "gctorture",
        "gctorture2",
        "memory.profile",
        "recordGraphics",
        "sys.calls",
        "sys.on.exit",
        "rank",
        "builtins",
        "bodyCode",
        "rapply",
        "islistfactor",
        "inspect",
        "mem.limits",
        "merge",
        "capabilitiesX11",
        "Cstack_info",
        "file.show",
        "file.choose",
        "polyroot",
        "mkCode",
        "bcClose",
        "is.builtin.internal",
        "disassemble",
        "bcVersion",
        "load.from.file",
        "save.to.file",
        "growconst",
        "putconst",
        "getconst",
        "enableJIT",
        "setNumMathThreads",
        "setMaxNumMathThreads",
        "isatty",
        "isIncomplete",
        "pipe",
        "fifo",
        "bzfile",
        "xzfile",
        "unz",
        "truncate",
        "rawConnection",
        "rawConnectionValue",
        "sockSelect",
        "gzcon",
        "memCompress",
        "memDecompress",
        "mkUnbound",
        "env.profile",
        "setTimeLimit",
        "setSessionTimeLimit",
        "icuSetCollate",
        "lazyLoadDBflush",
        "findInterval",
        "pretty",
        "crc64",
        "rowsum_matrix",
        "rowsum_df",
        "setS4Object",
        "traceOnOff",
        "La_qr_cmplx",
        "La_rs_cmplx",
        "La_rg_cmplx",
        "La_rs",
        "La_rs_cmplx",
        "La_dlange",
        "La_dgecon",
        "La_dtrcon",
        "La_zgecon",
        "La_ztrcon",
        "La_solve_cmplx",
        "La_chol2inv",
        "qr_qy_real",
        "qr_coef_cmplx",
        "qr_qy_cmpl",
        "La_svd",
        "La_svd_cmplx"
      };
}
Пример #14
0
abstract class PositionCheckNode extends Node {

  protected final Class<?> positionClass;
  protected final int dimensionIndex;
  protected final int numDimensions;
  protected final VectorLengthProfile positionLengthProfile = VectorLengthProfile.create();
  protected final BranchProfile error = BranchProfile.create();
  protected final boolean replace;
  protected final RType containerType;
  @Child private PositionCastNode castNode;
  @Child private RLengthNode positionLengthNode = RLengthNode.create();
  @Child private PositionCharacterLookupNode characterLookup;

  PositionCheckNode(
      ElementAccessMode mode,
      RType containerType,
      Object positionValue,
      int dimensionIndex,
      int numDimensions,
      boolean exact,
      boolean replace) {
    this.positionClass = positionValue.getClass();
    this.dimensionIndex = dimensionIndex;
    this.numDimensions = numDimensions;
    this.replace = replace;
    this.containerType = containerType;
    this.castNode = PositionCastNode.create(mode, replace);
    if (positionValue instanceof String || positionValue instanceof RAbstractStringVector) {
      boolean useNAForNotFound = !replace && isListLike(containerType) && mode.isSubscript();
      characterLookup =
          new PositionCharacterLookupNode(
              mode, numDimensions, dimensionIndex, useNAForNotFound, exact);
    }
  }

  protected static boolean isListLike(RType type) {
    switch (type) {
      case Language:
      case DataFrame:
      case Expression:
      case PairList:
      case List:
        return true;
    }
    return false;
  }

  public boolean isIgnoreDimension() {
    return positionClass == RMissing.class;
  }

  public Class<?> getPositionClass() {
    return positionClass;
  }

  public final boolean isSupported(Object object) {
    return object.getClass() == positionClass;
  }

  public static PositionCheckNode createNode(
      ElementAccessMode mode,
      RType containerType,
      Object position,
      int positionIndex,
      int numDimensions,
      boolean exact,
      boolean replace,
      boolean recursive) {
    if (mode.isSubset()) {
      return PositionCheckSubsetNodeGen.create(
          mode, containerType, position, positionIndex, numDimensions, exact, replace);
    } else {
      return PositionCheckSubscriptNodeGen.create(
          mode, containerType, position, positionIndex, numDimensions, exact, replace, recursive);
    }
  }

  protected boolean isMultiDimension() {
    return numDimensions > 1;
  }

  public final Object execute(
      PositionProfile profile,
      RAbstractContainer vector,
      int[] vectorDimensions,
      int vectorLength,
      Object position) {
    Object castPosition = castNode.execute(positionClass.cast(position));

    int dimensionLength;
    if (numDimensions == 1) {
      dimensionLength = vectorLength;
    } else {
      assert vectorDimensions != null;
      assert vectorDimensions.length == numDimensions;
      dimensionLength = vectorDimensions[dimensionIndex];
    }

    if (characterLookup != null) {
      castPosition =
          characterLookup.execute(vector, (RAbstractStringVector) castPosition, dimensionLength);
    }

    RTypedValue positionVector = (RTypedValue) profilePosition(castPosition);

    int positionLength;
    if (positionVector instanceof RMissing) {
      positionLength = -1;
    } else {
      positionLength =
          positionLengthProfile.profile(((RAbstractVector) positionVector).getLength());
    }

    assert isValidCastedType(positionVector)
        : "result type of a position cast node must be integer or logical";

    return execute(profile, dimensionLength, positionVector, positionLength);
  }

  private final ValueProfile castedValue = ValueProfile.createClassProfile();

  Object profilePosition(Object positionVector) {
    return castedValue.profile(positionVector);
  }

  private static boolean isValidCastedType(RTypedValue positionVector) {
    RType type = positionVector.getRType();
    return type == RType.Integer
        || type == RType.Logical
        || type == RType.Character
        || type == RType.Double
        || type == RType.Null;
  }

  public abstract Object execute(
      PositionProfile statistics, int dimensionLength, Object position, int positionLength);
}
Пример #15
0
/**
 * The {@code rep} builtin works as follows.
 *
 * <ol>
 *   <li>If {@code each} is greater than one, all elements of {@code x} are first replicated {@code
 *       each} times.
 *   <li>If {@code length.out} is given, the result of the first step is truncated or extended as
 *       required. In this case, {@code times} is ignored.
 *   <li>If {@code length.out} is not given, {@code times} is regarded:
 *       <ul>
 *         <li>If {@code times} is a one-element vector, the result of the first step is replicated
 *             {@code times} times.
 *         <li>If {@code times} is a vector longer than one, and {@code each} is greater than one,
 *             an error is issued.
 *         <li>If {@code times} is a vector longer than one, and {@code each} is one, and {@code
 *             times} is as long as {@code x}, each element of {@code x} is given the number of
 *             times indicated by the value at the same index of {@code times}. If {@code times} has
 *             a different length, an error is issued.
 *       </ul>
 * </ol>
 */
@RBuiltin(
    name = "rep",
    kind = PRIMITIVE,
    parameterNames = {"x", "times", "length.out", "each"},
    dispatch = INTERNAL_GENERIC,
    behavior = PURE)
public abstract class Repeat extends RBuiltinNode {

  protected abstract Object execute(
      RAbstractVector x, RAbstractIntVector times, int lengthOut, int each);

  private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile();
  private final BranchProfile errorBranch = BranchProfile.create();
  private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile();
  private final ConditionProfile replicateOnce = ConditionProfile.createBinaryProfile();
  @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();

  @Override
  public Object[] getDefaultParameterValues() {
    return new Object[] {RMissing.instance, 1, RRuntime.INT_NA, 1};
  }

  private String argType(Object arg) {
    return ((RTypedValue) arg).getRType().getName();
  }

  @Override
  protected void createCasts(CastBuilder casts) {
    Function<Object, Object> argType = this::argType;
    casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, argType);
    casts
        .arg("times")
        .defaultError(RError.Message.INVALID_ARGUMENT, "times")
        .mustNotBeNull()
        .asIntegerVector();
    casts
        .arg("length.out")
        .mustNotBeNull()
        .asIntegerVector()
        .shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "length.out")
        .findFirst(RRuntime.INT_NA, RError.Message.FIRST_ELEMENT_USED, "length.out")
        .mustBe(intNA().or(gte(0)));
    casts
        .arg("each")
        .asIntegerVector()
        .shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "each")
        .findFirst(1, RError.Message.FIRST_ELEMENT_USED, "each")
        .notNA(1)
        .mustBe(gte(0));
  }

  protected boolean hasNames(RAbstractVector x) {
    return getNames.getNames(x) != null;
  }

  private RError invalidTimes() {
    throw RError.error(this, RError.Message.INVALID_ARGUMENT, "times");
  }

  @Specialization(
      guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"})
  protected RAbstractVector repNoEachNoNamesSimple(
      RAbstractDoubleVector x,
      RAbstractIntVector times,
      int lengthOut,
      @SuppressWarnings("unused") int each) {
    int t = times.getDataAt(0);
    if (t < 0) {
      errorBranch.enter();
      throw invalidTimes();
    }
    int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t;
    double[] data = new double[length];
    Arrays.fill(data, x.getDataAt(0));
    return RDataFactory.createDoubleVector(data, !RRuntime.isNA(x.getDataAt(0)));
  }

  @Specialization(guards = {"each > 1", "!hasNames(x)"})
  protected RAbstractVector repEachNoNames(
      RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) {
    if (times.getLength() > 1) {
      errorBranch.enter();
      throw invalidTimes();
    }
    RAbstractVector input = handleEach(x, each);
    if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
      return handleLengthOut(input, lengthOut, false);
    } else {
      return handleTimes(input, times, false);
    }
  }

  @Specialization(guards = {"each <= 1", "!hasNames(x)"})
  protected RAbstractVector repNoEachNoNames(
      RAbstractVector x,
      RAbstractIntVector times,
      int lengthOut,
      @SuppressWarnings("unused") int each) {
    if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
      return handleLengthOut(x, lengthOut, true);
    } else {
      return handleTimes(x, times, true);
    }
  }

  @Specialization(guards = {"each > 1", "hasNames(x)"})
  protected RAbstractVector repEachNames(
      RAbstractVector x,
      RAbstractIntVector times,
      int lengthOut,
      int each,
      @Cached("create()") InitAttributesNode initAttributes,
      @Cached("createNames()") SetFixedAttributeNode putNames) {
    if (times.getLength() > 1) {
      errorBranch.enter();
      throw invalidTimes();
    }
    RAbstractVector input = handleEach(x, each);
    RStringVector names = (RStringVector) handleEach(getNames.getNames(x), each);
    RVector<?> r;
    if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
      names = (RStringVector) handleLengthOut(names, lengthOut, false);
      r = handleLengthOut(input, lengthOut, false);
    } else {
      names = (RStringVector) handleTimes(names, times, false);
      r = handleTimes(input, times, false);
    }
    putNames.execute(initAttributes.execute(r), names);
    return r;
  }

  @Specialization(guards = {"each <= 1", "hasNames(x)"})
  protected RAbstractVector repNoEachNames(
      RAbstractVector x,
      RAbstractIntVector times,
      int lengthOut,
      @SuppressWarnings("unused") int each,
      @Cached("create()") InitAttributesNode initAttributes,
      @Cached("createNames()") SetFixedAttributeNode putNames) {
    RStringVector names;
    RVector<?> r;
    if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
      names = (RStringVector) handleLengthOut(getNames.getNames(x), lengthOut, true);
      r = handleLengthOut(x, lengthOut, true);
    } else {
      names = (RStringVector) handleTimes(getNames.getNames(x), times, true);
      r = handleTimes(x, times, true);
    }
    putNames.execute(initAttributes.execute(r), names);
    return r;
  }

  /** Prepare the input vector by replicating its elements. */
  private static RVector<?> handleEach(RAbstractVector x, int each) {
    RVector<?> r = x.createEmptySameType(x.getLength() * each, x.isComplete());
    for (int i = 0; i < x.getLength(); i++) {
      for (int j = i * each; j < (i + 1) * each; j++) {
        r.transferElementSameType(j, x, i);
      }
    }
    return r;
  }

  /** Extend or truncate the vector to a specified length. */
  private static RVector<?> handleLengthOut(
      RAbstractVector x, int lengthOut, boolean copyIfSameSize) {
    if (x.getLength() == lengthOut) {
      return (RVector<?>) (copyIfSameSize ? x.copy() : x);
    }
    return x.copyResized(lengthOut, false);
  }

  /** Replicate the vector a given number of times. */
  private RVector<?> handleTimes(
      RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) {
    if (oneTimeGiven.profile(times.getLength() == 1)) {
      // only one times value is given
      final int howManyTimes = times.getDataAt(0);
      if (howManyTimes < 0) {
        errorBranch.enter();
        throw invalidTimes();
      }
      if (replicateOnce.profile(howManyTimes == 1)) {
        return (RVector<?>) (copyIfSameSize ? x.copy() : x);
      } else {
        return x.copyResized(x.getLength() * howManyTimes, false);
      }
    } else {
      // times is a vector with several elements
      if (x.getLength() != times.getLength()) {
        errorBranch.enter();
        invalidTimes();
      }
      // iterate once over the times vector to determine result vector size
      int resultLength = 0;
      for (int i = 0; i < times.getLength(); i++) {
        int t = times.getDataAt(i);
        if (t < 0) {
          errorBranch.enter();
          throw invalidTimes();
        }
        resultLength += t;
      }
      // create and populate result vector
      RVector<?> r = x.createEmptySameType(resultLength, x.isComplete());
      int wp = 0; // write pointer
      for (int i = 0; i < x.getLength(); i++) {
        for (int j = 0; j < times.getDataAt(i); ++j, ++wp) {
          r.transferElementSameType(wp, x, i);
        }
      }
      return r;
    }
  }
}