private Node buildFieldDecl(FieldDecl fd) throws SemanticException {
    Type t = fd.declType();

    if (t.isSubtype(SJ_PROTOCOL_TYPE)) {
      if (!(fd instanceof SJFieldProtocolDecl)) {
        throw new SemanticException(
            "[SJProtocolDeclTypeBuilder] Protocols may only be declared using the protocol keyword: "
                + fd);
      }

      SJTypeNode tn = disambiguateSJTypeNode(this, ((SJProtocolDecl) fd).sessionType());
      SJSessionType st = tn.type();
      String sjname = fd.name(); // Should match that given by SJVariable.sjname.

      SJFieldInstance fi = (SJFieldInstance) fd.fieldInstance();
      SJFieldProtocolInstance fpi =
          sjts.SJFieldProtocolInstance((SJFieldInstance) fd.fieldInstance(), st, sjname);

      fpi.setConstantValue(
          fi
              .constantValue()); // Currently, constant checker not run on custom nodes/type
                                 // objects. (Previously done by SJNoAliasTypeBuilder.)

      fd = fd.fieldInstance(fpi);
      fd = (FieldDecl) setSJProtocolDeclExt((SJProtocolDecl) fd, tn, sjname);

      updateSJFieldInstance(fi, fpi);
    }

    return fd;
  }
Beispiel #2
0
  @Override
  public Node leave(Node parent, Node old, Node n, NodeVisitor v) {
    // do context bookkeeping first
    if (old instanceof X10MethodDecl) {
      assert ((X10MethodDecl) old).returnType().type() == returnType.peek();
      returnType.pop();
    }

    // NB: for calls and closure calls, the rules for boxing are complicated,
    // so we insert a simple Cast AST node, so that codegen makes a decision
    // whether to do boxing/unboxing. The goal is to ensure, that
    // the only places, where codegen needs to consider boxing/unboxing
    // are:
    // * casts
    // * method or closure call arguments

    // Generic methods (return type T) can return boxed values (e.g., x10.core.UInt)
    // but in the type instantiated [UInt] subclass it is treated as unboxed int.
    // We need to insert explicit cast to
    // an unboxed type,  so that proper conversion method call is inserted later.
    if (n instanceof X10Call && !(parent instanceof Eval)) {
      X10Call call = (X10Call) n;
      Receiver target = call.target();
      MethodInstance mi = call.methodInstance();
      Type expectedReturnType = call.type();
      // do not insert cast the expected type is already boxed or is void
      if (X10PrettyPrinterVisitor.isBoxedType(expectedReturnType)
          || expectedReturnType.isVoid() // (void) never needs boxing
          // or if the method def type is void -- it is a synthetic method without a proper
          // definition
          || mi.def().returnType().get().isVoid()) return n;
      if (X10PrettyPrinterVisitor.isBoxedType(mi.def().returnType().get())) {
        // only insert cast if the actual returned type is boxed
        return cast(call, expectedReturnType);
      }
    }

    // Closures may be implemented by methods returning boxed or unboxed values,
    // depending on some involved condition that is checked in codegen.
    // So add the dummy type cast to give the codegen
    // chance to handle unboxing in a single place
    if (n instanceof ClosureCall && !(parent instanceof Eval) && !(parent instanceof Cast)) {
      ClosureCall call = (ClosureCall) n;
      // if the return type is not primitive, then unboxing will not be needed
      if (X10PrettyPrinterVisitor.isBoxedType(call.type()) || call.type().isVoid()) return n;
      return cast(call, call.type());
    }

    if (n instanceof Expr) { // boxing may be needed only for expressions
      Expr expr = (Expr) n;

      // parent node still has "old" as its child
      if (isBoxed(expr) && expectsUnboxed(parent, old)) {
        return unbox(expr);
      } else if (isUnboxed(expr) && expectsBoxed(parent, old)) {
        return box(expr);
      }
    }
    return n;
  }
Beispiel #3
0
 public boolean hasDeserializationConstructor(Context context) {
   for (ConstructorDef cd : constructors()) {
     if (cd.formalTypes().size() == 1) {
       Type type = cd.formalTypes().get(0).get();
       if (type.isSubtype(type.typeSystem().Deserializer(), context)) {
         return true;
       }
     }
   }
   return false;
 }
