internal/core: move CloseID from Environment to Conjunct
Change-Id: If83db9714764e30c764c8947cfb3936beafd8bc5
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7001
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
diff --git a/cue/go.go b/cue/go.go
index 28399d9..1d6717c 100644
--- a/cue/go.go
+++ b/cue/go.go
@@ -38,7 +38,7 @@
expr = &adt.Bottom{Err: err}
}
n := &adt.Vertex{}
- n.AddConjunct(adt.MakeConjunct(nil, expr))
+ n.AddConjunct(adt.MakeRootConjunct(nil, expr))
return Value{r.idx, n}
// return convertType(runtime.(*Runtime), x)
diff --git a/cue/instance.go b/cue/instance.go
index 5b954ea..7eb1958 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -75,7 +75,7 @@
st, ok := x.(*adt.Vertex)
if !ok {
st = &adt.Vertex{}
- st.AddConjunct(adt.MakeConjunct(nil, x))
+ st.AddConjunct(adt.MakeRootConjunct(nil, x))
}
return v.ctx().index.addInst(&Instance{
root: st,
@@ -231,7 +231,7 @@
for _, i := range inst {
w := i.Value()
- v.AddConjunct(adt.MakeConjunct(nil, w.v.ToDataAll()))
+ v.AddConjunct(adt.MakeRootConjunct(nil, w.v.ToDataAll()))
}
v.Finalize(ctx)
@@ -255,7 +255,7 @@
v, err := compile.Files(&compile.Config{Scope: inst.root}, r, p.Files...)
- v.AddConjunct(adt.MakeConjunct(nil, inst.root))
+ v.AddConjunct(adt.MakeRootConjunct(nil, inst.root))
i := newInstance(idx, p, v)
if rErr != nil {
@@ -345,7 +345,7 @@
} else {
ctx := eval.NewContext(inst.index.Runtime, nil)
expr := convert.GoValueToExpr(ctx, true, x)
- u.AddConjunct(adt.MakeConjunct(nil, expr))
+ u.AddConjunct(adt.MakeRootConjunct(nil, expr))
u.Finalize(ctx)
}
inst = inst.index.addInst(&Instance{
diff --git a/cue/types.go b/cue/types.go
index 2981a84..0848bbb 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -570,7 +570,7 @@
node.Parent = v.v.Parent
}
node.UpdateStatus(adt.Finalized)
- node.AddConjunct(adt.MakeConjunct(nil, b))
+ node.AddConjunct(adt.MakeRootConjunct(nil, b))
return makeValue(v.idx, node)
}
@@ -590,7 +590,7 @@
return newVertexRoot(ctx, n)
}
node := &adt.Vertex{}
- node.AddConjunct(adt.MakeConjunct(nil, x))
+ node.AddConjunct(adt.MakeRootConjunct(nil, x))
return newVertexRoot(ctx, node)
}
@@ -648,7 +648,7 @@
return Value{base.idx, v}
}
n := &adt.Vertex{Parent: base.v.Parent, Label: base.v.Label}
- n.AddConjunct(adt.MakeConjunct(env, v))
+ n.AddConjunct(adt.MakeRootConjunct(env, v))
n = base.ctx().manifest(n)
return makeValue(base.idx, n)
}
@@ -1556,7 +1556,7 @@
n, _ := value.(*adt.Vertex)
if n == nil {
n = &adt.Vertex{Label: v.v.Label, Parent: v.v.Parent}
- n.AddConjunct(adt.MakeConjunct(nil, value))
+ n.AddConjunct(adt.MakeRootConjunct(nil, value))
} else {
n.Label = v.v.Label
}
@@ -1653,8 +1653,8 @@
return v
}
n := &adt.Vertex{Parent: v.v.Parent, Label: v.v.Label}
- n.AddConjunct(adt.MakeConjunct(nil, v.v))
- n.AddConjunct(adt.MakeConjunct(nil, w.v))
+ n.AddConjunct(adt.MakeRootConjunct(nil, v.v))
+ n.AddConjunct(adt.MakeRootConjunct(nil, w.v))
ctx := v.idx.newContext()
n.Finalize(ctx.opCtx)
@@ -1675,8 +1675,8 @@
}
n := &adt.Vertex{Parent: v.v.Parent, Label: v.v.Label}
- n.AddConjunct(adt.MakeConjunct(nil, v.v))
- n.AddConjunct(adt.MakeConjunct(nil, w.v))
+ n.AddConjunct(adt.MakeRootConjunct(nil, v.v))
+ n.AddConjunct(adt.MakeRootConjunct(nil, w.v))
e := eval.New(v.idx.Runtime)
ctx := e.NewContext(n)
@@ -2166,8 +2166,8 @@
Closed: v.v.Closed,
}
b := a
- a.AddConjunct(adt.MakeConjunct(env, n.Val))
- b.AddConjunct(adt.MakeConjunct(env, disjunct.Val))
+ a.AddConjunct(adt.MakeRootConjunct(env, n.Val))
+ b.AddConjunct(adt.MakeRootConjunct(env, disjunct.Val))
e := eval.New(v.idx.Runtime)
ctx := e.NewContext(nil)
@@ -2246,7 +2246,7 @@
n := &adt.Vertex{
Parent: v.v.Parent,
Label: v.v.Label}
- c := adt.MakeConjunct(envEmbed, x)
+ c := adt.MakeRootConjunct(envEmbed, x)
n.AddConjunct(c)
n.Finalize(ctx)
a = append(a, makeValue(v.idx, n))
@@ -2265,7 +2265,7 @@
Parent: v.v.Parent,
Label: v.v.Label,
}
- c := adt.MakeConjunct(env, &adt.StructLit{
+ c := adt.MakeRootConjunct(env, &adt.StructLit{
Decls: fields,
})
n.AddConjunct(c)
diff --git a/internal/core/adt/composite.go b/internal/core/adt/composite.go
index 999d4d8..3cbbbd1 100644
--- a/internal/core/adt/composite.go
+++ b/internal/core/adt/composite.go
@@ -91,10 +91,6 @@
// TODO(perf): make the following public fields a shareable struct as it
// mostly is going to be the same for child nodes.
- // CloseID is a unique number that tracks a group of conjuncts that need
- // belong to a single originating definition.
- CloseID uint32
-
// Cyclic indicates a structural cycle was detected for this conjunct or one
// of its ancestors.
Cyclic bool
@@ -129,6 +125,8 @@
cache map[Expr]Value
}
+type ID int32
+
// evalCached is used to look up let expressions. Caching let expressions
// prevents a possible combinatorial explosion.
func (e *Environment) evalCached(c *OpContext, x Expr) Value {
@@ -337,7 +335,7 @@
status: Finalized,
Value: x,
}
- n.AddConjunct(MakeConjunct(nil, v))
+ n.AddConjunct(MakeRootConjunct(nil, v))
return n
}
}
@@ -557,13 +555,25 @@
type Conjunct struct {
Env *Environment
x Node
+
+ // CloseID is a unique number that tracks a group of conjuncts that need
+ // belong to a single originating definition.
+ CloseID ID
+}
+
+func (c *Conjunct) ID() ID {
+ return c.CloseID
}
// TODO(perf): replace with composite literal if this helps performance.
-// MakeConjunct creates a conjunct from the given environment and node.
+// MakeRootConjunct creates a conjunct from the given environment and node.
// It panics if x cannot be used as an expression.
-func MakeConjunct(env *Environment, x Node) Conjunct {
+func MakeRootConjunct(env *Environment, x Node) Conjunct {
+ return MakeConjunct(env, x, 0)
+}
+
+func MakeConjunct(env *Environment, x Node, id ID) Conjunct {
if env == nil {
// TODO: better is to pass one.
env = &Environment{}
@@ -573,7 +583,7 @@
default:
panic(fmt.Sprintf("invalid Node type %T", x))
}
- return Conjunct{env, x}
+ return Conjunct{env, x, id}
}
func (c *Conjunct) Source() ast.Node {
diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go
index 9a36cc1..7cb2aa0 100644
--- a/internal/core/adt/context.go
+++ b/internal/core/adt/context.go
@@ -160,9 +160,6 @@
sub := *c
node.Parent = c.e.Vertex
sub.e = &Environment{Up: c.e, Vertex: node}
- if c.e != nil {
- sub.e.CloseID = c.e.CloseID
- }
return &sub
}
@@ -290,9 +287,7 @@
if src != nil {
c.src = src
}
- if env != nil {
- c.e = env
- }
+ c.e = env
return saved
}
diff --git a/internal/core/adt/default.go b/internal/core/adt/default.go
index 2dd1ff7..fc922bd 100644
--- a/internal/core/adt/default.go
+++ b/internal/core/adt/default.go
@@ -69,7 +69,7 @@
for _, c := range v.Conjuncts {
// TODO: preserve field information.
expr, _ := stripNonDefaults(c.Expr())
- w.Conjuncts = append(w.Conjuncts, MakeConjunct(c.Env, expr))
+ w.Conjuncts = append(w.Conjuncts, MakeRootConjunct(c.Env, expr))
}
return w
diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go
index 8fbdcec..4b53894 100644
--- a/internal/core/adt/expr.go
+++ b/internal/core/adt/expr.go
@@ -40,7 +40,7 @@
func (x *StructLit) evaluate(c *OpContext) Value {
e := c.Env(0)
- v := &Vertex{Conjuncts: []Conjunct{{e, x}}}
+ v := &Vertex{Conjuncts: []Conjunct{{e, x, 0}}}
c.Unifier.Unify(c, v, Finalized) // TODO: also partial okay?
return v
}
@@ -168,7 +168,7 @@
func (x *ListLit) evaluate(c *OpContext) Value {
e := c.Env(0)
- v := &Vertex{Conjuncts: []Conjunct{{e, x}}}
+ v := &Vertex{Conjuncts: []Conjunct{{e, x, 0}}}
c.Unifier.Unify(c, v, Finalized) // TODO: also partial okay?
return v
}
@@ -547,7 +547,7 @@
e := c.Env(x.UpCount)
label := e.Vertex.Label
// Anonymous arc.
- return &Vertex{Parent: nil, Label: label, Conjuncts: []Conjunct{{e, x.X}}}
+ return &Vertex{Parent: nil, Label: label, Conjuncts: []Conjunct{{e, x.X, 0}}}
}
func (x *LetReference) evaluate(c *OpContext) Value {
@@ -822,7 +822,7 @@
env := c.Env(0)
if x.Op == AndOp {
// Anonymous Arc
- v := Vertex{Conjuncts: []Conjunct{{env, x}}}
+ v := Vertex{Conjuncts: []Conjunct{{env, x, 0}}}
return c.Unifier.Evaluate(c, &v)
}
@@ -1094,7 +1094,7 @@
func (x *DisjunctionExpr) evaluate(c *OpContext) Value {
e := c.Env(0)
- v := &Vertex{Conjuncts: []Conjunct{{e, x}}}
+ v := &Vertex{Conjuncts: []Conjunct{{e, x, 0}}}
c.Unifier.Unify(c, v, Finalized) // TODO: also partial okay?
// TODO: if the disjunction result originated from a literal value, we may
// consider the result closed to create more permanent errors.
@@ -1178,7 +1178,7 @@
if x.Key != 0 {
v := &Vertex{Label: x.Key}
key := a.Label.ToValue(c)
- v.AddConjunct(MakeConjunct(c.Env(0), key))
+ v.AddConjunct(MakeRootConjunct(c.Env(0), key))
v.SetValue(c, Finalized, key)
n.Arcs = append(n.Arcs, v)
}
@@ -1234,7 +1234,7 @@
func (x *LetClause) yield(c *OpContext, f YieldFunc) {
n := &Vertex{Arcs: []*Vertex{
- {Label: x.Label, Conjuncts: []Conjunct{{c.Env(0), x.Expr}}},
+ {Label: x.Label, Conjuncts: []Conjunct{{c.Env(0), x.Expr, 0}}},
}}
x.Dst.yield(c.spawn(n), f)
}
diff --git a/internal/core/compile/builtin.go b/internal/core/compile/builtin.go
index 8934019..75972dc 100644
--- a/internal/core/compile/builtin.go
+++ b/internal/core/compile/builtin.go
@@ -128,7 +128,7 @@
}
v := &adt.Vertex{}
// TODO: make a Disjunction.
- v.AddConjunct(adt.MakeConjunct(nil,
+ v.AddConjunct(adt.MakeRootConjunct(nil,
&adt.DisjunctionExpr{Values: d, HasDefaults: false},
))
c.Unify(c, v, adt.Finalized)
diff --git a/internal/core/compile/compile.go b/internal/core/compile/compile.go
index dbb556a..eab01fd 100644
--- a/internal/core/compile/compile.go
+++ b/internal/core/compile/compile.go
@@ -241,7 +241,7 @@
c.pushScope(nil, 0, file) // File scope
v := &adt.StructLit{Src: file}
c.addDecls(v, file.Decls)
- res.Conjuncts = append(res.Conjuncts, adt.MakeConjunct(nil, v))
+ res.Conjuncts = append(res.Conjuncts, adt.MakeRootConjunct(nil, v))
c.popScope()
}
@@ -278,7 +278,7 @@
// env = e
}
- return adt.MakeConjunct(env, expr)
+ return adt.MakeRootConjunct(env, expr)
}
// resolve assumes that all existing resolutions are legal. Validation should
diff --git a/internal/core/convert/go.go b/internal/core/convert/go.go
index 067321d..2a4173b 100644
--- a/internal/core/convert/go.go
+++ b/internal/core/convert/go.go
@@ -63,7 +63,7 @@
return v
}
obj := &adt.Vertex{}
- obj.AddConjunct(adt.MakeConjunct(nil, e))
+ obj.AddConjunct(adt.MakeRootConjunct(nil, e))
return obj
}
@@ -400,7 +400,7 @@
case reflect.Struct:
obj := &adt.StructLit{Src: src}
v := &adt.Vertex{}
- v.AddConjunct(adt.MakeConjunct(nil, obj))
+ v.AddConjunct(adt.MakeRootConjunct(nil, obj))
v.SetValue(ctx, adt.Finalized, &adt.StructMarker{})
t := value.Type()
@@ -441,7 +441,7 @@
arc.Label = f
} else {
arc = &adt.Vertex{Label: f, Value: sub}
- arc.AddConjunct(adt.MakeConjunct(nil, sub))
+ arc.AddConjunct(adt.MakeRootConjunct(nil, sub))
}
v.Arcs = append(v.Arcs, arc)
}
@@ -451,7 +451,7 @@
case reflect.Map:
obj := &adt.StructLit{Src: src}
v := &adt.Vertex{Value: &adt.StructMarker{}}
- v.AddConjunct(adt.MakeConjunct(nil, obj))
+ v.AddConjunct(adt.MakeRootConjunct(nil, obj))
v.SetValue(ctx, adt.Finalized, &adt.StructMarker{})
t := value.Type()
@@ -492,7 +492,7 @@
arc.Label = f
} else {
arc = &adt.Vertex{Label: f, Value: sub}
- arc.AddConjunct(adt.MakeConjunct(nil, sub))
+ arc.AddConjunct(adt.MakeRootConjunct(nil, sub))
}
v.Arcs = append(v.Arcs, arc)
}
diff --git a/internal/core/eval/closed.go b/internal/core/eval/closed.go
index 56a0d7f..175b08d 100644
--- a/internal/core/eval/closed.go
+++ b/internal/core/eval/closed.go
@@ -143,7 +143,7 @@
// any value.
type CloseDef struct {
Src adt.Node // for error reporting
- ID uint32
+ ID adt.ID
IsAnd bool
List []*CloseDef
}
@@ -161,7 +161,7 @@
// a CloseDef tree based on replacement information gathered during evaluation
// of this flat list.
//
-func updateClosed(c *CloseDef, replace map[uint32]*CloseDef) *CloseDef { // used in eval.go
+func updateClosed(c *CloseDef, replace map[adt.ID]*CloseDef) *CloseDef { // used in eval.go
// Insert an entry for CloseID 0 if we are about to replace it. By default
// 0, which is the majority case, is omitted.
if c != nil && replace[0] != nil && !containsClosed(c, 0) {
@@ -190,7 +190,7 @@
return c
}
-func updateClosedRec(c *CloseDef, replace map[uint32]*CloseDef) *CloseDef {
+func updateClosedRec(c *CloseDef, replace map[adt.ID]*CloseDef) *CloseDef {
if c == nil {
return nil
}
@@ -239,18 +239,13 @@
// UpdateReplace is called after evaluating a conjunct at the top of the arc
// to update the replacement information with the gathered CloseDef info.
-func (n *nodeContext) updateReplace(env *adt.Environment) { // used in eval.go
+func (n *nodeContext) updateReplace(id adt.ID) { // used in eval.go
if n.newClose == nil {
return
}
if n.replace == nil {
- n.replace = make(map[uint32]*CloseDef)
- }
-
- id := uint32(0)
- if env != nil {
- id = env.CloseID
+ n.replace = make(map[adt.ID]*CloseDef)
}
n.replace[id] = updateClose(n.replace[id], n.newClose)
@@ -310,7 +305,7 @@
}
}
-func (n *nodeContext) addOr(parentID uint32, c *CloseDef) { // used in eval.go
+func (n *nodeContext) addOr(parentID adt.ID, c *CloseDef) { // used in eval.go
switch {
case n.newClose == nil:
d := &CloseDef{ID: parentID, List: []*CloseDef{{ID: parentID}}}
@@ -337,6 +332,7 @@
// more clever and only generate this when it is a user error.
filter := f.IsString() || f == adt.InvalidLabel
if filter && !n.verifyArcRecursive(ctx, n.tree, f) {
+ collectPositions(ctx, n.tree)
label := f.SelectorString(ctx)
return ctx.NewErrf("field `%s` not allowed", label)
}
@@ -365,9 +361,9 @@
// verifyDefinition reports whether f is a valid member for any of the fieldSets
// with the same closeID.
-func (n *acceptor) verifyDefinition(ctx *adt.OpContext, closeID uint32, f adt.Feature) (ok bool) {
+func (n *acceptor) verifyDefinition(ctx *adt.OpContext, closeID adt.ID, f adt.Feature) (ok bool) {
for _, o := range n.fields {
- if o.env.CloseID != closeID {
+ if o.id != closeID {
continue
}
@@ -387,7 +383,6 @@
}
}
}
- collectPositions(ctx, n.tree)
for _, o := range n.fields {
if o.pos != nil {
ctx.AddPosition(o.pos)
@@ -407,7 +402,7 @@
// containsClosed reports whether c contains any CloseDef with ID x,
// recursively.
-func containsClosed(c *CloseDef, x uint32) bool {
+func containsClosed(c *CloseDef, x adt.ID) bool {
if c.ID == x && !c.IsAnd {
return true
}
diff --git a/internal/core/eval/closed_test.go b/internal/core/eval/closed_test.go
index c0ed278..45511f6 100644
--- a/internal/core/eval/closed_test.go
+++ b/internal/core/eval/closed_test.go
@@ -17,6 +17,7 @@
import (
"testing"
+ "cuelang.org/go/internal/core/adt"
"github.com/google/go-cmp/cmp"
)
@@ -24,12 +25,12 @@
testCases := []struct {
desc string
close *CloseDef
- replace map[uint32]*CloseDef
+ replace map[adt.ID]*CloseDef
want *CloseDef
}{{
desc: "introduce new",
close: nil,
- replace: map[uint32]*CloseDef{
+ replace: map[adt.ID]*CloseDef{
0: {ID: 2, IsAnd: false, List: nil},
},
want: &CloseDef{
@@ -40,7 +41,7 @@
close: &CloseDef{
ID: 1,
},
- replace: map[uint32]*CloseDef{
+ replace: map[adt.ID]*CloseDef{
0: {ID: 2, IsAnd: false, List: nil},
1: nil, // keep 1
},
@@ -53,7 +54,7 @@
close: &CloseDef{
ID: 1,
},
- replace: map[uint32]*CloseDef{
+ replace: map[adt.ID]*CloseDef{
1: {ID: 1, IsAnd: true, List: []*CloseDef{{ID: 2}, {ID: 3}}},
},
want: &CloseDef{
@@ -66,7 +67,7 @@
close: &CloseDef{
ID: 1,
},
- replace: map[uint32]*CloseDef{
+ replace: map[adt.ID]*CloseDef{
0: nil,
},
want: nil,
@@ -80,7 +81,7 @@
{ID: 3},
},
},
- replace: map[uint32]*CloseDef{2: nil},
+ replace: map[adt.ID]*CloseDef{2: nil},
want: &CloseDef{ID: 2},
}, {
desc: "eliminateAllEmbeddings",
@@ -91,7 +92,7 @@
{ID: 3},
},
},
- replace: map[uint32]*CloseDef{0: {ID: 4}, 4: nil},
+ replace: map[adt.ID]*CloseDef{0: {ID: 4}, 4: nil},
want: &CloseDef{ID: 4},
}, {
// Do not eliminate an embedding that has a replacement.
@@ -103,7 +104,7 @@
{ID: 3},
},
},
- replace: map[uint32]*CloseDef{
+ replace: map[adt.ID]*CloseDef{
2: nil,
3: {ID: 3, IsAnd: true, List: []*CloseDef{{ID: 4}, {ID: 5}}},
},
@@ -134,7 +135,7 @@
{ID: 0},
},
},
- replace: map[uint32]*CloseDef{0: {ID: 3}},
+ replace: map[adt.ID]*CloseDef{0: {ID: 3}},
want: &CloseDef{ID: 3},
}, {
// Select b within a
@@ -156,7 +157,7 @@
{ID: 0},
},
},
- replace: map[uint32]*CloseDef{
+ replace: map[adt.ID]*CloseDef{
0: {IsAnd: true, List: []*CloseDef{{ID: 3}, {ID: 4}}},
},
want: &CloseDef{
diff --git a/internal/core/eval/disjunct.go b/internal/core/eval/disjunct.go
index 27c479d..6028093 100644
--- a/internal/core/eval/disjunct.go
+++ b/internal/core/eval/disjunct.go
@@ -87,7 +87,7 @@
env *adt.Environment
values []disjunct
numDefaults int
- cloneID uint32
+ cloneID adt.ID
isEmbed bool
}
@@ -96,7 +96,7 @@
isDefault bool
}
-func (n *nodeContext) addDisjunction(env *adt.Environment, x *adt.DisjunctionExpr, cloneID uint32, isEmbed bool) {
+func (n *nodeContext) addDisjunction(env *adt.Environment, x *adt.DisjunctionExpr, cloneID adt.ID, isEmbed bool) {
a := []disjunct{}
numDefaults := 0
@@ -116,7 +116,7 @@
envDisjunct{env, a, numDefaults, cloneID, isEmbed})
}
-func (n *nodeContext) addDisjunctionValue(env *adt.Environment, x *adt.Disjunction, cloneID uint32, isEmbed bool) {
+func (n *nodeContext) addDisjunctionValue(env *adt.Environment, x *adt.Disjunction, cloneID adt.ID, isEmbed bool) {
a := []disjunct{}
for i, v := range x.Values {
@@ -297,8 +297,8 @@
k := n.stack[p]
v := d.values[k]
n.isFinal = n.isFinal && k == len(d.values)-1
- c := adt.MakeConjunct(d.env, v.expr)
- n.addExprConjunct(c, d.cloneID, d.isEmbed)
+ c := adt.MakeConjunct(d.env, v.expr, d.cloneID)
+ n.addExprConjunct(c, d.isEmbed)
for n.expandOne() {
}
diff --git a/internal/core/eval/eval.go b/internal/core/eval/eval.go
index 647d4b8..bc5a477 100644
--- a/internal/core/eval/eval.go
+++ b/internal/core/eval/eval.go
@@ -112,12 +112,12 @@
type Evaluator struct {
r adt.Runtime
index adt.StringIndexer
- closeID uint32
+ closeID adt.ID
stats Stats
}
-func (e *Evaluator) nextID() uint32 {
+func (e *Evaluator) nextID() adt.ID {
e.closeID++
return e.closeID
}
@@ -363,16 +363,10 @@
isFinal: true,
}
- closeID := uint32(0)
-
for _, x := range v.Conjuncts {
- closeID := closeID
// TODO: needed for reentrancy. Investigate usefulness for cycle
// detection.
- if x.Env != nil && x.Env.CloseID != 0 {
- closeID = x.Env.CloseID
- }
- n.addExprConjunct(x, closeID, true)
+ n.addExprConjunct(x, true)
}
if i == 0 {
@@ -577,20 +571,20 @@
replace := n.replace
if replace == nil {
- replace = map[uint32]*CloseDef{}
+ replace = map[adt.ID]*CloseDef{}
}
// Mark any used CloseID to keep, if not already replaced.
for _, x := range n.optionals {
- if _, ok := replace[x.env.CloseID]; !ok {
- replace[x.env.CloseID] = nil
+ if _, ok := replace[x.id]; !ok {
+ replace[x.id] = nil
}
}
for _, a := range n.node.Arcs {
for _, c := range a.Conjuncts {
if c.Env != nil {
- if _, ok := replace[c.Env.CloseID]; !ok {
- replace[c.Env.CloseID] = nil
+ if _, ok := replace[c.ID()]; !ok {
+ replace[c.ID()] = nil
}
}
}
@@ -753,8 +747,8 @@
aStruct adt.Expr
hasTop bool
newClose *CloseDef
- // closeID uint32 // from parent, or if not exist, new if introducing a def.
- replace map[uint32]*CloseDef
+ // closeID adt.ID // from parent, or if not exist, new if introducing a def.
+ replace map[adt.ID]*CloseDef
// Expression conjuncts
lists []envList
@@ -891,18 +885,19 @@
type conjunct struct {
adt.Conjunct
- closeID uint32
- top bool
+ top bool
}
type envDynamic struct {
env *adt.Environment
field *adt.DynamicField
+ id adt.ID
}
type envYield struct {
env *adt.Environment
yield adt.Yielder
+ id adt.ID
}
type envList struct {
@@ -910,6 +905,7 @@
list *adt.ListLit
n int64 // recorded length after evaluator
elipsis *adt.Ellipsis
+ id adt.ID
}
func (n *nodeContext) addBottom(b *adt.Bottom) {
@@ -927,52 +923,51 @@
// addExprConjuncts will attempt to evaluate an adt.Expr and insert the value
// into the nodeContext if successful or queue it for later evaluation if it is
// incomplete or is not value.
-func (n *nodeContext) addExprConjunct(v adt.Conjunct, def uint32, top bool) {
+func (n *nodeContext) addExprConjunct(v adt.Conjunct, top bool) {
env := v.Env
- if env != nil && env.CloseID != def {
- e := *env
- e.CloseID = def
- env = &e
- }
+ id := v.CloseID
+
switch x := v.Expr().(type) {
case adt.Value:
- n.addValueConjunct(env, x)
+ n.addValueConjunct(env, x, id)
case *adt.BinaryExpr:
if x.Op == adt.AndOp {
- n.addExprConjunct(adt.MakeConjunct(env, x.X), def, false)
- n.addExprConjunct(adt.MakeConjunct(env, x.Y), def, false)
+ n.addExprConjunct(adt.MakeConjunct(env, x.X, id), false)
+ n.addExprConjunct(adt.MakeConjunct(env, x.Y, id), false)
} else {
- n.evalExpr(v, def, top)
+ n.evalExpr(v, top)
}
case *adt.StructLit:
- n.addStruct(env, x, def, top)
+ n.addStruct(env, x, id, top)
case *adt.ListLit:
- n.lists = append(n.lists, envList{env: env, list: x})
+ n.lists = append(n.lists, envList{env: env, list: x, id: id})
case *adt.DisjunctionExpr:
if n.disjunctions != nil {
_ = n.disjunctions
}
- n.addDisjunction(env, x, def, top)
+ n.addDisjunction(env, x, id, top)
default:
// Must be Resolver or Evaluator.
- n.evalExpr(v, def, top)
+ n.evalExpr(v, top)
}
if top {
- n.updateReplace(v.Env)
+ n.updateReplace(v.CloseID)
}
}
// evalExpr is only called by addExprConjunct.
-func (n *nodeContext) evalExpr(v adt.Conjunct, closeID uint32, top bool) {
+func (n *nodeContext) evalExpr(v adt.Conjunct, top bool) {
// Require an Environment.
ctx := n.ctx
+ closeID := v.CloseID
+
// TODO: see if we can do without these counters.
for _, d := range v.Env.Deref {
d.EvalCount++
@@ -1002,7 +997,7 @@
}
}
if arc == nil {
- n.exprs = append(n.exprs, conjunct{v, closeID, top})
+ n.exprs = append(n.exprs, conjunct{v, top})
break
}
@@ -1074,8 +1069,10 @@
id := n.eval.nextID()
n.insertClosed(arc, id, cyclic, arc)
} else {
- for _, a := range arc.Conjuncts {
- n.addExprConjunct(updateCyclic(a, cyclic, arc), closeID, top)
+ for _, c := range arc.Conjuncts {
+ c = updateCyclic(c, cyclic, arc)
+ c.CloseID = closeID
+ n.addExprConjunct(c, top)
}
}
@@ -1084,7 +1081,7 @@
// Could be unify?
val, complete := ctx.Evaluate(v.Env, v.Expr())
if !complete {
- n.exprs = append(n.exprs, conjunct{v, closeID, top})
+ n.exprs = append(n.exprs, conjunct{v, top})
break
}
@@ -1094,14 +1091,15 @@
b, ok := v.Value.(*adt.Bottom)
if ok && b.IsIncomplete() && len(v.Conjuncts) > 0 {
for _, c := range v.Conjuncts {
- n.addExprConjunct(c, closeID, top)
+ c.CloseID = closeID
+ n.addExprConjunct(c, top)
}
break
}
}
// TODO: insert in vertex as well
- n.addValueConjunct(v.Env, val)
+ n.addValueConjunct(v.Env, val, closeID)
default:
panic(fmt.Sprintf("unknown expression of type %T", x))
@@ -1138,17 +1136,19 @@
env.Deref = append(env.Deref, deref)
env.Cycles = append(env.Cycles, deref)
}
- return adt.MakeConjunct(env, c.Expr())
+ return adt.MakeConjunct(env, c.Expr(), c.CloseID)
}
-func (n *nodeContext) insertClosed(arc *adt.Vertex, id uint32, cyclic bool, deref *adt.Vertex) {
+func (n *nodeContext) insertClosed(arc *adt.Vertex, id adt.ID, cyclic bool, deref *adt.Vertex) {
n.needClose = true
current := n.newClose
n.newClose = nil
- for _, a := range arc.Conjuncts {
- n.addExprConjunct(updateCyclic(a, cyclic, deref), id, false)
+ for _, c := range arc.Conjuncts {
+ c = updateCyclic(c, cyclic, deref)
+ c.CloseID = id
+ n.addExprConjunct(c, false)
}
current, n.newClose = n.newClose, current
@@ -1159,7 +1159,7 @@
n.addAnd(current)
}
-func (n *nodeContext) addValueConjunct(env *adt.Environment, v adt.Value) {
+func (n *nodeContext) addValueConjunct(env *adt.Environment, v adt.Value, id adt.ID) {
n.updateCyclicStatus(env)
if x, ok := v.(*adt.Vertex); ok {
@@ -1181,11 +1181,13 @@
if !x.IsData() && len(x.Conjuncts) > 0 {
cyclic := env != nil && env.Cyclic
if needClose {
- n.insertClosed(x, env.CloseID, cyclic, nil)
+ n.insertClosed(x, id, cyclic, nil)
return
}
for _, c := range x.Conjuncts {
- n.addExprConjunct(updateCyclic(c, cyclic, nil), 0, false) // TODO: Pass from eval
+ c = updateCyclic(c, cyclic, nil)
+ c.CloseID = id
+ n.addExprConjunct(c, false) // TODO: Pass from eval
}
return
}
@@ -1206,17 +1208,17 @@
n.aStruct = x
}
// TODO, insert here as
- n.insertField(a.Label, adt.MakeConjunct(nil, a))
+ n.insertField(a.Label, adt.MakeConjunct(nil, a, id))
// sub, _ := n.node.GetArc(a.Label)
// sub.Add(a)
}
default:
- n.addValueConjunct(env, v)
+ n.addValueConjunct(env, v, id)
for _, a := range x.Arcs {
// TODO(errors): report error when this is a regular field.
- n.insertField(a.Label, adt.MakeConjunct(nil, a))
+ n.insertField(a.Label, adt.MakeConjunct(nil, a, id))
// sub, _ := n.node.GetArc(a.Label)
// sub.Add(a)
}
@@ -1239,17 +1241,17 @@
switch x := v.(type) {
case *adt.Disjunction:
- n.addDisjunctionValue(env, x, 0, true)
+ n.addDisjunctionValue(env, x, id, true)
case *adt.Conjunction:
for _, x := range x.Values {
- n.addValueConjunct(env, x)
+ n.addValueConjunct(env, x, id)
}
case *adt.Top:
n.hasTop = true
// TODO: Is this correct. Needed for elipsis, but not sure for others.
- n.optionals = append(n.optionals, fieldSet{env: env, isOpen: true})
+ n.optionals = append(n.optionals, fieldSet{env: env, id: id, isOpen: true})
case *adt.BasicType:
// handled above
@@ -1259,7 +1261,7 @@
case adt.LessThanOp, adt.LessEqualOp:
if y := n.upperBound; y != nil {
n.upperBound = nil
- n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y))
+ n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y), id)
return
}
n.upperBound = x
@@ -1267,7 +1269,7 @@
case adt.GreaterThanOp, adt.GreaterEqualOp:
if y := n.lowerBound; y != nil {
n.lowerBound = nil
- n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y))
+ n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y), id)
return
}
n.lowerBound = x
@@ -1303,7 +1305,7 @@
if u := adt.SimplifyBounds(ctx, n.kind, n.lowerBound, n.upperBound); u != nil {
n.lowerBound = nil
n.upperBound = nil
- n.addValueConjunct(env, u)
+ n.addValueConjunct(env, u, id)
}
}
}
@@ -1318,7 +1320,7 @@
func (n *nodeContext) addStruct(
env *adt.Environment,
s *adt.StructLit,
- newDef uint32,
+ closeID adt.ID,
top bool) {
n.updateCyclicStatus(env) // to handle empty structs.
@@ -1326,12 +1328,6 @@
ctx := n.ctx
n.node.AddStructs(s)
- // Inherit closeID from environment, unless this is a new definition.
- closeID := newDef
- if closeID == 0 && env != nil {
- closeID = env.CloseID
- }
-
// NOTE: This is a crucial point in the code:
// Unification derferencing happens here. The child nodes are set to
// an Environment linked to the current node. Together with the De Bruijn
@@ -1345,9 +1341,8 @@
// }
// }
childEnv := &adt.Environment{
- Up: env,
- Vertex: n.node,
- CloseID: closeID,
+ Up: env,
+ Vertex: n.node,
}
if env != nil {
childEnv.Cyclic = env.Cyclic
@@ -1357,7 +1352,7 @@
var hasOther, hasBulk adt.Node
hasEmbed := false
- opt := fieldSet{pos: s, env: childEnv}
+ opt := fieldSet{pos: s, env: childEnv, id: closeID}
for _, d := range s.Decls {
switch x := d.(type) {
@@ -1374,16 +1369,16 @@
case *adt.DynamicField:
n.aStruct = s
hasOther = x
- n.dynamicFields = append(n.dynamicFields, envDynamic{childEnv, x})
+ n.dynamicFields = append(n.dynamicFields, envDynamic{childEnv, x, closeID})
opt.AddDynamic(ctx, childEnv, x)
case *adt.ForClause:
hasOther = x
- n.forClauses = append(n.forClauses, envYield{childEnv, x})
+ n.forClauses = append(n.forClauses, envYield{childEnv, x, closeID})
case adt.Yielder:
hasOther = x
- n.ifClauses = append(n.ifClauses, envYield{childEnv, x})
+ n.ifClauses = append(n.ifClauses, envYield{childEnv, x, closeID})
case adt.Expr:
hasEmbed = true
@@ -1395,7 +1390,7 @@
n.newClose = nil
hasOther = x
- n.addExprConjunct(adt.MakeConjunct(childEnv, x), id, false)
+ n.addExprConjunct(adt.MakeConjunct(childEnv, x, id), false)
current, n.newClose = n.newClose, current
@@ -1443,7 +1438,7 @@
if x.Label.IsString() {
n.aStruct = s
}
- n.insertField(x.Label, adt.MakeConjunct(childEnv, x))
+ n.insertField(x.Label, adt.MakeConjunct(childEnv, x, closeID))
}
}
}
@@ -1502,7 +1497,7 @@
exprs := n.exprs
n.exprs = n.exprs[:0]
for _, x := range exprs {
- n.addExprConjunct(x.Conjunct, x.closeID, x.top)
+ n.addExprConjunct(x.Conjunct, x.top)
// collect and and or
}
@@ -1530,11 +1525,11 @@
continue
}
if b, _ := v.(*adt.Bottom); b != nil {
- n.addValueConjunct(nil, b)
+ n.addValueConjunct(nil, b, d.id)
continue
}
f = ctx.Label(v)
- n.insertField(f, adt.MakeConjunct(d.env, d.field))
+ n.insertField(f, adt.MakeConjunct(d.env, d.field, d.id))
}
progress = k < len(n.dynamicFields)
@@ -1575,7 +1570,7 @@
}
for _, st := range sa {
- n.addStruct(st.env, st.s, 0, true)
+ n.addStruct(st.env, st.s, d.id, true)
}
}
@@ -1639,7 +1634,7 @@
for _, a := range elems {
if a.Conjuncts == nil {
- n.insertField(a.Label, adt.MakeConjunct(nil, a.Value))
+ n.insertField(a.Label, adt.MakeConjunct(nil, a.Value, 0))
continue
}
for _, c := range a.Conjuncts {
@@ -1663,7 +1658,7 @@
label, err := adt.MakeLabel(x.Source(), index, adt.IntLabel)
n.addErr(err)
index++
- n.insertField(label, adt.MakeConjunct(e, st))
+ n.insertField(label, adt.MakeConjunct(e, st, l.id))
})
hasComprehension = true
if err != nil && !err.IsIncomplete() {
@@ -1681,7 +1676,7 @@
label, err := adt.MakeLabel(x.Source(), index, adt.IntLabel)
n.addErr(err)
index++ // TODO: don't use insertField.
- n.insertField(label, adt.MakeConjunct(l.env, x))
+ n.insertField(label, adt.MakeConjunct(l.env, x, l.id))
}
// Terminate early n case of runaway comprehension.
@@ -1734,7 +1729,7 @@
continue
}
- f := fieldSet{pos: l.list, env: l.env}
+ f := fieldSet{pos: l.list, env: l.env, id: l.id}
f.AddEllipsis(c, l.elipsis)
n.optionals = append(n.optionals, f)
diff --git a/internal/core/eval/optionals.go b/internal/core/eval/optionals.go
index 0426c18..947dd19 100644
--- a/internal/core/eval/optionals.go
+++ b/internal/core/eval/optionals.go
@@ -23,11 +23,13 @@
// fieldSet represents the fields for a single struct literal, along
// the constraints of fields that may be added.
type fieldSet struct {
- pos adt.Node
+ next *fieldSet
+ pos adt.Node
// TODO: look at consecutive identical environments to figure out
// what belongs to same definition?
env *adt.Environment
+ id adt.ID
// field marks the optional conjuncts of all explicit fields.
// Required fields are marked as empty
@@ -104,7 +106,7 @@
}
if p < len(o.fields) {
for _, e := range o.fields[p].optional {
- arc.AddConjunct(adt.MakeConjunct(env, e))
+ arc.AddConjunct(adt.MakeConjunct(env, e, o.id))
}
return
}
@@ -122,7 +124,7 @@
if f.check.Match(c, arc.Label) {
matched = true
if f.expr != nil {
- arc.AddConjunct(adt.MakeConjunct(&bulkEnv, f.expr))
+ arc.AddConjunct(adt.MakeConjunct(&bulkEnv, f.expr, o.id))
}
}
}
@@ -132,7 +134,7 @@
// match others
for _, x := range o.additional {
- arc.AddConjunct(adt.MakeConjunct(env, x))
+ arc.AddConjunct(adt.MakeConjunct(env, x, o.id))
}
}
@@ -242,13 +244,13 @@
v := adt.Vertex{}
v.AddConjunct(adt.Conjunct(m))
label := f.ToValue(c)
- v.AddConjunct(adt.MakeConjunct(m.Env, label))
+ v.AddConjunct(adt.MakeRootConjunct(m.Env, label))
v.Finalize(c)
b, _ := v.Value.(*adt.Bottom)
return b == nil
}
func (o *fieldSet) newPatternMatcher(ctx *adt.OpContext, x adt.Value) fieldMatcher {
- c := adt.MakeConjunct(o.env, x)
+ c := adt.MakeRootConjunct(o.env, x)
return patternMatcher(c)
}
diff --git a/internal/core/export/export.go b/internal/core/export/export.go
index 51f2209..733c202 100644
--- a/internal/core/export/export.go
+++ b/internal/core/export/export.go
@@ -291,7 +291,7 @@
func (e *exporter) setDocs(x adt.Node) {
f := e.stack[len(e.stack)-1]
- f.docSources = []adt.Conjunct{adt.MakeConjunct(nil, x)}
+ f.docSources = []adt.Conjunct{adt.MakeRootConjunct(nil, x)}
e.stack[len(e.stack)-1] = f
}
diff --git a/internal/core/export/expr.go b/internal/core/export/expr.go
index 3edc5f5..7f130f5 100644
--- a/internal/core/export/expr.go
+++ b/internal/core/export/expr.go
@@ -65,7 +65,7 @@
return e.mergeValues(adt.InvalidLabel, x, a, x.Conjuncts...)
case *adt.StructLit:
- c := adt.MakeConjunct(nil, x)
+ c := adt.MakeRootConjunct(nil, x)
return e.mergeValues(adt.InvalidLabel, nil, []conjunct{{c: c, up: 0}}, c)
case adt.Value:
@@ -204,7 +204,7 @@
func (c *conjuncts) addConjunct(f adt.Feature, env *adt.Environment, n adt.Node) {
x := c.fields[f]
- v := adt.MakeConjunct(env, n)
+ v := adt.MakeRootConjunct(env, n)
x.conjuncts = append(x.conjuncts, conjunct{
c: v,
up: c.top().upCount,
@@ -282,7 +282,7 @@
switch x.(type) {
case *adt.StructMarker, *adt.Top:
default:
- e.values.AddConjunct(adt.MakeConjunct(env, x)) // GOBBLE TOP
+ e.values.AddConjunct(adt.MakeRootConjunct(env, x)) // GOBBLE TOP
}
case *adt.BinaryExpr:
@@ -291,14 +291,14 @@
e.addExpr(env, x.X)
e.addExpr(env, x.Y)
case isSelfContained(x):
- e.values.AddConjunct(adt.MakeConjunct(env, x))
+ e.values.AddConjunct(adt.MakeRootConjunct(env, x))
default:
e.exprs = append(e.exprs, e.expr(x))
}
default:
if isSelfContained(x) {
- e.values.AddConjunct(adt.MakeConjunct(env, x))
+ e.values.AddConjunct(adt.MakeRootConjunct(env, x))
} else {
e.exprs = append(e.exprs, e.expr(x))
}
diff --git a/internal/core/subsume/structural.go b/internal/core/subsume/structural.go
index 16e7a0e..bc581cb 100644
--- a/internal/core/subsume/structural.go
+++ b/internal/core/subsume/structural.go
@@ -42,7 +42,7 @@
}
func (s *subsumer) c(env *adt.Environment, x adt.Expr) adt.Conjunct {
- return adt.MakeConjunct(env, x)
+ return adt.MakeRootConjunct(env, x)
}
func isBottomConjunct(c adt.Conjunct) bool {
@@ -247,12 +247,12 @@
case *adt.Field:
e := c.fields[x.Label]
e.required = true
- e.conjuncts = append(e.conjuncts, adt.MakeConjunct(env, x))
+ e.conjuncts = append(e.conjuncts, adt.MakeRootConjunct(env, x))
c.fields[x.Label] = e
case *adt.OptionalField:
e := c.fields[x.Label]
- e.conjuncts = append(e.conjuncts, adt.MakeConjunct(env, x))
+ e.conjuncts = append(e.conjuncts, adt.MakeRootConjunct(env, x))
c.fields[x.Label] = e
c.hasOptional = true
diff --git a/pkg/internal/builtin.go b/pkg/internal/builtin.go
index 167bbec..ac69222 100644
--- a/pkg/internal/builtin.go
+++ b/pkg/internal/builtin.go
@@ -64,7 +64,7 @@
pkgLabel := ctx.StringLabel(pkgName)
st := &adt.StructLit{}
if len(p.Native) > 0 {
- obj.AddConjunct(adt.MakeConjunct(nil, st))
+ obj.AddConjunct(adt.MakeRootConjunct(nil, st))
}
for _, b := range p.Native {
b.Pkg = pkgLabel