示例#1
0
 /**
  * Perform type propagation through a given expression, returning the type of value that is
  * returned by evaluating this expression.
  *
  * @param e
  * @param environment
  * @param generics
  * @param context
  * @return
  */
 private SemanticType propagate(
     Expr e,
     HashMap<String, SemanticType> environment,
     HashSet<String> generics,
     WyalFile.Context context) {
   SemanticType t;
   if (e instanceof Expr.Variable) {
     t = propagate((Expr.Variable) e, environment, generics, context);
   } else if (e instanceof Expr.Constant) {
     t = propagate((Expr.Constant) e, environment, generics, context);
   } else if (e instanceof Expr.Unary) {
     t = propagate((Expr.Unary) e, environment, generics, context);
   } else if (e instanceof Expr.Binary) {
     t = propagate((Expr.Binary) e, environment, generics, context);
   } else if (e instanceof Expr.Ternary) {
     t = propagate((Expr.Ternary) e, environment, generics, context);
   } else if (e instanceof Expr.Nary) {
     t = propagate((Expr.Nary) e, environment, generics, context);
   } else if (e instanceof Expr.Quantifier) {
     t = propagate((Expr.Quantifier) e, environment, generics, context);
   } else if (e instanceof Expr.FunCall) {
     t = propagate((Expr.FunCall) e, environment, generics, context);
   } else if (e instanceof Expr.IndexOf) {
     t = propagate((Expr.IndexOf) e, environment, generics, context);
   } else {
     internalFailure("unknown expression encountered (" + e + ")", filename, e);
     return null;
   }
   e.attributes().add(new TypeAttribute(t));
   return returnType(e);
 }
示例#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");
 }