Beispiel #4
0
 /**
  * The ast nodes will use this callback to notify us that they throw an exception of type t. This
  * method will throw a SemanticException if the type t is not allowed to be thrown at this point;
  * the exception t will be added to the throwsSet of all exception checkers in the stack, up to
  * (and not including) the exception checker that catches the exception.
  *
  * @param t The type of exception that the node throws.
  * @throws SemanticException
  */
 public void throwsException(Type t, Position pos) throws SemanticException {
   if (!t.isUncheckedException()) {
     // go through the stack of catches and see if the exception
     // is caught.
     boolean exceptionCaught = false;
     ExceptionChecker ec = this;
     while (!exceptionCaught && ec != null) {
       if (ec.catchable != null) {
         for (Iterator<Type> iter = ec.catchable.iterator(); iter.hasNext(); ) {
           Type catchType = (Type) iter.next();
           if (ts.isSubtype(t, catchType, ts.emptyContext())) {
             exceptionCaught = true;
             break;
           }
         }
       }
       if (!exceptionCaught && ec.throwsSet != null) {
         // add t to ec's throwsSet.
         ec.throwsSet.add(t);
       }
       if (ec.catchAllThrowable) {
         // stop the propagation
         exceptionCaught = true;
       }
       ec = ec.pop();
     }
     if (!exceptionCaught) {
       reportUncaughtException(t, pos);
     }
   }
 }
  private static Map<String, Long> getMessageSVUID(Type messageType)
      throws SJIOException,
          ClassNotFoundException // SJCompilerUtils has a simpler version of this routine.
      {
    HashMap<String, Long> ours = new HashMap<String, Long>();

    if (messageType
        instanceof
        SJSessionType) // Should come before ordinary class cases? (But SJSessionType shouldn't be a
                       // class type).
    {
      ours.putAll(getClassSVUIDs((SJSessionType) messageType));
    } else if (messageType.isPrimitive()) {
      // No SVUID needed for primitive types.
    } else if (messageType.isClass()) // Duplicated from above.
    {
      String className = messageType.toClass().fullName();
      Class<?> c = Class.forName(className);

      if (c.isInterface()) {
        // Interfaces don't have SVUIDs (so what should we do here?). // This encourages use of
        // abstract classes rather than interfaces for message types?
      } else {
        ObjectStreamClass osc = ObjectStreamClass.lookup(c);

        if (osc == null) {
          throw new SJIOException("Class not serializable: " + c);
        }

        ours.put(
            className,
            osc
                .getSerialVersionUID()); // Not possible to find a different SVUID for the same
                                         // (name) class here? // SVUIDs could be recorded in the
                                         // session type objects. // Put currently problems working
                                         // with these values at compilation time if the class
                                         // binary is not available a priori (SVUID value not built
                                         // yet?).
      }
    } else if (messageType.isArray()) {
      throw new SJIOException("Array types not done yet: " + messageType);
    }

    return ours;
  }
  private Node buildFormal(Formal f) throws SemanticException // Based on buildLocalDecl.
      {
    Type t = f.declType();
    SJLocalInstance li = (SJLocalInstance) f.localInstance();

    if (t.isSubtype(SJ_ABSTRACT_CHANNEL_TYPE)) {
      if (!(f instanceof SJFormal)) {
        throw new SemanticException(
            "[SJProtocolDeclTypeBuilder] Session socket parameters should be declared by their session type: "
                + f);
      }

      SJTypeNode tn = disambiguateSJTypeNode(this, ((SJFormal) f).sessionType());
      SJSessionType st = tn.type();
      String sjname = f.name(); // Should match that given by SJVariable.sjname.

      f = f.localInstance(sjts.SJLocalProtocolInstance(li, st, sjname));
      f = setSJFormalExt((SJFormal) f, tn, sjname);
    }

    return f;
  }
  private Node buildLocalDecl(LocalDecl ld) throws SemanticException {
    Type t = ld.declType();
    SJLocalInstance li = (SJLocalInstance) ld.localInstance();
    // SJNamedInstance ni = null;

    if (t.isSubtype(SJ_PROTOCOL_TYPE)) // Mostly the same as for LocalDecl.
    {
      if (!(ld instanceof SJLocalProtocolDecl)) {
        throw new SemanticException(
            "[SJProtocolDeclTypeBuilder] Protocols may only be declared using the protocol keyword: "
                + ld);
      }

      SJTypeNode tn = disambiguateSJTypeNode(this, ((SJProtocolDecl) ld).sessionType());
      SJSessionType st = tn.type();
      String sjname = ld.name(); // Should match that given by SJVariable.sjname.

      ld = ld.localInstance(sjts.SJLocalProtocolInstance(li, st, sjname));
      ld = (LocalDecl) setSJProtocolDeclExt((SJProtocolDecl) ld, tn, sjname);
    }

    return ld;
  }
