diff --git a/lang/interfaces/unification.go b/lang/interfaces/unification.go index b514c643..43d10ab3 100644 --- a/lang/interfaces/unification.go +++ b/lang/interfaces/unification.go @@ -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 // 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 -// 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 // error that represents a response of "impossible". This would mean that there diff --git a/lang/interpret_test/TestAstFunc2/printfsimple0.output b/lang/interpret_test/TestAstFunc2/printfsimple0.output new file mode 100644 index 00000000..b7747cff --- /dev/null +++ b/lang/interpret_test/TestAstFunc2/printfsimple0.output @@ -0,0 +1 @@ +Vertex: test[the answer is 42] diff --git a/lang/interpret_test/TestAstFunc2/printfsimple0/main.mcl b/lang/interpret_test/TestAstFunc2/printfsimple0/main.mcl new file mode 100644 index 00000000..1f3d6a98 --- /dev/null +++ b/lang/interpret_test/TestAstFunc2/printfsimple0/main.mcl @@ -0,0 +1,5 @@ +import "fmt" + +$out = 42 + +test fmt.printf("the answer is %d", $out) {} diff --git a/lang/unification/simplesolver.go b/lang/unification/simplesolver.go index 3cfed028..9a291b84 100644 --- a/lang/unification/simplesolver.go +++ b/lang/unification/simplesolver.go @@ -741,7 +741,28 @@ Loop: } 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! for i := len(used) - 1; i >= 0; i-- { ix := used[i] // delete index that was marked as used! @@ -861,10 +882,11 @@ Loop: // TODO: print ambiguity logf("%s: ================ ambiguity ================", Name) + unsolved, isSolved := isSolvedFn(solved) + logf("%s: isSolved: %+v", Name, isSolved) for _, x := range equalities { logf("%s: unsolved equality: %+v", Name, x) } - unsolved, _ := isSolvedFn(solved) for x := range unsolved { logf("%s: unsolved expected: %+v", Name, x) }