Example #1
0
  private SemanticType propagate(
      Expr.IndexOf e,
      HashMap<String, SemanticType> environment,
      HashSet<String> generics,
      WyalFile.Context context) {
    SemanticType src_type = propagate(e.operand, environment, generics, context);
    SemanticType index_type = propagate(e.index, environment, generics, context);
    if (src_type instanceof SemanticType.EffectiveTuple) {
      SemanticType.EffectiveTuple tt = (SemanticType.EffectiveTuple) src_type;
      checkIsSubtype(SemanticType.Int, index_type, e.operand);
      if (!(e.index instanceof Expr.Constant)) {
        syntaxError("constant index required for tuple load", filename, e.index);
      }
    } else {
      checkIsSubtype(SemanticType.SetTupleAnyAny, src_type, e.operand);
      // FIXME: handle case for effective set (i.e. union of sets)
      SemanticType.Set st = (SemanticType.Set) src_type;
      SemanticType.EffectiveTuple tt = (SemanticType.EffectiveTuple) st.element();
      // FIXME: handle case for effective tuple of wrong size
      checkIsSubtype(tt.tupleElement(0), index_type, e.index);
    }

    return src_type;
  }
Example #2
0
 /**
  * Calculate the most precise type that captures those possible values a given expression can
  * evaluate to.
  *
  * @param e
  * @return
  */
 public static SemanticType returnType(Expr e) {
   SemanticType type = e.attribute(TypeAttribute.class).type;
   if (e instanceof Expr.Variable || e instanceof Expr.Constant || e instanceof Expr.Quantifier) {
     return type;
   } else if (e instanceof Expr.Unary) {
     Expr.Unary ue = (Expr.Unary) e;
     switch (ue.op) {
       case NOT:
         return SemanticType.Bool;
       case NEG:
         return type;
       case LENGTHOF:
         return SemanticType.Int;
     }
   } else if (e instanceof Expr.Binary) {
     Expr.Binary ue = (Expr.Binary) e;
     switch (ue.op) {
       case ADD:
       case SUB:
       case MUL:
       case DIV:
       case REM:
       case SETUNION:
       case SETINTERSECTION:
       case LISTAPPEND:
       case RANGE:
         return type;
       case EQ:
       case NEQ:
       case IMPLIES:
       case IFF:
       case LT:
       case LTEQ:
       case GT:
       case GTEQ:
       case IN:
       case SUBSET:
       case SUBSETEQ:
       case SUPSET:
       case SUPSETEQ:
         return SemanticType.Bool;
     }
   } else if (e instanceof Expr.Ternary) {
     Expr.Ternary ue = (Expr.Ternary) e;
     switch (ue.op) {
       case UPDATE:
       case SUBLIST:
         return type;
     }
   } else if (e instanceof Expr.Nary) {
     Expr.Nary ue = (Expr.Nary) e;
     switch (ue.op) {
       case AND:
       case OR:
         return SemanticType.Bool;
       case TUPLE:
       case SET:
       case LIST:
         return type;
     }
   } else if (e instanceof Expr.IndexOf) {
     Expr.IndexOf ue = (Expr.IndexOf) e;
     if (type instanceof SemanticType.EffectiveTuple) {
       SemanticType.EffectiveTuple tt = (SemanticType.EffectiveTuple) type;
       Value.Integer idx = (Value.Integer) ((Expr.Constant) ue.index).value;
       return tt.tupleElement(idx.value.intValue());
     } else {
       SemanticType.Set st = (SemanticType.Set) type;
       SemanticType.EffectiveTuple tt = (SemanticType.EffectiveTuple) st.element();
       return tt.tupleElement(1);
     }
   } else {
     Expr.FunCall fc = (Expr.FunCall) e;
     return ((SemanticType.Function) type).to();
   }
   // should be deadcode.
   throw new IllegalArgumentException("Invalid opcode for expression");
 }