示例#1
0
  // make a property args from the this accessor sig and kind
  public FuncInfo propertySig(final String accessorName) {
    FuncInfo fi = null;
    if (accessorName.equals("set")) {

      // remove the last argument from the set accessor

      Debug.Assert(
          +_paramTypes.length > 0,
          "a set accessor must have at least one argument (the value arg)");

      fi = new FuncInfo(this); // copy
      final int numPropArgs = _paramTypes.length - 1;

      final TypeSpec[] pTypes = new TypeSpec[numPropArgs];
      for (int i = 0; i < numPropArgs; i++) {
        pTypes[i] = _paramTypes[i];
      }

      final String[] pNames = new String[numPropArgs];
      for (int i = 0; i < numPropArgs; i++) {
        pNames[i] = _paramNames[i];
      }

      final Object[] pDefaults = new Object[numPropArgs];
      for (int i = 0; i < numPropArgs; i++) {
        pDefaults[i] = _paramDefaults[i];
      }

      final boolean[] pHasDefault = new boolean[numPropArgs];
      for (int i = 0; i < numPropArgs; i++) {
        pHasDefault[i] = _paramHasDefault[i];
      }

      fi._paramNames = pNames;
      fi._paramTypes = pTypes;
      fi._paramDefaults = pDefaults;
      fi._paramHasDefault = pHasDefault;
    } else if (accessorName.equals("get")) {
      // property args are the same as the get accessor args, no change
      fi = new FuncInfo(this); // copy
    } else {
      Debug.Assert(false, "invalid accessor kind name (should be 'get' or 'set'");
    }
    return fi;
  }
示例#2
0
  // compare for equality, ignoring return types
  // NB: doens't consider param names or default values
  public boolean equalsParams(final FuncInfo f) {
    if (f == null) {
      return false;
    }
    if (f.numArgs() != numArgs()) {
      return false;
    }

    if (f.numRequiredArgs() != numRequiredArgs()) {
      return false;
    }

    for (int a = 0; a < numArgs(); a++) {
      if (!_paramTypes[a].equals(f._paramTypes[a])) {
        return false;
      }
    }
    return true;
  }
示例#3
0
 public static TypeSpec propertyTypeFromAccessor(
     final String accessorName, final FuncInfo accessorSig) {
   if (accessorName.equals("get")) {
     return accessorSig._returnType;
   } else if (accessorName.equals("set")) {
     return accessorSig._paramTypes[accessorSig.numArgs() - 1];
   } else {
     Debug.Assert(false, "invalid accessor name");
   }
   return null;
 }
示例#4
0
  // can this func be called using a call with signature callSig?
  // if callSig.returnType is any, then ignore return type compatibility
  // (NB: this doesn't consider implicit argument conversions, use
  // TypeManager.isMatchingFunc() for that)
  public boolean callCompatible(final FuncInfo callSig) {
    Debug.Assert(callSig != null);

    if (callSig.numArgs() < numRequiredArgs()) {
      return false; // not enough args
    }
    if (callSig.numArgs() > numArgs()) {
      return false; // too many args
    }

    // check types
    for (int a = 0; a < callSig.numArgs(); a++) {
      if (!_paramTypes[a].equals(callSig._paramTypes[a])) {
        return false;
      }
    }

    if (callSig.getReturnType() != null) {
      if (!callSig.getReturnType().equals(TypeSpec.typeOf("any"))) {
        if (!_returnType.equals(callSig.getReturnType())) {
          return false;
        }
      }
    }

    return true;
  }
