Skip to content

Commit

Permalink
internal/core/compile: fix alias resolution bug
Browse files Browse the repository at this point in the history
Fixes #495

Change-Id: Ia8a4b0972e036cd970f921046d5a436f7a8e413e
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7267
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Oct 1, 2020
1 parent 742593f commit d23402c
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 16 deletions.
34 changes: 34 additions & 0 deletions cue/testdata/basicrewrite/aliases/aliases.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-- in.cue --
t0: {
a=_a: _
let _b = a
_out: _b
}
t1: {
_a: b
let b = c
c=d: 3
}
-- out/compile --
--- in.cue
{
t0: {
_a: _
_out: 〈0;let _b〉
}
t1: {
_a: 〈0;let b〉
d: 3
}
}
-- out/eval --
(struct){
t0: (struct){
_a: (_){ _ }
_out: (_){ _ }
}
t1: (struct){
_a: (int){ 3 }
d: (int){ 3 }
}
}
56 changes: 40 additions & 16 deletions internal/core/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ func (c *compiler) insertAlias(id *ast.Ident, a aliasEntry) *adt.Bottom {
return nil
}

func (c *compiler) updateAlias(id *ast.Ident, expr adt.Expr) {
k := len(c.stack) - 1
m := c.stack[k].aliases

x := m[id.Name]
x.expr = expr
m[id.Name] = x
}

// lookupAlias looks up an alias with the given name at the k'th stack position.
func (c compiler) lookupAlias(k int, id *ast.Ident) aliasEntry {
m := c.stack[k].aliases
Expand Down Expand Up @@ -440,6 +449,9 @@ func (c *compiler) resolve(n *ast.Ident) adt.Expr {
}

func (c *compiler) addDecls(st *adt.StructLit, a []ast.Decl) {
for _, d := range a {
c.markAlias(d)
}
for _, d := range a {
c.addLetDecl(d)
}
Expand All @@ -450,6 +462,30 @@ func (c *compiler) addDecls(st *adt.StructLit, a []ast.Decl) {
}
}

func (c *compiler) markAlias(d ast.Decl) {
switch x := d.(type) {
case *ast.Field:
lab := x.Label
if a, ok := lab.(*ast.Alias); ok {
if _, ok = a.Expr.(ast.Label); !ok {
c.errf(a, "alias expression is not a valid label")
}

e := aliasEntry{source: a}

c.insertAlias(a.Ident, e)
}

case *ast.LetClause:
a := aliasEntry{source: x}
c.insertAlias(x.Ident, a)

case *ast.Alias:
a := aliasEntry{source: x}
c.insertAlias(x.Ident, a)
}
}

func (c *compiler) decl(d ast.Decl) adt.Decl {
switch x := d.(type) {
case *ast.BadDecl:
Expand All @@ -462,18 +498,12 @@ func (c *compiler) decl(d ast.Decl) adt.Decl {
return c.errf(a, "alias expression is not a valid label")
}

e := aliasEntry{source: a}

switch lab.(type) {
case *ast.Ident, *ast.BasicLit, *ast.ListLit:
// Even though we won't need the alias, we still register it
// for duplicate and failed reference detection.
default:
e.expr = c.expr(a.Expr)
}

if err := c.insertAlias(a.Ident, e); err != nil {
return err
c.updateAlias(a.Ident, c.expr(a.Expr))
}
}

Expand Down Expand Up @@ -576,19 +606,13 @@ func (c *compiler) addLetDecl(d ast.Decl) {
// blowup in x2: x1+x1, x3: x2+x2, ... patterns.

expr := c.labeledExpr(nil, (*letScope)(x), x.Expr)

a := aliasEntry{source: x, expr: expr}

c.insertAlias(x.Ident, a)
c.updateAlias(x.Ident, expr)

case *ast.Alias:

expr := c.labeledExpr(nil, (*deprecatedAliasScope)(x), x.Expr)

// TODO(legacy): deprecated, remove this use of Alias
a := aliasEntry{source: x, expr: expr}

c.insertAlias(x.Ident, a)
expr := c.labeledExpr(nil, (*deprecatedAliasScope)(x), x.Expr)
c.updateAlias(x.Ident, expr)
}
}

Expand Down

0 comments on commit d23402c

Please sign in to comment.