diff --git a/src/main/java/de/tla2b/analysis/TypeChecker.java b/src/main/java/de/tla2b/analysis/TypeChecker.java index e18192046231bd959cd2a0bd60f882ac587ce5a8..895078167e2cbb43abe73503ae5c79acc8ebbd9e 100644 --- a/src/main/java/de/tla2b/analysis/TypeChecker.java +++ b/src/main/java/de/tla2b/analysis/TypeChecker.java @@ -347,15 +347,10 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo case OPCODE_eq: // = case OPCODE_noteq: // /=, # { - try { - BoolType.getInstance().unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected %s, found BOOL at '%s',%n%s", expected, - n.getOperator().getName(), n.getLocation())); - } - TLAType left = visitExprOrOpArgNode(n.getArgs()[0], new de.tla2b.types.UntypedType()); + TLAType opType = unify(BoolType.getInstance(), expected, n); + TLAType left = visitExprOrOpArgNode(n.getArgs()[0], new UntypedType()); visitExprOrOpArgNode(n.getArgs()[1], left); - return BoolType.getInstance(); + return opType; } /* @@ -370,16 +365,11 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo case OPCODE_equiv: // \equiv case OPCODE_implies: // => { - try { - BoolType.getInstance().unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected %s, found BOOL at '%s',%n%s", expected, - n.getOperator().getName(), n.getLocation())); - } + TLAType opType = unify(BoolType.getInstance(), expected, n); for (int i = 0; i < n.getArgs().length; i++) { visitExprOrOpArgNode(n.getArgs()[i], BoolType.getInstance()); } - return BoolType.getInstance(); + return opType; } /* @@ -388,15 +378,10 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo case OPCODE_be: // \E x \in S : P case OPCODE_bf: // \A x \in S : P { - try { - BoolType.getInstance().unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected %s, found BOOL at '%s',%n%s", expected, - n.getOperator().getName(), n.getLocation())); - } + TLAType opType = unify(BoolType.getInstance(), expected, n); evalBoundedVariables(n); visitExprOrOpArgNode(n.getArgs()[0], BoolType.getInstance()); - return BoolType.getInstance(); + return opType; } /* @@ -404,13 +389,7 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo */ case OPCODE_se: // SetEnumeration {..} { - SetType found = new SetType(new UntypedType()); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException( - String.format("Expected %s, found POW(_A) at set enumeration,%n%s", expected, n.getLocation())); - } + SetType found = (SetType) unify(new SetType(new UntypedType()), expected, n); TLAType current = found.getSubType(); for (int i = 0; i < n.getArgs().length; i++) { current = visitExprOrOpArgNode(n.getArgs()[i], current); @@ -421,43 +400,27 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo case OPCODE_in: // \in case OPCODE_notin: // \notin { - if (!BoolType.getInstance().compare(expected)) { - throw new TypeErrorException(String.format("Expected %s, found BOOL at '%s',%n%s", expected, - n.getOperator().getName(), n.getLocation())); - } + TLAType boolType = unify(BoolType.getInstance(), expected, n); TLAType element = visitExprOrOpArgNode(n.getArgs()[0], new UntypedType()); visitExprOrOpArgNode(n.getArgs()[1], new SetType(element)); - - return BoolType.getInstance(); + return boolType; } case OPCODE_setdiff: // set difference case OPCODE_cup: // set union case OPCODE_cap: // set intersection { - SetType found = new SetType(new UntypedType()); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected %s, found POW(_A) at '%s',%n%s", expected, - n.getOperator().getName(), n.getLocation())); - } + TLAType found = unify(new SetType(new UntypedType()), expected, n); TLAType left = visitExprOrOpArgNode(n.getArgs()[0], found); - TLAType right = visitExprOrOpArgNode(n.getArgs()[1], left); - return right; + return visitExprOrOpArgNode(n.getArgs()[1], left); // right } case OPCODE_subseteq: // \subseteq - subset or equal { - try { - BoolType.getInstance().unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected %s, found BOOL at '%s',%n%s", expected, - n.getOperator().getName(), n.getLocation())); - } + TLAType boolType = unify(BoolType.getInstance(), expected, n); TLAType left = visitExprOrOpArgNode(n.getArgs()[0], new SetType(new UntypedType())); visitExprOrOpArgNode(n.getArgs()[1], left); - return BoolType.getInstance(); + return boolType; } /* @@ -466,27 +429,14 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo case OPCODE_sso: // $SubsetOf Represents {x \in S : P} { - TLAType domainType = evalBoundedVariables(n); - SetType found = new SetType(domainType); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected %s, found %s at '%s',%n%s", expected, found, - n.getOperator().getName(), n.getLocation())); - } + SetType found = (SetType) unify(new SetType(evalBoundedVariables(n)), expected, n); visitExprOrOpArgNode(n.getArgs()[0], BoolType.getInstance()); return found; } case OPCODE_soa: // $SetOfAll Represents {e : p1 \in S, p2,p3 \in S2} { - SetType found = new SetType(new UntypedType()); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected %s, found POW(_A) at '%s',%n%s", expected, - n.getOperator().getName(), n.getLocation())); - } + SetType found = (SetType) unify(new SetType(new UntypedType()), expected, n); evalBoundedVariables(n); visitExprOrOpArgNode(n.getArgs()[0], found.getSubType()); return found; @@ -494,26 +444,14 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo case OPCODE_subset: // SUBSET (conforms POW in B) { - SetType found = new SetType(new UntypedType()); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException( - String.format("Expected %s, found POW(_A) at 'SUBSET',%n%s", expected, n.getLocation())); - } + SetType found = (SetType) unify(new SetType(new UntypedType()), expected, n); visitExprOrOpArgNode(n.getArgs()[0], found.getSubType()); return found; } case OPCODE_union: // Union - Union{{1},{2}} { - SetType found = new SetType(new UntypedType()); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException( - String.format("Expected %s, found POW(_A) at 'SUBSET',%n%s", expected, n.getLocation())); - } + TLAType found = unify(new SetType(new UntypedType()), expected, n); SetType setOfSet = (SetType) visitExprOrOpArgNode(n.getArgs()[0], new SetType(found)); return setOfSet.getSubType(); } @@ -553,18 +491,8 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo found = TupleOrFunction.createTupleOrFunctionType(list); // found = new TupleType(list); } - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException( - String.format("Expected %s, found %s at Tuple,%n%s", expected, found, n.getLocation())); - } - n.setToolObject(TYPE_ID, found); tupleNodeList.add(n); - if (found instanceof AbstractHasFollowers) { - ((AbstractHasFollowers) found).addFollower(n); - } - return found; + return unifyAndSetTypeWithFollowers(found, expected, "tuple", n); } /* @@ -576,29 +504,14 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo FormalParamNode recFunc = n.getUnbdedQuantSymbols()[0]; symbolNodeList.add(recFunc); - FunctionType recType = new FunctionType(); - recFunc.setToolObject(TYPE_ID, recType); - recType.addFollower(recFunc); + setTypeAndFollowers(recFunc, new FunctionType()); TLAType domainType = evalBoundedVariables(n); FunctionType found = new FunctionType(domainType, new UntypedType()); visitExprOrOpArgNode(n.getArgs()[0], found.getRange()); - try { - found = (FunctionType) found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException("Expected '" + expected + "', found '" + found + "'.\n" + n.getLocation()); - } - - TLAType t = null; - try { - t = (TLAType) recFunc.getToolObject(TYPE_ID); - found = (FunctionType) found.unify(t); - } catch (UnificationException e) { - throw new TypeErrorException("Expected '" + expected + "', found '" + t + "'.\n" + n.getLocation()); - } - - return found; + found = (FunctionType) unify(found, expected, n); + return unify(found, getType(recFunc), n); } case OPCODE_nrfs: // succ[n \in Nat] == n + 1 @@ -607,13 +520,7 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo TLAType domainType = evalBoundedVariables(n); FunctionType found = new FunctionType(domainType, new UntypedType()); visitExprOrOpArgNode(n.getArgs()[0], found.getRange()); - - try { - found = (FunctionType) found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException("Expected '" + expected + "', found '" + found + "'.\n" + n.getLocation()); - } - return found; + return unify(found, expected, n); } /* @@ -623,50 +530,25 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo { TLAType domType; ExprOrOpArgNode dom = n.getArgs()[1]; - if (dom instanceof OpApplNode && ((OpApplNode) dom).getOperator().getName().toString().equals("$Tuple")) { - ArrayList<TLAType> domList = new ArrayList<>(); - OpApplNode domOpAppl = (OpApplNode) dom; - for (int i = 0; i < domOpAppl.getArgs().length; i++) { - TLAType d = visitExprOrOpArgNode(domOpAppl.getArgs()[i], new UntypedType()); - domList.add(d); - } - - if (domList.size() == 1) { // one-tuple - domType = new FunctionType(IntType.getInstance(), domList.get(0)); - FunctionType func = new FunctionType(domType, expected); - TLAType res = visitExprOrOpArgNode(n.getArgs()[0], func); - return ((FunctionType) res).getRange(); - } else { - domType = new TupleType(domList); - FunctionType func = new FunctionType(domType, expected); - TLAType res = visitExprOrOpArgNode(n.getArgs()[0], func); - return ((FunctionType) res).getRange(); + if (dom instanceof OpApplNode && ((OpApplNode) dom).getOperator().getName().equals("$Tuple")) { + List<TLAType> domList = new ArrayList<>(); + for (ExprOrOpArgNode arg : ((OpApplNode) dom).getArgs()) { + domList.add(visitExprOrOpArgNode(arg, new UntypedType())); } + domType = domList.size() == 1 + ? new FunctionType(IntType.getInstance(), domList.get(0)) // one-tuple + : new TupleType(domList); + } else if (dom instanceof NumeralNode) { + NumeralNode num = (NumeralNode) dom; + UntypedType u = new UntypedType(); + setTypeAndFollowers(n, u); + + TLAType res = visitExprOrOpArgNode(n.getArgs()[0], new TupleOrFunction(num.val(), u)); + setTypeAndFollowers(n.getArgs()[0], res); + tupleNodeList.add(n.getArgs()[0]); + return unify(getType(n), expected, n.getArgs()[0].toString(), n); } else { - ExprOrOpArgNode arg = n.getArgs()[1]; - if (arg instanceof NumeralNode) { - NumeralNode num = (NumeralNode) arg; - UntypedType u = new UntypedType(); - n.setToolObject(TYPE_ID, u); - u.addFollower(n); - TupleOrFunction tupleOrFunc = new TupleOrFunction(num.val(), u); - - TLAType res = visitExprOrOpArgNode(n.getArgs()[0], tupleOrFunc); - n.getArgs()[0].setToolObject(TYPE_ID, res); - tupleNodeList.add(n.getArgs()[0]); - if (res instanceof AbstractHasFollowers) { - ((AbstractHasFollowers) res).addFollower(n.getArgs()[0]); - } - TLAType found = (TLAType) n.getToolObject(TYPE_ID); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException("Expected '" + expected + "', found '" + found + "'.\n" - + n.getArgs()[0].toString(2) + "\n" + n.getLocation()); - } - return found; - } - domType = visitExprOrOpArgNode(n.getArgs()[1], new UntypedType()); + domType = visitExprOrOpArgNode(dom, new UntypedType()); } FunctionType func = new FunctionType(domType, expected); TLAType res = visitExprOrOpArgNode(n.getArgs()[0], func); @@ -681,14 +563,7 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo FunctionType func = new FunctionType(new UntypedType(), new UntypedType()); func = (FunctionType) visitExprOrOpArgNode(n.getArgs()[0], func); - TLAType res; - try { - res = new SetType(func.getDomain()).unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected '%s', found '%s' at 'DOMAIN(..)',%n%s", expected, - func, n.getLocation())); - } - return res; + return unify(new SetType(func.getDomain()), expected, n); } /* * Set of Function @@ -698,13 +573,8 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo SetType A = (SetType) visitExprOrOpArgNode(n.getArgs()[0], new SetType(new UntypedType())); SetType B = (SetType) visitExprOrOpArgNode(n.getArgs()[1], new SetType(new UntypedType())); - SetType found = new SetType(new FunctionType(A.getSubType(), B.getSubType())); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected '%s', found '%s' at Set of Function,%n%s", - expected, found, n.getLocation())); - } + TLAType found = new SetType(new FunctionType(A.getSubType(), B.getSubType())); + found = unify(found, expected, "set of functions", n); return found; } @@ -726,14 +596,8 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo SetType t = (SetType) visitExprOrOpArgNode(n.getArgs()[i], new SetType(new UntypedType())); list.add(t.getSubType()); } - SetType found = new SetType(new TupleType(list)); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected %s, found %s at Cartesian Product,%n%s", expected, - found, n.getLocation())); - } - + TLAType found = new SetType(new TupleType(list)); + found = unify(found, expected, "cartesian product", n); return found; } @@ -750,16 +614,7 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo struct.add(field.getRep().toString(), fieldType.getSubType()); } - SetType found = new SetType(struct); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException(String.format("Expected %s, found %s at Set of Records,%n%s", expected, - found, n.getLocation())); - } - n.setToolObject(TYPE_ID, found); - found.addFollower(n); - return found; + return unifyAndSetTypeWithFollowers(new SetType(struct), expected, "set of records", n); } case OPCODE_rc: // [h_1 |-> 1, h_2 |-> 2] @@ -771,17 +626,7 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo TLAType fieldType = visitExprOrOpArgNode(pair.getArgs()[1], new UntypedType()); found.add(field.getRep().toString(), fieldType); } - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException( - String.format("Expected %s, found %s at Record,%n%s", expected, found, n.getLocation())); - } - n.setToolObject(TYPE_ID, found); - found.addFollower(n); - - return found; - + return unifyAndSetTypeWithFollowers(found, expected, "record constructor", n); } case OPCODE_rs: // $RcdSelect r.c @@ -798,8 +643,7 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo throw new TypeErrorException(String.format("Struct has no field %s with type %s: %s%n%s", fieldName, r.getType(fieldName), r, n.getLocation())); } - n.getArgs()[0].setToolObject(TYPE_ID, r); - r.addFollower(n.getArgs()[0]); + setTypeAndFollowers(n.getArgs()[0], r); return r.getType(fieldName); } @@ -811,10 +655,7 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo visitExprOrOpArgNode(n.getArgs()[0], BoolType.getInstance()); TLAType then = visitExprOrOpArgNode(n.getArgs()[1], expected); TLAType eelse = visitExprOrOpArgNode(n.getArgs()[2], then); - n.setToolObject(TYPE_ID, eelse); - if (eelse instanceof AbstractHasFollowers) { - ((AbstractHasFollowers) eelse).addFollower(n); - } + setTypeAndFollowers(n, eelse); return eelse; } @@ -858,30 +699,25 @@ public class TypeChecker extends BuiltInOPs implements BBuildIns, TranslationGlo case OPCODE_bc: { // CHOOSE x \in S: P TLAType found = evalBoundedVariables(n); - try { - found = found.unify(expected); - } catch (UnificationException e) { - throw new TypeErrorException( - String.format("Expected %s, found %s at 'CHOOSE',%n%s", expected, found, n.getLocation())); - } + found = unify(found, expected, n); visitExprOrOpArgNode(n.getArgs()[0], BoolType.getInstance()); return found; } - case OPCODE_unchanged: { + case OPCODE_unchanged: return BoolType.getInstance().unify(expected); } /* * no TLA+ Built-ins */ - case 0: { + case 0: return evalBBuiltIns(n, expected); - } - } - throw new NotImplementedException( - "Not supported Operator: " + n.getOperator().getName() + "\n" + n.getLocation()); + default: + throw new NotImplementedException( + "Not supported Operator: " + n.getOperator().getName() + "\n" + n.getLocation()); + } } private TLAType evalBoundedVariables(OpApplNode n) throws TLA2BException {