示例#5
0
  // make a property accessor signature from this property args and the
  // property type
  public FuncInfo accessorSig(final String accessorName, final TypeSpec propertyType) {
    FuncInfo fi = null;
    if (accessorName.equals("set")) { // add the propertyType as an extra
      // parameter named 'value'
      fi = new FuncInfo();
      final int numPropArgs = _paramTypes.length;

      final TypeSpec[] pTypes = new TypeSpec[numPropArgs + 1];
      for (int i = 0; i < numPropArgs; i++) {
        pTypes[i] = _paramTypes[i];
      }
      pTypes[numPropArgs] = propertyType;

      final String[] pNames = new String[numPropArgs + 1];
      for (int i = 0; i < numPropArgs; i++) {
        pNames[i] = _paramNames[i];
      }
      pNames[numPropArgs] = "value";

      final Object[] pDefaults = new Object[numPropArgs + 1];
      for (int i = 0; i < numPropArgs; i++) {
        pDefaults[i] = _paramDefaults[i];
      }
      pDefaults[numPropArgs] = null;

      final boolean[] pHasDefault = new boolean[numPropArgs + 1];
      for (int i = 0; i < numPropArgs; i++) {
        pHasDefault[i] = _paramHasDefault[i];
      }
      pHasDefault[numPropArgs] = false;

      fi._paramNames = pNames;
      fi._paramTypes = pTypes;
      fi._paramDefaults = pDefaults;
      fi._paramHasDefault = pHasDefault;
    } else if (accessorName.equals("get")) { // set the returnType to the
      // propertyType
      fi = new FuncInfo(this);
      fi._returnType = propertyType;
    } else {
      Debug.Assert(false, "invalid accessor kind name (should be 'get' or 'set'");
    }
    return fi;
  }
示例#6
0
  // convert the args for a call with signature callSig that is compatible
  // with this
  // to exactly the types this func expects (including filling in defaults if
  // possible)
  // throws on arg type or number mismatch
  public Object[] convertParameters(
      final FuncInfo callSig, Object[] args, final boolean externCall) {
    if (args == null) {
      args = new Object[0];
    }

    Debug.Assert(callSig != null);
    Debug.Assert(callSig.numArgs() == args.length, "supplied arg count must match callSig");

    // if (externCall) //!!!
    // Debug.WriteLine("Warning: FuncInfo.convertParameters() - externCall being ignored
    // (unimplemented)");

    if (numRequiredArgs() > callSig.numArgs()) {
      ScigolTreeParser.semanticError(
          callSig.getDefinitionLocation(),
          "not enough arguments for function " + this + " in call with signature " + callSig);
    }

    if (callSig.numArgs() > numArgs()) {
      ScigolTreeParser.semanticError(
          callSig.getDefinitionLocation(),
          "too many arguments for function " + this + " in call with signature " + callSig);
    }

    final Object[] convertedArgs = new Object[numArgs()];

    // for each formal param
    for (int a = 0; a < numArgs(); a++) {

      if (a < callSig.numArgs()) { // if param supplied
        Object arg =
            ((args[a] instanceof Value)
                ? (((Value) args[a]).getValue())
                : args[a]); // convert from Value if
        // necessary

        TypeSpec argType = TypeSpec.typeOf(arg);
        if (!argType.isAny()) { // implicit conversion from any always
          // exists
          // does an implicit conversion from the argType to the
          // parameter type exist?
          if (!TypeManager.existsImplicitConversion(argType, _paramTypes[a], new Value(arg))) {
            ScigolTreeParser.semanticError(
                callSig.getDefinitionLocation(),
                "argument "
                    + a
                    + " ("
                    + _paramNames[a]
                    + ") to func with signature "
                    + this
                    + " is of type '"
                    + argType
                    + "' which is incompatible with parameter type '"
                    + _paramTypes[a]
                    + "'");
          }
        } else {
          arg = TypeSpec.unwrapAny(arg);
          argType = TypeSpec.typeOf(arg);
        }

        // conversion
        final Value convertedArg =
            TypeManager.performImplicitConversion(argType, _paramTypes[a], new Value(arg));

        if (convertedArg == null) {
          ScigolTreeParser.semanticError(
              callSig.getDefinitionLocation(),
              "argument "
                  + a
                  + " ("
                  + _paramNames[a]
                  + ") to func with signature "
                  + this
                  + " is of type '"
                  + argType
                  + "' which cannot be converted into the required parameter type '"
                  + _paramTypes[a]
                  + "'");
        }

        convertedArgs[a] = convertedArg.getValue();
      } else { // not supplied
        // do we have a default value?
        if (!_paramHasDefault[a]) {
          ScigolTreeParser.semanticError(
              callSig.getDefinitionLocation(),
              "in call to function "
                  + this
                  + ", no argument was supplied for parameter "
                  + _paramNames[a]
                  + " (which has no default)");
        }

        // use default
        convertedArgs[a] = _paramDefaults[a];
      }
    } // for each param

    return convertedArgs;
  }