Beispiel #8
0
 void uncaughtType(Type t, Position pos) throws SemanticException {
   SemanticException e =
       new SemanticException(
           codeType
               + " cannot throw a \""
               + t
               + "\"; the exception must either be caught or declared to be thrown.",
           pos);
   Map<String, Object> map = CollectionFactory.newHashMap();
   map.put(CodedErrorInfo.ERROR_CODE_KEY, CodedErrorInfo.ERROR_CODE_SURROUND_THROW);
   map.put("TYPE", t.toString());
   e.setAttributes(map);
   throw e;
 }
Beispiel #9
0
  /** Type check the statement. */
  public Node typeCheck(TypeChecker tc) throws SemanticException {
    TypeSystem ts = tc.typeSystem();

    // Check that all initializers have the same type.
    // This should be enforced by the parser, but check again here,
    // just to be sure.
    Type t = null;

    for (Iterator i = inits.iterator(); i.hasNext(); ) {
      ForInit s = (ForInit) i.next();

      if (s instanceof LocalDecl) {
        LocalDecl d = (LocalDecl) s;
        Type dt = d.type().type();
        if (t == null) {
          t = dt;
        } else if (!t.equals(dt)) {
          throw new InternalCompilerError(
              "Local variable "
                  + "declarations in a for loop initializer must all "
                  + "be the same type, in this case "
                  + t
                  + ", not "
                  + dt
                  + ".",
              d.position());
        }
      }
    }

    if (cond != null && !ts.isImplicitCastValid(cond.type(), ts.Boolean())) {
      throw new SemanticException(
          "The condition of a for statement must have boolean type.", cond.position());
    }

    return this;
  }
