lang: unification: Don't stall the solver over generators
If we have a solution, and all that remains are generators, then feel free to remove them and win.
This commit is contained in:
@@ -641,7 +641,18 @@ func (obj *EqualityWrapCallInvariant) Possible(partials []Invariant) error {
|
|||||||
// add-in partial progress, you could have it generate a list of invariants and
|
// add-in partial progress, you could have it generate a list of invariants and
|
||||||
// include a new generator invariant in this list. Be sure to only do this if
|
// include a new generator invariant in this list. Be sure to only do this if
|
||||||
// you are making progress on each invocation, and make sure to avoid infinite
|
// you are making progress on each invocation, and make sure to avoid infinite
|
||||||
// looping which isn't something we can currently detect or prevent.
|
// looping which isn't something we can currently detect or prevent. One special
|
||||||
|
// bit about generators and returning a partial: you must always return the
|
||||||
|
// minimum set of expressions that need to be solved in the first Unify() call
|
||||||
|
// that also returns the very first generator. This is because you must not rely
|
||||||
|
// on the generator to tell the solver about new expressions that it *also*
|
||||||
|
// wants solved. This is because after the initial (pre-generator-running)
|
||||||
|
// collection of the invariants, we need to be able to build a list of all the
|
||||||
|
// expressions that need to be solved for us to consider the problem "done". If
|
||||||
|
// a new expression only appeared after we ran a generator, then this would
|
||||||
|
// require our solver be far more complicated than it needs to be and currently
|
||||||
|
// is. Besides, there's no reason (that I know of at the moment) that needs this
|
||||||
|
// sort of invariant that only appears after the solver is running.
|
||||||
//
|
//
|
||||||
// NOTE: We might *consider* an optimization where we return a different kind of
|
// NOTE: We might *consider* an optimization where we return a different kind of
|
||||||
// error that represents a response of "impossible". This would mean that there
|
// error that represents a response of "impossible". This would mean that there
|
||||||
|
|||||||
1
lang/interpret_test/TestAstFunc2/printfsimple0.output
Normal file
1
lang/interpret_test/TestAstFunc2/printfsimple0.output
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Vertex: test[the answer is 42]
|
||||||
5
lang/interpret_test/TestAstFunc2/printfsimple0/main.mcl
Normal file
5
lang/interpret_test/TestAstFunc2/printfsimple0/main.mcl
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import "fmt"
|
||||||
|
|
||||||
|
$out = 42
|
||||||
|
|
||||||
|
test fmt.printf("the answer is %d", $out) {}
|
||||||
@@ -741,7 +741,28 @@ Loop:
|
|||||||
}
|
}
|
||||||
used = append(used, i) // mark equality as used up
|
used = append(used, i) // mark equality as used up
|
||||||
}
|
}
|
||||||
logf("%s: got %d equalities left after %d used up", Name, len(equalities)-len(used), len(used))
|
logf("%s: got %d equalities left after %d value invariants used up", Name, len(equalities)-len(used), len(used))
|
||||||
|
// delete used equalities, in reverse order to preserve indexing!
|
||||||
|
for i := len(used) - 1; i >= 0; i-- {
|
||||||
|
ix := used[i] // delete index that was marked as used!
|
||||||
|
equalities = append(equalities[:ix], equalities[ix+1:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(used) > 0 {
|
||||||
|
continue Loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(exclusives) == 0 && isSolved { // old generators
|
||||||
|
used := []int{}
|
||||||
|
for i, x := range equalities {
|
||||||
|
_, ok := x.(*interfaces.GeneratorInvariant)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
used = append(used, i) // mark equality as used up
|
||||||
|
}
|
||||||
|
logf("%s: got %d equalities left after %d generators used up", Name, len(equalities)-len(used), len(used))
|
||||||
// delete used equalities, in reverse order to preserve indexing!
|
// delete used equalities, in reverse order to preserve indexing!
|
||||||
for i := len(used) - 1; i >= 0; i-- {
|
for i := len(used) - 1; i >= 0; i-- {
|
||||||
ix := used[i] // delete index that was marked as used!
|
ix := used[i] // delete index that was marked as used!
|
||||||
@@ -861,10 +882,11 @@ Loop:
|
|||||||
|
|
||||||
// TODO: print ambiguity
|
// TODO: print ambiguity
|
||||||
logf("%s: ================ ambiguity ================", Name)
|
logf("%s: ================ ambiguity ================", Name)
|
||||||
|
unsolved, isSolved := isSolvedFn(solved)
|
||||||
|
logf("%s: isSolved: %+v", Name, isSolved)
|
||||||
for _, x := range equalities {
|
for _, x := range equalities {
|
||||||
logf("%s: unsolved equality: %+v", Name, x)
|
logf("%s: unsolved equality: %+v", Name, x)
|
||||||
}
|
}
|
||||||
unsolved, _ := isSolvedFn(solved)
|
|
||||||
for x := range unsolved {
|
for x := range unsolved {
|
||||||
logf("%s: unsolved expected: %+v", Name, x)
|
logf("%s: unsolved expected: %+v", Name, x)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user