lang: ast: Optimize unification invariants for common case
This optimizes the list of type unification invariants that we generate for the common case where a resource or edge name is known statically. For one code base this halved the type unification time in half. More work can be done though!
This commit is contained in:
@@ -561,32 +561,6 @@ func (obj *StmtRes) SetScope(scope *interfaces.Scope) error {
|
|||||||
func (obj *StmtRes) Unify() ([]interfaces.Invariant, error) {
|
func (obj *StmtRes) Unify() ([]interfaces.Invariant, error) {
|
||||||
var invariants []interfaces.Invariant
|
var invariants []interfaces.Invariant
|
||||||
|
|
||||||
invars, err := obj.Name.Unify()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
invariants = append(invariants, invars...)
|
|
||||||
|
|
||||||
// name must be a string or a list
|
|
||||||
ors := []interfaces.Invariant{}
|
|
||||||
|
|
||||||
invarStr := &interfaces.EqualsInvariant{
|
|
||||||
Expr: obj.Name,
|
|
||||||
Type: types.TypeStr,
|
|
||||||
}
|
|
||||||
ors = append(ors, invarStr)
|
|
||||||
|
|
||||||
invarListStr := &interfaces.EqualsInvariant{
|
|
||||||
Expr: obj.Name,
|
|
||||||
Type: types.NewType("[]str"),
|
|
||||||
}
|
|
||||||
ors = append(ors, invarListStr)
|
|
||||||
|
|
||||||
invar := &interfaces.ExclusiveInvariant{
|
|
||||||
Invariants: ors, // one and only one of these should be true
|
|
||||||
}
|
|
||||||
invariants = append(invariants, invar)
|
|
||||||
|
|
||||||
// collect all the invariants of each field and edge
|
// collect all the invariants of each field and edge
|
||||||
for _, x := range obj.Contents {
|
for _, x := range obj.Contents {
|
||||||
invars, err := x.Unify(obj.Kind) // pass in the resource kind
|
invars, err := x.Unify(obj.Kind) // pass in the resource kind
|
||||||
@@ -596,6 +570,47 @@ func (obj *StmtRes) Unify() ([]interfaces.Invariant, error) {
|
|||||||
invariants = append(invariants, invars...)
|
invariants = append(invariants, invars...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
invars, err := obj.Name.Unify()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
invariants = append(invariants, invars...)
|
||||||
|
|
||||||
|
invarStr := &interfaces.EqualsInvariant{
|
||||||
|
Expr: obj.Name,
|
||||||
|
Type: types.TypeStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimization: If we know it's an str, no need for exclusives!
|
||||||
|
if _, ok := obj.Name.(*ExprStr); ok {
|
||||||
|
invariants = append(invariants, invarStr)
|
||||||
|
return invariants, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
invarListStr := &interfaces.EqualsInvariant{
|
||||||
|
Expr: obj.Name,
|
||||||
|
Type: types.NewType("[]str"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimization: If we know it's a []str, no need for exclusives!
|
||||||
|
if expr, ok := obj.Name.(*ExprList); ok {
|
||||||
|
typ, err := expr.Type()
|
||||||
|
if err == nil && typ.Cmp(types.NewType("[]str")) == nil {
|
||||||
|
invariants = append(invariants, invarListStr)
|
||||||
|
return invariants, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// name must be a string or a list
|
||||||
|
ors := []interfaces.Invariant{}
|
||||||
|
ors = append(ors, invarStr)
|
||||||
|
ors = append(ors, invarListStr)
|
||||||
|
|
||||||
|
invar := &interfaces.ExclusiveInvariant{
|
||||||
|
Invariants: ors, // one and only one of these should be true
|
||||||
|
}
|
||||||
|
invariants = append(invariants, invar)
|
||||||
|
|
||||||
return invariants, nil
|
return invariants, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2473,19 +2488,34 @@ func (obj *StmtEdgeHalf) Unify() ([]interfaces.Invariant, error) {
|
|||||||
}
|
}
|
||||||
invariants = append(invariants, invars...)
|
invariants = append(invariants, invars...)
|
||||||
|
|
||||||
// name must be a string or a list
|
|
||||||
ors := []interfaces.Invariant{}
|
|
||||||
|
|
||||||
invarStr := &interfaces.EqualsInvariant{
|
invarStr := &interfaces.EqualsInvariant{
|
||||||
Expr: obj.Name,
|
Expr: obj.Name,
|
||||||
Type: types.TypeStr,
|
Type: types.TypeStr,
|
||||||
}
|
}
|
||||||
ors = append(ors, invarStr)
|
|
||||||
|
// Optimization: If we know it's an str, no need for exclusives!
|
||||||
|
if _, ok := obj.Name.(*ExprStr); ok {
|
||||||
|
invariants = append(invariants, invarStr)
|
||||||
|
return invariants, nil
|
||||||
|
}
|
||||||
|
|
||||||
invarListStr := &interfaces.EqualsInvariant{
|
invarListStr := &interfaces.EqualsInvariant{
|
||||||
Expr: obj.Name,
|
Expr: obj.Name,
|
||||||
Type: types.NewType("[]str"),
|
Type: types.NewType("[]str"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optimization: If we know it's a []str, no need for exclusives!
|
||||||
|
if expr, ok := obj.Name.(*ExprList); ok {
|
||||||
|
typ, err := expr.Type()
|
||||||
|
if err == nil && typ.Cmp(types.NewType("[]str")) == nil {
|
||||||
|
invariants = append(invariants, invarListStr)
|
||||||
|
return invariants, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// name must be a string or a list
|
||||||
|
ors := []interfaces.Invariant{}
|
||||||
|
ors = append(ors, invarStr)
|
||||||
ors = append(ors, invarListStr)
|
ors = append(ors, invarListStr)
|
||||||
|
|
||||||
invar := &interfaces.ExclusiveInvariant{
|
invar := &interfaces.ExclusiveInvariant{
|
||||||
|
|||||||
Reference in New Issue
Block a user