Beispiel #10
0
 @Override
 public boolean typeEquals(Type type1, Type type2) {
   // Removed the assert_ calls as this is a hotspot when using typecase
   return type1.typeEqualsImpl(type2);
 }
  private Node translateExtendedFor(ExtendedFor n, List<String> labels) throws SemanticException {

    if (n.expr().type().isArray()) {
      return translateExtForArray(n, labels);
    }

    Position pos = Position.compilerGenerated();
    Type iterType = ts.typeForName("java.util.Iterator");
    Type iteratedType = n.decl().type().type();
    // translate "L1,...,Ln: for (C x: e) b" to
    // "{ Iterator iter = e.iterator(); L1,...,Ln: while (iter.hasNext();)  { C x = (C)iter.next();
    // b }"

    // Create the iter declaration "Iterator iter = e.iterator()"
    Id iterName = freshName("iter");
    LocalDecl iterDecl;
    LocalInstance iterLI = ts.localInstance(pos, Flags.NONE, iterType, iterName.id());
    {
      Id id = nodeFactory().Id(pos, "iterator");
      Call iterator = nodeFactory().Call(pos, n.expr(), id);
      iterator = (Call) iterator.type(iterType);
      iterator =
          iterator.methodInstance(
              ts.findMethod(
                  n.expr().type().toClass(),
                  "iterator",
                  Collections.<Type>emptyList(),
                  this.context().currentClass()));

      iterDecl =
          nodeFactory()
              .LocalDecl(
                  pos,
                  Flags.NONE,
                  nodeFactory().CanonicalTypeNode(pos, iterType),
                  iterName,
                  iterator);
      iterDecl = iterDecl.localInstance(iterLI);
    }

    // create the loop body
    List<Stmt> loopBody = new ArrayList<Stmt>();
    {
      Id id = nodeFactory().Id(pos, "next");
      Call call =
          nodeFactory()
              .Call(
                  pos,
                  ((Local) nodeFactory().Local(pos, iterName).type(iterType))
                      .localInstance(iterDecl.localInstance()),
                  id);
      call = (Call) call.type(ts.Object());
      call =
          call.methodInstance(
              ts.findMethod(
                  iterType.toClass(),
                  "next",
                  Collections.<Type>emptyList(),
                  this.context().currentClass()));

      Cast cast = nodeFactory().Cast(pos, nodeFactory().CanonicalTypeNode(pos, iteratedType), call);
      cast = (Cast) cast.type(iteratedType);

      loopBody.add(n.decl().init(cast));
      loopBody.add(n.body());
    }

    // create the while loop
    While loop;
    {
      Id id = nodeFactory().Id(pos, "hasNext");
      Call cond =
          nodeFactory()
              .Call(
                  pos,
                  ((Local) nodeFactory().Local(pos, iterName).type(iterType))
                      .localInstance(iterDecl.localInstance()),
                  id);
      cond = (Call) cond.type(ts.Boolean());
      cond =
          cond.methodInstance(
              ts.findMethod(
                  iterType.toClass(),
                  "hasNext",
                  Collections.<Type>emptyList(),
                  this.context().currentClass()));

      loop = nodeFactory().While(pos, cond, nodeFactory().Block(pos, loopBody));
    }

    return nodeFactory().Block(pos, iterDecl, labelStmt(loop, labels));
  }
  public boolean callValid(Type thisType, List<Type> argTypes, Context context) {
    JL5TypeSystem ts = (JL5TypeSystem) typeSystem();
    List<Type> l1 = this.formalTypes();
    List<Type> l2 = argTypes;
    if ((l1.size() == 0) && (l2.size() != 0)) return false;

    Iterator<Type> itCallee = l1.iterator();
    Iterator<Type> itCaller = l2.iterator();

    // caller can either:
    // - have one argument less than callee (last argument of
    //   callee is a varargs and caller do not provide a value)
    // - have same number of args. The last arg being either
    //		- same type as the last arg of callee
    //		- or same type as the last arg of callee which is a varargs array
    //		- or an array of same type as the last arg of callee (which could be a varargs array)
    // - have more args, then:
    //		- last args of callee must be a varargs array
    //		- all extra args provided by the caller must match
    //        the varargs array type of the callee.

    while (itCallee.hasNext() && itCaller.hasNext()) {
      Type t1 = itCallee.next();
      Type t2 = itCaller.next();

      // Varargs can be used only in the final argument position
      // When we reach the final argument, we check if it is varargs array.
      if (!itCallee.hasNext() && t1.isArray() && ((JL5ArrayType) t1).isVarargs()) {
        JL5ArrayType vartype = (JL5ArrayType) t1;
        // Every arguments remaining in the second iterator must match the type
        // of the varargs array

        if (!itCaller.hasNext()) {
          // if we also reached the last element of the caller,
          // check if the type matches or if it is an array
          return ts.isImplicitCastValid(t2, vartype, context)
              || ts.isImplicitCastValid(t2, vartype.base(), context);
        } else {
          // There are several arguments left, they should all match the callee's varargs array
          // type.
          while (itCaller.hasNext()) { // eat up actual args
            if (!ts.isImplicitCastValid(t2, vartype.base(), context)) {
              return false;
            }
            t2 = itCaller.next();
          }
        }
      } else {
        if (!ts.isImplicitCastValid(t2, t1, context)) {
          return false;
        }
      }
    }
    // Caller provided less args than the callee has, which is legal
    // if callee is a variable arity method
    if (itCallee.hasNext() && isVariableArrity()) {
      itCallee.next();
    }

    // and we've reached callee's last arg.
    return !(itCallee.hasNext() || itCaller.hasNext());
  }