github.com/google/skylark@v0.0.0-20181101142754-a5f7082aabed/resolve/resolve.go (about) 1 // Copyright 2017 The Bazel Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package resolve defines a name-resolution pass for Skylark abstract 6 // syntax trees. 7 // 8 // The resolver sets the Locals and FreeVars arrays of each DefStmt and 9 // the LocalIndex field of each syntax.Ident that refers to a local or 10 // free variable. It also sets the Locals array of a File for locals 11 // bound by comprehensions outside any function. Identifiers for global 12 // variables do not get an index. 13 package resolve 14 15 // All references to names are statically resolved. Names may be 16 // predeclared, global, or local to a function or module-level comprehension. 17 // The resolver maps each global name to a small integer and each local 18 // name to a small integer; these integers enable a fast and compact 19 // representation of globals and locals in the evaluator. 20 // 21 // As an optimization, the resolver classifies each predeclared name as 22 // either universal (e.g. None, len) or per-module (e.g. glob in Bazel's 23 // build language), enabling the evaluator to share the representation 24 // of the universal environment across all modules. 25 // 26 // The lexical environment is a tree of blocks with the module block at 27 // its root. The module's child blocks may be of two kinds: functions 28 // and comprehensions, and these may have further children of either 29 // kind. 30 // 31 // Python-style resolution requires multiple passes because a name is 32 // determined to be local to a function only if the function contains a 33 // "binding" use of it; similarly, a name is determined be global (as 34 // opposed to predeclared) if the module contains a binding use at the 35 // top level. For both locals and globals, a non-binding use may 36 // lexically precede the binding to which it is resolved. 37 // In the first pass, we inspect each function, recording in 38 // 'uses' each identifier and the environment block in which it occurs. 39 // If a use of a name is binding, such as a function parameter or 40 // assignment, we add the name to the block's bindings mapping and add a 41 // local variable to the enclosing function. 42 // 43 // As we finish resolving each function, we inspect all the uses within 44 // that function and discard ones that were found to be local. The 45 // remaining ones must be either free (local to some lexically enclosing 46 // function), or nonlocal (global or predeclared), but we cannot tell 47 // which until we have finished inspecting the outermost enclosing 48 // function. At that point, we can distinguish local from global names 49 // (and this is when Python would compute free variables). 50 // 51 // However, Skylark additionally requires that all references to global 52 // names are satisfied by some declaration in the current module; 53 // Skylark permits a function to forward-reference a global that has not 54 // been declared yet so long as it is declared before the end of the 55 // module. So, instead of re-resolving the unresolved references after 56 // each top-level function, we defer this until the end of the module 57 // and ensure that all such references are satisfied by some definition. 58 // 59 // At the end of the module, we visit each of the nested function blocks 60 // in bottom-up order, doing a recursive lexical lookup for each 61 // unresolved name. If the name is found to be local to some enclosing 62 // function, we must create a DefStmt.FreeVar (capture) parameter for 63 // each intervening function. We enter these synthetic bindings into 64 // the bindings map so that we create at most one freevar per name. If 65 // the name was not local, we check that it was defined at module level. 66 // 67 // We resolve all uses of locals in the module (due to comprehensions) 68 // in a similar way and compute the set of its local variables. 69 // 70 // Skylark enforces that all global names are assigned at most once on 71 // all control flow paths by forbidding if/else statements and loops at 72 // top level. A global may be used before it is defined, leading to a 73 // dynamic error. 74 // 75 // TODO(adonovan): opt: reuse local slots once locals go out of scope. 76 77 import ( 78 "fmt" 79 "log" 80 "strings" 81 82 "github.com/google/skylark/syntax" 83 ) 84 85 const debug = false 86 const doesnt = "this Skylark dialect does not " 87 88 // global options 89 // These features are either not standard Skylark (yet), or deprecated 90 // features of the BUILD language, so we put them behind flags. 91 var ( 92 AllowNestedDef = false // allow def statements within function bodies 93 AllowLambda = false // allow lambda expressions 94 AllowFloat = false // allow floating point literals, the 'float' built-in, and x / y 95 AllowSet = false // allow the 'set' built-in 96 AllowGlobalReassign = false // allow reassignment to globals declared in same file (deprecated) 97 AllowBitwise = false // allow bitwise operations (&, |, ^, ~, <<, and >>) 98 ) 99 100 // File resolves the specified file. 101 // 102 // The isPredeclared and isUniversal predicates report whether a name is 103 // a pre-declared identifier (visible in the current module) or a 104 // universal identifier (visible in every module). 105 // Clients should typically pass predeclared.Has for the first and 106 // skylark.Universe.Has for the second, where predeclared is the 107 // module's StringDict of predeclared names and skylark.Universe is the 108 // standard set of built-ins. 109 // The isUniverse predicate is supplied a parameter to avoid a cyclic 110 // dependency upon skylark.Universe, not because users should ever need 111 // to redefine it. 112 func File(file *syntax.File, isPredeclared, isUniversal func(name string) bool) error { 113 r := newResolver(isPredeclared, isUniversal) 114 r.stmts(file.Stmts) 115 116 r.env.resolveLocalUses() 117 118 // At the end of the module, resolve all non-local variable references, 119 // computing closures. 120 // Function bodies may contain forward references to later global declarations. 121 r.resolveNonLocalUses(r.env) 122 123 file.Locals = r.moduleLocals 124 file.Globals = r.moduleGlobals 125 126 if len(r.errors) > 0 { 127 return r.errors 128 } 129 return nil 130 } 131 132 // Expr resolves the specified expression. 133 // It returns the local variables bound within the expression. 134 // 135 // The isPredeclared and isUniversal predicates behave as for the File function. 136 func Expr(expr syntax.Expr, isPredeclared, isUniversal func(name string) bool) ([]*syntax.Ident, error) { 137 r := newResolver(isPredeclared, isUniversal) 138 r.expr(expr) 139 r.env.resolveLocalUses() 140 r.resolveNonLocalUses(r.env) // globals & universals 141 if len(r.errors) > 0 { 142 return nil, r.errors 143 } 144 return r.moduleLocals, nil 145 } 146 147 // An ErrorList is a non-empty list of resolver error messages. 148 type ErrorList []Error // len > 0 149 150 func (e ErrorList) Error() string { return e[0].Error() } 151 152 // An Error describes the nature and position of a resolver error. 153 type Error struct { 154 Pos syntax.Position 155 Msg string 156 } 157 158 func (e Error) Error() string { return e.Pos.String() + ": " + e.Msg } 159 160 // The Scope of a syntax.Ident indicates what kind of scope it has. 161 type Scope uint8 162 163 const ( 164 Undefined Scope = iota // name is not defined 165 Local // name is local to its function 166 Free // name is local to some enclosing function 167 Global // name is global to module 168 Predeclared // name is predeclared for this module (e.g. glob) 169 Universal // name is universal (e.g. len) 170 ) 171 172 var scopeNames = [...]string{ 173 Undefined: "undefined", 174 Local: "local", 175 Free: "free", 176 Global: "global", 177 Predeclared: "predeclared", 178 Universal: "universal", 179 } 180 181 func (scope Scope) String() string { return scopeNames[scope] } 182 183 func newResolver(isPredeclared, isUniversal func(name string) bool) *resolver { 184 return &resolver{ 185 env: new(block), // module block 186 isPredeclared: isPredeclared, 187 isUniversal: isUniversal, 188 globals: make(map[string]*syntax.Ident), 189 } 190 } 191 192 type resolver struct { 193 // env is the current local environment: 194 // a linked list of blocks, innermost first. 195 // The tail of the list is the module block. 196 env *block 197 198 // moduleLocals contains the local variables of the module 199 // (due to comprehensions outside any function). 200 // moduleGlobals contains the global variables of the module. 201 moduleLocals []*syntax.Ident 202 moduleGlobals []*syntax.Ident 203 204 // globals maps each global name in the module 205 // to its first binding occurrence. 206 globals map[string]*syntax.Ident 207 208 // These predicates report whether a name is 209 // pre-declared, either in this module or universally. 210 isPredeclared, isUniversal func(name string) bool 211 212 loops int // number of enclosing for loops 213 214 errors ErrorList 215 } 216 217 // container returns the innermost enclosing "container" block: 218 // a function (function != nil) or module (function == nil). 219 // Container blocks accumulate local variable bindings. 220 func (r *resolver) container() *block { 221 for b := r.env; ; b = b.parent { 222 if b.function != nil || b.isModule() { 223 return b 224 } 225 } 226 } 227 228 func (r *resolver) push(b *block) { 229 r.env.children = append(r.env.children, b) 230 b.parent = r.env 231 r.env = b 232 } 233 234 func (r *resolver) pop() { r.env = r.env.parent } 235 236 type block struct { 237 parent *block // nil for module block 238 239 // In the module (root) block, both these fields are nil. 240 function *syntax.Function // only for function blocks 241 comp *syntax.Comprehension // only for comprehension blocks 242 243 // bindings maps a name to its binding. 244 // A local binding has an index into its innermost enclosing container's locals array. 245 // A free binding has an index into its innermost enclosing function's freevars array. 246 bindings map[string]binding 247 248 // children records the child blocks of the current one. 249 children []*block 250 251 // uses records all identifiers seen in this container (function or module), 252 // and a reference to the environment in which they appear. 253 // As we leave each container block, we resolve them, 254 // so that only free and global ones remain. 255 // At the end of each top-level function we compute closures. 256 uses []use 257 } 258 259 type binding struct { 260 scope Scope 261 index int 262 } 263 264 func (b *block) isModule() bool { return b.parent == nil } 265 266 func (b *block) bind(name string, bind binding) { 267 if b.bindings == nil { 268 b.bindings = make(map[string]binding) 269 } 270 b.bindings[name] = bind 271 } 272 273 func (b *block) String() string { 274 if b.function != nil { 275 return "function block at " + fmt.Sprint(b.function.Span()) 276 } 277 if b.comp != nil { 278 return "comprehension block at " + fmt.Sprint(b.comp.Span()) 279 } 280 return "module block" 281 } 282 283 func (r *resolver) errorf(posn syntax.Position, format string, args ...interface{}) { 284 r.errors = append(r.errors, Error{posn, fmt.Sprintf(format, args...)}) 285 } 286 287 // A use records an identifier and the environment in which it appears. 288 type use struct { 289 id *syntax.Ident 290 env *block 291 } 292 293 // bind creates a binding for id in the current block, 294 // if there is not one already, and reports an error if 295 // a global was re-bound and allowRebind is false. 296 // It returns whether a binding already existed. 297 func (r *resolver) bind(id *syntax.Ident, allowRebind bool) bool { 298 // Binding outside any local (comprehension/function) block? 299 if r.env.isModule() { 300 id.Scope = uint8(Global) 301 prev, ok := r.globals[id.Name] 302 if ok { 303 // Global reassignments are permitted only if 304 // they are of the form x += y. We can't tell 305 // statically whether it's a reassignment 306 // (e.g. int += int) or a mutation (list += list). 307 if !allowRebind && !AllowGlobalReassign { 308 r.errorf(id.NamePos, "cannot reassign global %s declared at %s", id.Name, prev.NamePos) 309 } 310 id.Index = prev.Index 311 } else { 312 // first global binding of this name 313 r.globals[id.Name] = id 314 id.Index = len(r.moduleGlobals) 315 r.moduleGlobals = append(r.moduleGlobals, id) 316 } 317 return ok 318 } 319 320 // Mark this name as local to current block. 321 // Assign it a new local (positive) index in the current container. 322 _, ok := r.env.bindings[id.Name] 323 if !ok { 324 var locals *[]*syntax.Ident 325 if fn := r.container().function; fn != nil { 326 locals = &fn.Locals 327 } else { 328 locals = &r.moduleLocals 329 } 330 r.env.bind(id.Name, binding{Local, len(*locals)}) 331 *locals = append(*locals, id) 332 } 333 334 r.use(id) 335 return ok 336 } 337 338 func (r *resolver) use(id *syntax.Ident) { 339 b := r.container() 340 b.uses = append(b.uses, use{id, r.env}) 341 } 342 343 func (r *resolver) useGlobal(id *syntax.Ident) binding { 344 var scope Scope 345 if prev, ok := r.globals[id.Name]; ok { 346 scope = Global // use of global declared by module 347 id.Index = prev.Index 348 } else if r.isPredeclared(id.Name) { 349 scope = Predeclared // use of pre-declared 350 } else if r.isUniversal(id.Name) { 351 scope = Universal // use of universal name 352 if !AllowFloat && id.Name == "float" { 353 r.errorf(id.NamePos, doesnt+"support floating point") 354 } 355 if !AllowSet && id.Name == "set" { 356 r.errorf(id.NamePos, doesnt+"support sets") 357 } 358 } else { 359 scope = Undefined 360 r.errorf(id.NamePos, "undefined: %s", id.Name) 361 } 362 id.Scope = uint8(scope) 363 return binding{scope, id.Index} 364 } 365 366 // resolveLocalUses is called when leaving a container (function/module) 367 // block. It resolves all uses of locals within that block. 368 func (b *block) resolveLocalUses() { 369 unresolved := b.uses[:0] 370 for _, use := range b.uses { 371 if bind := lookupLocal(use); bind.scope == Local { 372 use.id.Scope = uint8(bind.scope) 373 use.id.Index = bind.index 374 } else { 375 unresolved = append(unresolved, use) 376 } 377 } 378 b.uses = unresolved 379 } 380 381 func (r *resolver) stmts(stmts []syntax.Stmt) { 382 for _, stmt := range stmts { 383 r.stmt(stmt) 384 } 385 } 386 387 func (r *resolver) stmt(stmt syntax.Stmt) { 388 switch stmt := stmt.(type) { 389 case *syntax.ExprStmt: 390 r.expr(stmt.X) 391 392 case *syntax.BranchStmt: 393 if r.loops == 0 && (stmt.Token == syntax.BREAK || stmt.Token == syntax.CONTINUE) { 394 r.errorf(stmt.TokenPos, "%s not in a loop", stmt.Token) 395 } 396 397 case *syntax.IfStmt: 398 if r.container().function == nil { 399 r.errorf(stmt.If, "if statement not within a function") 400 } 401 r.expr(stmt.Cond) 402 r.stmts(stmt.True) 403 r.stmts(stmt.False) 404 405 case *syntax.AssignStmt: 406 if !AllowBitwise { 407 switch stmt.Op { 408 case syntax.AMP_EQ, syntax.PIPE_EQ, syntax.CIRCUMFLEX_EQ, syntax.LTLT_EQ, syntax.GTGT_EQ: 409 r.errorf(stmt.OpPos, doesnt+"support bitwise operations") 410 } 411 } 412 r.expr(stmt.RHS) 413 // x += y may be a re-binding of a global variable, 414 // but we cannot tell without knowing the type of x. 415 // (If x is a list it's equivalent to x.extend(y).) 416 // The use is conservatively treated as binding, 417 // but we suppress the error if it's an already-bound global. 418 isAugmented := stmt.Op != syntax.EQ 419 r.assign(stmt.LHS, isAugmented) 420 421 case *syntax.DefStmt: 422 if !AllowNestedDef && r.container().function != nil { 423 r.errorf(stmt.Def, doesnt+"support nested def") 424 } 425 const allowRebind = false 426 r.bind(stmt.Name, allowRebind) 427 r.function(stmt.Def, stmt.Name.Name, &stmt.Function) 428 429 case *syntax.ForStmt: 430 if r.container().function == nil { 431 r.errorf(stmt.For, "for loop not within a function") 432 } 433 r.expr(stmt.X) 434 const allowRebind = false 435 r.assign(stmt.Vars, allowRebind) 436 r.loops++ 437 r.stmts(stmt.Body) 438 r.loops-- 439 440 case *syntax.ReturnStmt: 441 if r.container().function == nil { 442 r.errorf(stmt.Return, "return statement not within a function") 443 } 444 if stmt.Result != nil { 445 r.expr(stmt.Result) 446 } 447 448 case *syntax.LoadStmt: 449 if r.container().function != nil { 450 r.errorf(stmt.Load, "load statement within a function") 451 } 452 453 const allowRebind = false 454 for i, from := range stmt.From { 455 if from.Name == "" { 456 r.errorf(from.NamePos, "load: empty identifier") 457 continue 458 } 459 if from.Name[0] == '_' { 460 r.errorf(from.NamePos, "load: names with leading underscores are not exported: %s", from.Name) 461 } 462 r.bind(stmt.To[i], allowRebind) 463 } 464 465 default: 466 log.Fatalf("unexpected stmt %T", stmt) 467 } 468 } 469 470 func (r *resolver) assign(lhs syntax.Expr, isAugmented bool) { 471 switch lhs := lhs.(type) { 472 case *syntax.Ident: 473 // x = ... 474 allowRebind := isAugmented 475 r.bind(lhs, allowRebind) 476 477 case *syntax.IndexExpr: 478 // x[i] = ... 479 r.expr(lhs.X) 480 r.expr(lhs.Y) 481 482 case *syntax.DotExpr: 483 // x.f = ... 484 r.expr(lhs.X) 485 486 case *syntax.TupleExpr: 487 // (x, y) = ... 488 if len(lhs.List) == 0 { 489 r.errorf(syntax.Start(lhs), "can't assign to ()") 490 } 491 if isAugmented { 492 r.errorf(syntax.Start(lhs), "can't use tuple expression in augmented assignment") 493 } 494 for _, elem := range lhs.List { 495 r.assign(elem, isAugmented) 496 } 497 498 case *syntax.ListExpr: 499 // [x, y, z] = ... 500 if len(lhs.List) == 0 { 501 r.errorf(syntax.Start(lhs), "can't assign to []") 502 } 503 if isAugmented { 504 r.errorf(syntax.Start(lhs), "can't use list expression in augmented assignment") 505 } 506 for _, elem := range lhs.List { 507 r.assign(elem, isAugmented) 508 } 509 510 case *syntax.ParenExpr: 511 r.assign(lhs.X, isAugmented) 512 513 default: 514 name := strings.ToLower(strings.TrimPrefix(fmt.Sprintf("%T", lhs), "*syntax.")) 515 r.errorf(syntax.Start(lhs), "can't assign to %s", name) 516 } 517 } 518 519 func (r *resolver) expr(e syntax.Expr) { 520 switch e := e.(type) { 521 case *syntax.Ident: 522 r.use(e) 523 524 case *syntax.Literal: 525 if !AllowFloat && e.Token == syntax.FLOAT { 526 r.errorf(e.TokenPos, doesnt+"support floating point") 527 } 528 529 case *syntax.ListExpr: 530 for _, x := range e.List { 531 r.expr(x) 532 } 533 534 case *syntax.CondExpr: 535 r.expr(e.Cond) 536 r.expr(e.True) 537 r.expr(e.False) 538 539 case *syntax.IndexExpr: 540 r.expr(e.X) 541 r.expr(e.Y) 542 543 case *syntax.DictEntry: 544 r.expr(e.Key) 545 r.expr(e.Value) 546 547 case *syntax.SliceExpr: 548 r.expr(e.X) 549 if e.Lo != nil { 550 r.expr(e.Lo) 551 } 552 if e.Hi != nil { 553 r.expr(e.Hi) 554 } 555 if e.Step != nil { 556 r.expr(e.Step) 557 } 558 559 case *syntax.Comprehension: 560 // The 'in' operand of the first clause (always a ForClause) 561 // is resolved in the outer block; consider: [x for x in x]. 562 clause := e.Clauses[0].(*syntax.ForClause) 563 r.expr(clause.X) 564 565 // A list/dict comprehension defines a new lexical block. 566 // Locals defined within the block will be allotted 567 // distinct slots in the locals array of the innermost 568 // enclosing container (function/module) block. 569 r.push(&block{comp: e}) 570 571 const allowRebind = false 572 r.assign(clause.Vars, allowRebind) 573 574 for _, clause := range e.Clauses[1:] { 575 switch clause := clause.(type) { 576 case *syntax.IfClause: 577 r.expr(clause.Cond) 578 case *syntax.ForClause: 579 r.assign(clause.Vars, allowRebind) 580 r.expr(clause.X) 581 } 582 } 583 r.expr(e.Body) // body may be *DictEntry 584 r.pop() 585 586 case *syntax.TupleExpr: 587 for _, x := range e.List { 588 r.expr(x) 589 } 590 591 case *syntax.DictExpr: 592 for _, entry := range e.List { 593 entry := entry.(*syntax.DictEntry) 594 r.expr(entry.Key) 595 r.expr(entry.Value) 596 } 597 598 case *syntax.UnaryExpr: 599 if !AllowBitwise && e.Op == syntax.TILDE { 600 r.errorf(e.OpPos, doesnt+"support bitwise operations") 601 } 602 r.expr(e.X) 603 604 case *syntax.BinaryExpr: 605 if !AllowFloat && e.Op == syntax.SLASH { 606 r.errorf(e.OpPos, doesnt+"support floating point (use //)") 607 } 608 if !AllowBitwise { 609 switch e.Op { 610 case syntax.AMP, syntax.PIPE, syntax.CIRCUMFLEX, syntax.LTLT, syntax.GTGT: 611 r.errorf(e.OpPos, doesnt+"support bitwise operations") 612 } 613 } 614 r.expr(e.X) 615 r.expr(e.Y) 616 617 case *syntax.DotExpr: 618 r.expr(e.X) 619 // ignore e.Name 620 621 case *syntax.CallExpr: 622 r.expr(e.Fn) 623 var seenVarargs, seenKwargs, seenNamed bool 624 for _, arg := range e.Args { 625 pos, _ := arg.Span() 626 if unop, ok := arg.(*syntax.UnaryExpr); ok && unop.Op == syntax.STARSTAR { 627 // **kwargs 628 if seenKwargs { 629 r.errorf(pos, "multiple **kwargs not allowed") 630 } 631 seenKwargs = true 632 r.expr(arg) 633 } else if ok && unop.Op == syntax.STAR { 634 // *args 635 if seenKwargs { 636 r.errorf(pos, "*args may not follow **kwargs") 637 } else if seenVarargs { 638 r.errorf(pos, "multiple *args not allowed") 639 } 640 seenVarargs = true 641 r.expr(arg) 642 } else if binop, ok := arg.(*syntax.BinaryExpr); ok && binop.Op == syntax.EQ { 643 // k=v 644 if seenKwargs { 645 r.errorf(pos, "argument may not follow **kwargs") 646 } 647 // ignore binop.X 648 r.expr(binop.Y) 649 seenNamed = true 650 } else { 651 // positional argument 652 if seenVarargs { 653 r.errorf(pos, "argument may not follow *args") 654 } else if seenKwargs { 655 r.errorf(pos, "argument may not follow **kwargs") 656 } else if seenNamed { 657 r.errorf(pos, "positional argument may not follow named") 658 } 659 r.expr(arg) 660 } 661 } 662 663 case *syntax.LambdaExpr: 664 if !AllowLambda { 665 r.errorf(e.Lambda, doesnt+"support lambda") 666 } 667 r.function(e.Lambda, "lambda", &e.Function) 668 669 case *syntax.ParenExpr: 670 r.expr(e.X) 671 672 default: 673 log.Fatalf("unexpected expr %T", e) 674 } 675 } 676 677 func (r *resolver) function(pos syntax.Position, name string, function *syntax.Function) { 678 // Resolve defaults in enclosing environment. 679 for _, param := range function.Params { 680 if binary, ok := param.(*syntax.BinaryExpr); ok { 681 r.expr(binary.Y) 682 } 683 } 684 685 // Enter function block. 686 b := &block{function: function} 687 r.push(b) 688 689 const allowRebind = false 690 var seenVarargs, seenKwargs, seenOptional bool 691 for _, param := range function.Params { 692 switch param := param.(type) { 693 case *syntax.Ident: 694 // e.g. x 695 if seenKwargs { 696 r.errorf(pos, "parameter may not follow **kwargs") 697 } else if seenVarargs { 698 r.errorf(pos, "parameter may not follow *args") 699 } else if seenOptional { 700 r.errorf(pos, "required parameter may not follow optional") 701 } 702 if r.bind(param, allowRebind) { 703 r.errorf(pos, "duplicate parameter: %s", param.Name) 704 } 705 706 case *syntax.BinaryExpr: 707 // e.g. y=dflt 708 if seenKwargs { 709 r.errorf(pos, "parameter may not follow **kwargs") 710 } else if seenVarargs { 711 r.errorf(pos, "parameter may not follow *args") 712 } 713 if id := param.X.(*syntax.Ident); r.bind(id, allowRebind) { 714 r.errorf(pos, "duplicate parameter: %s", id.Name) 715 } 716 seenOptional = true 717 718 case *syntax.UnaryExpr: 719 // *args or **kwargs 720 if param.Op == syntax.STAR { 721 if seenKwargs { 722 r.errorf(pos, "*args may not follow **kwargs") 723 } else if seenVarargs { 724 r.errorf(pos, "multiple *args not allowed") 725 } 726 seenVarargs = true 727 } else { 728 if seenKwargs { 729 r.errorf(pos, "multiple **kwargs not allowed") 730 } 731 seenKwargs = true 732 } 733 if id := param.X.(*syntax.Ident); r.bind(id, allowRebind) { 734 r.errorf(pos, "duplicate parameter: %s", id.Name) 735 } 736 } 737 } 738 function.HasVarargs = seenVarargs 739 function.HasKwargs = seenKwargs 740 r.stmts(function.Body) 741 742 // Resolve all uses of this function's local vars, 743 // and keep just the remaining uses of free/global vars. 744 b.resolveLocalUses() 745 746 // Leave function block. 747 r.pop() 748 749 // References within the function body to globals are not 750 // resolved until the end of the module. 751 } 752 753 func (r *resolver) resolveNonLocalUses(b *block) { 754 // First resolve inner blocks. 755 for _, child := range b.children { 756 r.resolveNonLocalUses(child) 757 } 758 for _, use := range b.uses { 759 bind := r.lookupLexical(use.id, use.env) 760 use.id.Scope = uint8(bind.scope) 761 use.id.Index = bind.index 762 } 763 } 764 765 // lookupLocal looks up an identifier within its immediately enclosing function. 766 func lookupLocal(use use) binding { 767 for env := use.env; env != nil; env = env.parent { 768 if bind, ok := env.bindings[use.id.Name]; ok { 769 if bind.scope == Free { 770 // shouldn't exist till later 771 log.Fatalf("%s: internal error: %s, %d", use.id.NamePos, use.id.Name, bind) 772 } 773 return bind // found 774 } 775 if env.function != nil { 776 break 777 } 778 } 779 return binding{} // not found in this function 780 } 781 782 // lookupLexical looks up an identifier within its lexically enclosing environment. 783 func (r *resolver) lookupLexical(id *syntax.Ident, env *block) (bind binding) { 784 if debug { 785 fmt.Printf("lookupLexical %s in %s = ...\n", id.Name, env) 786 defer func() { fmt.Printf("= %d\n", bind) }() 787 } 788 789 // Is this the module block? 790 if env.isModule() { 791 return r.useGlobal(id) // global, predeclared, or not found 792 } 793 794 // Defined in this block? 795 bind, ok := env.bindings[id.Name] 796 if !ok { 797 // Defined in parent block? 798 bind = r.lookupLexical(id, env.parent) 799 if env.function != nil && (bind.scope == Local || bind.scope == Free) { 800 // Found in parent block, which belongs to enclosing function. 801 id := &syntax.Ident{ 802 Name: id.Name, 803 Scope: uint8(bind.scope), 804 Index: bind.index, 805 } 806 bind.scope = Free 807 bind.index = len(env.function.FreeVars) 808 env.function.FreeVars = append(env.function.FreeVars, id) 809 if debug { 810 fmt.Printf("creating freevar %v in function at %s: %s\n", 811 len(env.function.FreeVars), fmt.Sprint(env.function.Span()), id.Name) 812 } 813 } 814 815 // Memoize, to avoid duplicate free vars 816 // and redundant global (failing) lookups. 817 env.bind(id.Name, bind) 818 } 819 return bind 820 }