cue/parser: resolve identifiers for ParseExpr

note that unresolved references are not recorded, as
with ParseFile.

Change-Id: Iac60dd584632ff4535d8609ec2ee25d4e823d88d
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/1781
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
diff --git a/cue/parser/interface.go b/cue/parser/interface.go
index e2bfb82..d921adc 100644
--- a/cue/parser/interface.go
+++ b/cue/parser/interface.go
@@ -223,6 +223,7 @@
 		p.errors.Sort()
 		return nil, p.errors.Err()
 	}
+	resolveExpr(e, p.error)
 
 	return e, nil
 }
diff --git a/cue/parser/parser_test.go b/cue/parser/parser_test.go
index ca6292b..52364d5 100644
--- a/cue/parser/parser_test.go
+++ b/cue/parser/parser_test.go
@@ -395,6 +395,22 @@
 		t.Errorf("ParseExpr(%q): got no error", src)
 	}
 
+	// check resolution
+	src = "{ foo: bar, bar: foo }"
+	x, err = parseExprString(src)
+	if err != nil {
+		t.Fatalf("ParseExpr(%q): %v", src, err)
+	}
+	for _, d := range x.(*ast.StructLit).Elts {
+		v := d.(*ast.Field).Value.(*ast.Ident)
+		if v.Scope == nil {
+			t.Errorf("ParseExpr(%q): scope of field %v not set", src, v.Name)
+		}
+		if v.Node == nil {
+			t.Errorf("ParseExpr(%q): scope of node %v not set", src, v.Name)
+		}
+	}
+
 	// various other stuff following a valid expression
 	const validExpr = "a + b"
 	const anything = "dh3*#D)#_"
diff --git a/cue/parser/resolve.go b/cue/parser/resolve.go
index 98195d9..b7be33d 100644
--- a/cue/parser/resolve.go
+++ b/cue/parser/resolve.go
@@ -30,6 +30,11 @@
 	walk(&scope{errFn: errFn}, f)
 }
 
+func resolveExpr(e ast.Expr, errFn func(pos token.Pos, msg string)) {
+	f := &ast.File{}
+	walk(&scope{file: f, errFn: errFn}, e)
+}
+
 // A Scope maintains the set of named language entities declared
 // in the scope and a link to the immediately surrounding (outer)
 // scope.