416 * Check bounds and perform incorporation |
416 * Check bounds and perform incorporation |
417 */ |
417 */ |
418 void checkWithinBounds(InferenceContext inferenceContext, |
418 void checkWithinBounds(InferenceContext inferenceContext, |
419 Warner warn) throws InferenceException { |
419 Warner warn) throws InferenceException { |
420 MultiUndetVarListener mlistener = new MultiUndetVarListener(inferenceContext.undetvars); |
420 MultiUndetVarListener mlistener = new MultiUndetVarListener(inferenceContext.undetvars); |
|
421 List<Type> saved_undet = inferenceContext.save(); |
421 try { |
422 try { |
422 while (true) { |
423 while (true) { |
423 mlistener.reset(); |
424 mlistener.reset(); |
424 if (!allowGraphInference) { |
425 if (!allowGraphInference) { |
425 //in legacy mode we lack of transitivity, so bound check |
426 //in legacy mode we lack of transitivity, so bound check |
643 for (Type b : uv.getBounds(InferenceBound.UPPER)) { |
647 for (Type b : uv.getBounds(InferenceBound.UPPER)) { |
644 if (inferenceContext.inferenceVars().contains(b)) { |
648 if (inferenceContext.inferenceVars().contains(b)) { |
645 UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); |
649 UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); |
646 //alpha <: beta |
650 //alpha <: beta |
647 //0. set beta :> alpha |
651 //0. set beta :> alpha |
648 uv2.addBound(InferenceBound.LOWER, uv.qtype, infer.types); |
652 uv2.addBound(InferenceBound.LOWER, uv, infer.types); |
649 //1. copy alpha's lower to beta's |
653 //1. copy alpha's lower to beta's |
650 for (Type l : uv.getBounds(InferenceBound.LOWER)) { |
654 for (Type l : uv.getBounds(InferenceBound.LOWER)) { |
651 uv2.addBound(InferenceBound.LOWER, inferenceContext.asInstType(l), infer.types); |
655 uv2.addBound(InferenceBound.LOWER, inferenceContext.asInstType(l), infer.types); |
652 } |
656 } |
653 //2. copy beta's upper to alpha's |
657 //2. copy beta's upper to alpha's |
668 for (Type b : uv.getBounds(InferenceBound.LOWER)) { |
672 for (Type b : uv.getBounds(InferenceBound.LOWER)) { |
669 if (inferenceContext.inferenceVars().contains(b)) { |
673 if (inferenceContext.inferenceVars().contains(b)) { |
670 UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); |
674 UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); |
671 //alpha :> beta |
675 //alpha :> beta |
672 //0. set beta <: alpha |
676 //0. set beta <: alpha |
673 uv2.addBound(InferenceBound.UPPER, uv.qtype, infer.types); |
677 uv2.addBound(InferenceBound.UPPER, uv, infer.types); |
674 //1. copy alpha's upper to beta's |
678 //1. copy alpha's upper to beta's |
675 for (Type u : uv.getBounds(InferenceBound.UPPER)) { |
679 for (Type u : uv.getBounds(InferenceBound.UPPER)) { |
676 uv2.addBound(InferenceBound.UPPER, inferenceContext.asInstType(u), infer.types); |
680 uv2.addBound(InferenceBound.UPPER, inferenceContext.asInstType(u), infer.types); |
677 } |
681 } |
678 //2. copy beta's lower to alpha's |
682 //2. copy beta's lower to alpha's |
693 for (Type b : uv.getBounds(InferenceBound.EQ)) { |
697 for (Type b : uv.getBounds(InferenceBound.EQ)) { |
694 if (inferenceContext.inferenceVars().contains(b)) { |
698 if (inferenceContext.inferenceVars().contains(b)) { |
695 UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); |
699 UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); |
696 //alpha == beta |
700 //alpha == beta |
697 //0. set beta == alpha |
701 //0. set beta == alpha |
698 uv2.addBound(InferenceBound.EQ, uv.qtype, infer.types); |
702 uv2.addBound(InferenceBound.EQ, uv, infer.types); |
699 //1. copy all alpha's bounds to beta's |
703 //1. copy all alpha's bounds to beta's |
700 for (InferenceBound ib : InferenceBound.values()) { |
704 for (InferenceBound ib : InferenceBound.values()) { |
701 for (Type b2 : uv.getBounds(ib)) { |
705 for (Type b2 : uv.getBounds(ib)) { |
702 if (b2 != uv2) { |
706 if (b2 != uv2) { |
703 uv2.addBound(ib, inferenceContext.asInstType(b2), infer.types); |
707 uv2.addBound(ib, inferenceContext.asInstType(b2), infer.types); |
1088 checkWithinBounds(inferenceContext, warn); //initial propagation of bounds |
1092 checkWithinBounds(inferenceContext, warn); //initial propagation of bounds |
1089 InferenceGraph inferenceGraph = new InferenceGraph(); |
1093 InferenceGraph inferenceGraph = new InferenceGraph(); |
1090 while (!sstrategy.done()) { |
1094 while (!sstrategy.done()) { |
1091 InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph); |
1095 InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph); |
1092 List<Type> varsToSolve = List.from(nodeToSolve.data); |
1096 List<Type> varsToSolve = List.from(nodeToSolve.data); |
1093 inferenceContext.save(); |
1097 List<Type> saved_undet = inferenceContext.save(); |
1094 try { |
1098 try { |
1095 //repeat until all variables are solved |
1099 //repeat until all variables are solved |
1096 outer: while (Type.containsAny(inferenceContext.restvars(), varsToSolve)) { |
1100 outer: while (Type.containsAny(inferenceContext.restvars(), varsToSolve)) { |
1097 //for each inference phase |
1101 //for each inference phase |
1098 for (GraphInferenceSteps step : GraphInferenceSteps.values()) { |
1102 for (GraphInferenceSteps step : GraphInferenceSteps.values()) { |
1105 throw inferenceException.setMessage(); |
1109 throw inferenceException.setMessage(); |
1106 } |
1110 } |
1107 } |
1111 } |
1108 catch (InferenceException ex) { |
1112 catch (InferenceException ex) { |
1109 //did we fail because of interdependent ivars? |
1113 //did we fail because of interdependent ivars? |
1110 inferenceContext.rollback(); |
1114 inferenceContext.rollback(saved_undet); |
1111 instantiateAsUninferredVars(varsToSolve, inferenceContext); |
1115 instantiateAsUninferredVars(varsToSolve, inferenceContext); |
1112 checkWithinBounds(inferenceContext, warn); |
1116 checkWithinBounds(inferenceContext, warn); |
1113 } |
1117 } |
1114 inferenceGraph.deleteNode(nodeToSolve); |
1118 inferenceGraph.deleteNode(nodeToSolve); |
1115 } |
1119 } |
1500 } |
1504 } |
1501 |
1505 |
1502 /** |
1506 /** |
1503 * Save the state of this inference context |
1507 * Save the state of this inference context |
1504 */ |
1508 */ |
1505 void save() { |
1509 List<Type> save() { |
1506 ListBuffer<Type> buf = ListBuffer.lb(); |
1510 ListBuffer<Type> buf = ListBuffer.lb(); |
1507 for (Type t : undetvars) { |
1511 for (Type t : undetvars) { |
1508 UndetVar uv = (UndetVar)t; |
1512 UndetVar uv = (UndetVar)t; |
1509 UndetVar uv2 = new UndetVar((TypeVar)uv.qtype, types); |
1513 UndetVar uv2 = new UndetVar((TypeVar)uv.qtype, types); |
1510 for (InferenceBound ib : InferenceBound.values()) { |
1514 for (InferenceBound ib : InferenceBound.values()) { |
1513 } |
1517 } |
1514 } |
1518 } |
1515 uv2.inst = uv.inst; |
1519 uv2.inst = uv.inst; |
1516 buf.add(uv2); |
1520 buf.add(uv2); |
1517 } |
1521 } |
1518 saved_undet = buf.toList(); |
1522 return buf.toList(); |
1519 } |
1523 } |
1520 |
1524 |
1521 /** |
1525 /** |
1522 * Restore the state of this inference context to the previous known checkpoint |
1526 * Restore the state of this inference context to the previous known checkpoint |
1523 */ |
1527 */ |
1524 void rollback() { |
1528 void rollback(List<Type> saved_undet) { |
1525 Assert.check(saved_undet != null && saved_undet.length() == undetvars.length()); |
1529 Assert.check(saved_undet != null && saved_undet.length() == undetvars.length()); |
1526 undetvars = saved_undet; |
1530 //restore bounds (note: we need to preserve the old instances) |
1527 saved_undet = null; |
1531 for (Type t : undetvars) { |
|
1532 UndetVar uv = (UndetVar)t; |
|
1533 UndetVar uv_saved = (UndetVar)saved_undet.head; |
|
1534 for (InferenceBound ib : InferenceBound.values()) { |
|
1535 uv.setBounds(ib, uv_saved.getBounds(ib)); |
|
1536 } |
|
1537 uv.inst = uv_saved.inst; |
|
1538 saved_undet = saved_undet.tail; |
|
1539 } |
1528 } |
1540 } |
1529 |
1541 |
1530 /** |
1542 /** |
1531 * Copy variable in this inference context to the given context |
1543 * Copy variable in this inference context to the given context |
1532 */ |
1544 */ |