private SemanticType propagate( Expr.Nary e, HashMap<String, SemanticType> environment, HashSet<String> generics, WyalFile.Context context) { Expr[] e_operands = e.operands; SemanticType[] op_types = new SemanticType[e_operands.length]; for (int i = 0; i != e_operands.length; ++i) { op_types[i] = propagate(e_operands[i], environment, generics, context); } switch (e.op) { case AND: case OR: for (int i = 0; i != e_operands.length; ++i) { checkIsSubtype(SemanticType.Bool, op_types[i], e_operands[i]); } return SemanticType.Bool; case TUPLE: return SemanticType.Tuple(op_types); case SET: if (op_types.length == 0) { return SemanticType.Set(true, SemanticType.Void); } else { return SemanticType.Set(true, SemanticType.Or(op_types)); } case LIST: if (op_types.length == 0) { return SemanticType.Set(true, SemanticType.Void); } else { return SemanticType.Set( true, SemanticType.Tuple(SemanticType.Int, SemanticType.Or(op_types))); } } internalFailure("unknown nary expression encountered (" + e + ")", filename, e); return null; // deadcode }
private SemanticType propagate( Expr.Binary e, HashMap<String, SemanticType> environment, HashSet<String> generics, WyalFile.Context context) { SemanticType lhs_type = propagate(e.leftOperand, environment, generics, context); SemanticType rhs_type = propagate(e.rightOperand, environment, generics, context); switch (e.op) { case ADD: case SUB: case MUL: case DIV: case REM: checkIsSubtype(SemanticType.IntOrReal, lhs_type, e.leftOperand); checkIsSubtype(SemanticType.IntOrReal, rhs_type, e.rightOperand); return SemanticType.Or(lhs_type, rhs_type); case EQ: case NEQ: return SemanticType.Or(lhs_type, rhs_type); case IMPLIES: case IFF: checkIsSubtype(SemanticType.Bool, lhs_type, e.leftOperand); checkIsSubtype(SemanticType.Bool, rhs_type, e.rightOperand); return SemanticType.Bool; case LT: case LTEQ: case GT: case GTEQ: checkIsSubtype(SemanticType.IntOrReal, lhs_type, e.leftOperand); checkIsSubtype(SemanticType.IntOrReal, rhs_type, e.rightOperand); return SemanticType.Or(lhs_type, rhs_type); case IN: { checkIsSubtype(SemanticType.SetAny, rhs_type, e.rightOperand); SemanticType.Set s = (SemanticType.Set) rhs_type; return s; } case SUBSET: case SUBSETEQ: case SUPSET: case SUPSETEQ: { checkIsSubtype(SemanticType.SetAny, lhs_type, e.leftOperand); checkIsSubtype(SemanticType.SetAny, rhs_type, e.rightOperand); // following can cause some problems // checkIsSubtype(lhs_type,rhs_type,e); return SemanticType.Or(lhs_type, rhs_type); } case SETUNION: { checkIsSubtype(SemanticType.SetAny, lhs_type, e.leftOperand); checkIsSubtype(SemanticType.SetAny, rhs_type, e.rightOperand); SemanticType.Set l = (SemanticType.Set) lhs_type; SemanticType.Set r = (SemanticType.Set) rhs_type; return SemanticType.Set(true, SemanticType.Or(l.element(), r.element())); } case SETINTERSECTION: { checkIsSubtype(SemanticType.SetAny, lhs_type, e.leftOperand); checkIsSubtype(SemanticType.SetAny, rhs_type, e.rightOperand); // TODO: the following gives a more accurate type, but there are // some outstanding issues related to the type system reduction // rules. // return SemanticType.And(lhs_type,rhs_type); SemanticType.Set l = (SemanticType.Set) lhs_type; SemanticType.Set r = (SemanticType.Set) rhs_type; return SemanticType.Set(true, SemanticType.Or(l.element(), r.element())); } case LISTAPPEND: { checkIsSubtype(SemanticType.SetTupleAnyAny, lhs_type, e.leftOperand); checkIsSubtype(SemanticType.SetTupleAnyAny, rhs_type, e.rightOperand); SemanticType.Set l = (SemanticType.Set) lhs_type; SemanticType.Set r = (SemanticType.Set) rhs_type; return SemanticType.Set(true, SemanticType.Or(l.element(), r.element())); } case RANGE: { checkIsSubtype(SemanticType.Int, lhs_type, e.leftOperand); checkIsSubtype(SemanticType.Int, rhs_type, e.rightOperand); return SemanticType.Set(true, SemanticType.Tuple(SemanticType.Int, SemanticType.Int)); } } internalFailure("unknown binary expression encountered (" + e + ")", filename, e); return null; // deadcode }