aboutsummaryrefslogtreecommitdiff
path: root/resolve
diff options
context:
space:
mode:
authoralandonovan <adonovan@google.com>2017-10-11 13:04:47 -0400
committerGitHub <noreply@github.com>2017-10-11 13:04:47 -0400
commit631f7b543a37d302fcfc62793b6e756faa6b34bb (patch)
tree56401b712a19a92485d64204f5ebb3f72c3a6189 /resolve
parent13998aa7464402849172959d67ded8527c7d9370 (diff)
downloadstarlark-go-631f7b543a37d302fcfc62793b6e756faa6b34bb.tar.gz
resolve: clarify is{PredeclaredGlobal,Builtin} parameters (#11)
* resolve: clarify is{PredeclaredGlobal,Builtin} parameters - document these parameters - rename isBuiltin to isUniversal to avoid overloading 'builtin' (as in functions) - export StringDict.Has method, and simplify. Change-Id: I3b9396b879be960c08c3200fe1f6a2ac683d66e0 * resolve: fix typo Change-Id: Id5b88f5dcf55ed4733b74990419ef7cfcacfae2c
Diffstat (limited to 'resolve')
-rw-r--r--resolve/resolve.go44
-rw-r--r--resolve/resolve_test.go8
2 files changed, 32 insertions, 20 deletions
diff --git a/resolve/resolve.go b/resolve/resolve.go
index 9ccf482..d0c818a 100644
--- a/resolve/resolve.go
+++ b/resolve/resolve.go
@@ -13,7 +13,7 @@
package resolve
// All references to names are statically resolved. Names may be
-// built-in (e.g. None, len), global and predeclared (e.g. glob in the
+// universal (e.g. None, len), global and predeclared (e.g. glob in the
// build language), global and user-defined (e.g. x=1 at toplevel), or
// local to a function or module-level comprehension. The resolver maps
// each local name to a small integer for fast and compact
@@ -36,7 +36,7 @@ package resolve
// As we finish resolving each function, we inspect all the uses within
// that function and discard ones that were found to be local. The
// remaining ones must be either free (local to some lexically enclosing
-// function) or global/built-in, but we cannot tell which until we have
+// function) or global/universal, but we cannot tell which until we have
// finished inspecting the outermost enclosing function. At that point,
// we can distinguish local from global names (and this is when Python
// would compute free variables).
@@ -90,8 +90,14 @@ var (
)
// File resolves the specified file.
-func File(file *syntax.File, isPredeclaredGlobal, isBuiltin func(name string) bool) error {
- r := newResolver(isPredeclaredGlobal, isBuiltin)
+//
+// The isPredeclaredGlobal and isUniversal predicates report whether a
+// name is a pre-declared global identifier (in the current module) or a
+// universal identifier (in every module).
+// Typical values are globals.Has and Universe.Has, respectively, where
+// globals is the current module's StringDict.
+func File(file *syntax.File, isPredeclaredGlobal, isUniversal func(name string) bool) error {
+ r := newResolver(isPredeclaredGlobal, isUniversal)
r.stmts(file.Stmts)
r.env.resolveLocalUses()
@@ -111,11 +117,17 @@ func File(file *syntax.File, isPredeclaredGlobal, isBuiltin func(name string) bo
// Expr resolves the specified expression.
// It returns the local variables bound within the expression.
-func Expr(expr syntax.Expr, isPredeclaredGlobal, isBuiltin func(name string) bool) ([]*syntax.Ident, error) {
- r := newResolver(isPredeclaredGlobal, isBuiltin)
+//
+// The isPredeclaredGlobal and isUniversal predicates report whether a
+// name is a pre-declared global identifier (in the current module) or a
+// universal identifier (in every module).
+// Typical values are globals.Has and Universe.Has, respectively, where
+// globals is the current module's StringDict.
+func Expr(expr syntax.Expr, isPredeclaredGlobal, isUniversal func(name string) bool) ([]*syntax.Ident, error) {
+ r := newResolver(isPredeclaredGlobal, isUniversal)
r.expr(expr)
r.env.resolveLocalUses()
- r.resolveNonLocalUses(r.env) // globals & builtins
+ r.resolveNonLocalUses(r.env) // globals & universals
if len(r.errors) > 0 {
return nil, r.errors
}
@@ -143,7 +155,7 @@ const (
Local // name is local to its function
Free // name is local to some enclosing function
Global // name is global to module
- Builtin // name is universal (e.g. len)
+ Universal // name is universal (e.g. len)
)
var scopeNames = [...]string{
@@ -151,16 +163,16 @@ var scopeNames = [...]string{
Local: "local",
Free: "free",
Global: "global",
- Builtin: "builtin",
+ Universal: "universal",
}
func (scope Scope) String() string { return scopeNames[scope] }
-func newResolver(isPredeclaredGlobal, isBuiltin func(name string) bool) *resolver {
+func newResolver(isPredeclaredGlobal, isUniversal func(name string) bool) *resolver {
return &resolver{
env: new(block), // module block
isPredeclaredGlobal: isPredeclaredGlobal,
- isBuiltin: isBuiltin,
+ isUniversal: isUniversal,
globals: make(map[string]syntax.Position),
}
}
@@ -181,8 +193,8 @@ type resolver struct {
globals map[string]syntax.Position
// These predicates report whether a name is
- // a pre-declared global or built-in.
- isPredeclaredGlobal, isBuiltin func(name string) bool
+ // a pre-declared global or universal.
+ isPredeclaredGlobal, isUniversal func(name string) bool
loops int // number of enclosing for loops
@@ -326,8 +338,8 @@ func (r *resolver) useGlobal(id *syntax.Ident) (scope Scope) {
scope = Global // use of pre-declared global
} else if id.Name == "PACKAGE_NAME" {
scope = Global // nasty hack in Skylark spec; will go away (b/34240042).
- } else if r.isBuiltin(id.Name) {
- scope = Builtin // use of built-in
+ } else if r.isUniversal(id.Name) {
+ scope = Universal // use of universal name
if !AllowFloat && id.Name == "float" {
r.errorf(id.NamePos, doesnt+"support floating point")
}
@@ -737,7 +749,7 @@ func (r *resolver) lookupLexical(id *syntax.Ident, env *block) (bind binding) {
// Is this the module block?
if env.isModule() {
- return binding{r.useGlobal(id), 0} // global or builtin, or not found
+ return binding{r.useGlobal(id), 0} // global or universal, or not found
}
// Defined in this block?
diff --git a/resolve/resolve_test.go b/resolve/resolve_test.go
index 6223515..11e953c 100644
--- a/resolve/resolve_test.go
+++ b/resolve/resolve_test.go
@@ -31,7 +31,7 @@ func TestResolve(t *testing.T) {
resolve.AllowSet = option(chunk.Source, "set")
resolve.AllowGlobalReassign = option(chunk.Source, "global_reassign")
- if err := resolve.File(f, isPredeclaredGlobal, isBuiltin); err != nil {
+ if err := resolve.File(f, isPredeclaredGlobal, isUniversal); err != nil {
for _, err := range err.(resolve.ErrorList) {
chunk.GotError(int(err.Pos.Line), err.Msg)
}
@@ -50,7 +50,7 @@ func TestDefVarargsAndKwargsSet(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- if err := resolve.File(file, isPredeclaredGlobal, isBuiltin); err != nil {
+ if err := resolve.File(file, isPredeclaredGlobal, isUniversal); err != nil {
t.Fatal(err)
}
fn := file.Stmts[0].(*syntax.DefStmt)
@@ -69,7 +69,7 @@ func TestLambdaVarargsAndKwargsSet(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- if err := resolve.File(file, isPredeclaredGlobal, isBuiltin); err != nil {
+ if err := resolve.File(file, isPredeclaredGlobal, isUniversal); err != nil {
t.Fatal(err)
}
lam := file.Stmts[0].(*syntax.AssignStmt).RHS.(*syntax.LambdaExpr)
@@ -82,6 +82,6 @@ func TestLambdaVarargsAndKwargsSet(t *testing.T) {
}
func isPredeclaredGlobal(name string) bool { return strings.HasPrefix(name, "G") }
-func isBuiltin(name string) bool {
+func isUniversal(name string) bool {
return strings.HasPrefix(name, "B") || name == "float"
}