diff --git a/topdown/eval.go b/topdown/eval.go index 9d91eca9ff..c5ec5f22c6 100644 --- a/topdown/eval.go +++ b/topdown/eval.go @@ -2491,73 +2491,6 @@ func (e evalVirtualPartial) evalAllRulesNoCache(rules []*ast.Rule) (*ast.Term, e return result, nil } -// FIXME: unused; remove -func (e evalVirtualPartial) evalOneRulePreUnify(iter unifyIterator, rule *ast.Rule, hint evalVirtualPartialCacheHint, result *ast.Term, unknown bool) error { - - key := e.ref[e.pos+1] - child := e.e.child(rule.Body) - - child.traceEnter(rule) - var defined bool - - headKey := rule.Head.Key - if headKey == nil { - headKey = rule.Head.Reference[len(rule.Head.Reference)-1] - } - err := child.biunify(headKey, key, child.bindings, e.bindings, func() error { - defined = true - return child.eval(func(child *eval) error { - - term := rule.Head.Value - if term == nil { - term = headKey - } - - if hint.key != nil { - result := child.bindings.Plug(term) - e.e.virtualCache.Put(hint.key, result) - } - - // NOTE(tsandall): if the rule set depends on any unknowns then do - // not perform the duplicate check because evaluation of the ruleset - // may not produce a definitive result. This is a bit strict--we - // could improve by skipping only when saves occur. - if !unknown { - var dup bool - var err error - result, dup, err = e.reduce(rule, child.bindings, result) - if err != nil { - return err - } else if dup { - child.traceDuplicate(rule) - return nil - } - } - - child.traceExit(rule) - term, termbindings := child.bindings.apply(term) - err := e.evalTerm(iter, e.pos+2, term, termbindings) - if err != nil { - return err - } - - child.traceRedo(rule) - return nil - }) - }) - - if err != nil { - return err - } - - // TODO(tsandall): why are we tracing here? this looks wrong. - if !defined { - child.traceFail(rule) - } - - return nil -} - func wrapInObjects(leaf *ast.Term, ref ast.Ref) *ast.Term { // We build the nested objects leaf-to-root to preserve ground:ness if len(ref) == 0 { diff --git a/types/types.go b/types/types.go index b61a0eb2e4..4ea4b4e8e5 100644 --- a/types/types.go +++ b/types/types.go @@ -433,24 +433,24 @@ func (t *Object) Select(name interface{}) Type { func (t *Object) Merge(other Type) *Object { if otherObj, ok := other.(*Object); ok { return mergeObjects(t, otherObj) + } + + var typeK Type + var typeV Type + dynProps := t.DynamicProperties() + if dynProps != nil { + typeK = Or(Keys(other), dynProps.Key) + typeV = Or(Values(other), dynProps.Value) + dynProps = NewDynamicProperty(typeK, typeV) } else { - var typeK Type - var typeV Type - dynProps := t.DynamicProperties() - if dynProps != nil { - typeK = Or(Keys(other), dynProps.Key) - typeV = Or(Values(other), dynProps.Value) + typeK = Keys(other) + typeV = Values(other) + if typeK != nil && typeV != nil { dynProps = NewDynamicProperty(typeK, typeV) - } else { - typeK = Keys(other) - typeV = Values(other) - if typeK != nil && typeV != nil { - dynProps = NewDynamicProperty(typeK, typeV) - } } - - return NewObject(t.StaticProperties(), dynProps) } + + return NewObject(t.StaticProperties(), dynProps) } func mergeObjects(a, b *Object) *Object { @@ -494,8 +494,11 @@ func mergeObjects(a, b *Object) *Object { } var staticProps []*StaticProperty - for k, v := range staticPropsMap { - staticProps = append(staticProps, NewStaticProperty(k, v)) + if len(staticProps) > 0 { + staticProps = make([]*StaticProperty, len(staticPropsMap)) + for k, v := range staticPropsMap { + staticProps = append(staticProps, NewStaticProperty(k, v)) + } } return NewObject(staticProps, dynamicProps)