lang: unification, interfaces: Add a skip invariant

This is a cleaner way of telling the type unifier that we don't want
this particular expression in the solution set at the end.
This commit is contained in:
James Shubin
2023-12-17 21:41:20 -05:00
parent c2bf4ef7d4
commit 7cc231e8b9
3 changed files with 63 additions and 0 deletions

View File

@@ -170,6 +170,9 @@ func DebugSolverState(solved map[interfaces.Expr]*types.Type, equalities []inter
case *interfaces.AnyInvariant:
// skip, not used in the examples I care about
case *interfaces.SkipInvariant:
// we don't care about this one
default:
s += fmt.Sprintf("%v\n", equality)
}
@@ -249,6 +252,10 @@ func SimpleInvariantSolver(invariants []interfaces.Invariant, expected []interfa
case *interfaces.CallFuncArgsValueInvariant:
equalities = append(equalities, invariant)
case *interfaces.SkipInvariant:
// drop it for now
//equalities = append(equalities, invariant)
default:
return nil, nil, fmt.Errorf("unknown invariant type: %T", x)
}
@@ -296,6 +303,8 @@ func SimpleInvariantSolver(invariants []interfaces.Invariant, expected []interfa
return nil, err
}
//skipExprs := make(map[interfaces.Expr]struct{})
// XXX: if these partials all shared the same variable definition, would
// it all work??? Maybe we don't even need the first map prefix...
listPartials := make(map[interfaces.Expr]map[interfaces.Expr]*types.Type)
@@ -1074,6 +1083,11 @@ Loop:
// a generator invariant wants to read them...
continue
case *interfaces.SkipInvariant:
//skipExprs[eq.Expr] = struct{}{} // save
used = append(used, eqi) // mark equality as used up
continue
default:
return nil, fmt.Errorf("unknown invariant type: %T", eqx)
}
@@ -1334,6 +1348,12 @@ Loop:
solutions := []*interfaces.EqualsInvariant{}
// FIXME: can we do this loop in a deterministic, sorted way?
for expr, typ := range solved {
// Don't do this here, or the current Unifier struct machinery
// will see it as a bug. Do it there until we change the API.
//if _, exists := skipExprs[expr]; exists {
// continue
//}
invar := &interfaces.EqualsInvariant{
Expr: expr,
Type: typ,

View File

@@ -72,7 +72,13 @@ func (obj *Unifier) Unify() error {
// build a list of what we think we need to solve for to succeed
exprs := []interfaces.Expr{}
skips := make(map[interfaces.Expr]struct{})
for _, x := range invariants {
if si, ok := x.(*interfaces.SkipInvariant); ok {
skips[si.Expr] = struct{}{}
continue
}
exprs = append(exprs, x.ExprList()...)
}
exprMap := ExprListToExprMap(exprs) // makes searching faster
@@ -137,6 +143,10 @@ func (obj *Unifier) Unify() error {
// programming error ?
return fmt.Errorf("unexpected invalid solution at: %p", x)
}
if _, exists := skips[x.Expr]; exists {
continue
}
if obj.Debug {
obj.Logf("solution: %p => %+v\t(%+v)", x.Expr, x.Type, x.Expr.String())
}