github.com/goplus/gox@v1.14.13-0.20240308130321-6ff7f61cfae8/type_var_and_const.go (about) 1 /* 2 Copyright 2021 The GoPlus Authors (goplus.org) 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 http://www.apache.org/licenses/LICENSE-2.0 7 Unless required by applicable law or agreed to in writing, software 8 distributed under the License is distributed on an "AS IS" BASIS, 9 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 See the License for the specific language governing permissions and 11 limitations under the License. 12 */ 13 14 package gox 15 16 import ( 17 "go/ast" 18 "go/token" 19 "go/types" 20 "log" 21 "syscall" 22 23 "github.com/goplus/gox/internal" 24 ) 25 26 // ---------------------------------------------------------------------------- 27 28 // ConstStart starts a constant expression. 29 func (p *Package) ConstStart() *CodeBuilder { 30 return &p.cb 31 } 32 33 func (p *CodeBuilder) EndConst() *Element { 34 return p.stk.Pop() 35 } 36 37 // ---------------------------------------------------------------------------- 38 39 // MethodToFunc: 40 // 41 // (T).method 42 // (*T).method 43 func (pkg *Package) MethodToFunc(typ types.Type, name string, src ...ast.Node) (ret *Element, err error) { 44 _, err = pkg.cb.Typ(typ, src...).Member(name, MemberFlagVal, src...) 45 ret = pkg.cb.stk.Pop() 46 return 47 } 48 49 // ---------------------------------------------------------------------------- 50 51 type TyState int 52 53 const ( 54 TyStateUninited TyState = iota 55 TyStateInited 56 TyStateDeleted 57 ) 58 59 // TypeDecl type 60 type TypeDecl struct { 61 typ *types.Named 62 spec *ast.TypeSpec 63 } 64 65 // SetComments sets associated documentation. 66 func (p *TypeDecl) SetComments(pkg *Package, doc *ast.CommentGroup) *TypeDecl { 67 p.spec.Doc = doc 68 pkg.setDoc(p.typ.Obj(), doc) 69 return p 70 } 71 72 // Type returns the type. 73 func (p *TypeDecl) Type() *types.Named { 74 return p.typ 75 } 76 77 // State checkes state of this type. 78 // If Delete is called, it returns TyStateDeleted. 79 // If InitType is called (but not deleted), it returns TyStateInited. 80 // Otherwise it returns TyStateUninited. 81 func (p *TypeDecl) State() TyState { 82 spec := p.spec 83 if spec.Name != nil { 84 if spec.Type != nil { 85 return TyStateInited 86 } 87 return TyStateUninited 88 } 89 return TyStateDeleted 90 } 91 92 // Delete deletes this type. 93 // NOTE: It panics if you call InitType after Delete. 94 func (p *TypeDecl) Delete() { 95 p.spec.Name = nil 96 } 97 98 // Inited checkes if InitType is called or not. 99 // Will panic if this type is deleted (please use State to check). 100 func (p *TypeDecl) Inited() bool { 101 return p.spec.Type != nil 102 } 103 104 // InitType initializes a uncompleted type. 105 func (p *TypeDecl) InitType(pkg *Package, typ types.Type, tparams ...*TypeParam) *types.Named { 106 if debugInstr { 107 log.Println("InitType", p.typ.Obj().Name(), typ) 108 } 109 spec := p.spec 110 if spec.Type != nil { 111 log.Panicln("TODO: type already defined -", typ) 112 } 113 if named, ok := typ.(*types.Named); ok { 114 p.typ.SetUnderlying(pkg.cb.getUnderlying(named)) 115 } else { 116 p.typ.SetUnderlying(typ) 117 } 118 if tparams != nil { 119 setTypeParams(pkg, p.typ, spec, tparams) 120 } 121 spec.Type = toType(pkg, typ) 122 return p.typ 123 } 124 125 // ---------------------------------------------------------------------------- 126 127 // TypeDefs represents a type declaration block. 128 type TypeDefs struct { 129 decl *ast.GenDecl 130 scope *types.Scope 131 pkg *Package 132 } 133 134 // Pkg returns the package instance. 135 func (p *TypeDefs) Pkg() *Package { 136 return p.pkg 137 } 138 139 // SetComments sets associated documentation. 140 func (p *TypeDefs) SetComments(doc *ast.CommentGroup) *TypeDefs { 141 p.decl.Doc = doc 142 return p 143 } 144 145 // NewType creates a new type (which need to call InitType later). 146 func (p *TypeDefs) NewType(name string, src ...ast.Node) *TypeDecl { 147 if debugInstr { 148 log.Println("NewType", name) 149 } 150 return p.pkg.doNewType(p, getPos(src), name, nil, 0) 151 } 152 153 // AliasType gives a specified type with a new name. 154 func (p *TypeDefs) AliasType(name string, typ types.Type, src ...ast.Node) *TypeDecl { 155 if debugInstr { 156 log.Println("AliasType", name, typ) 157 } 158 return p.pkg.doNewType(p, getPos(src), name, typ, 1) 159 } 160 161 // Complete checks type declarations & marks completed. 162 func (p *TypeDefs) Complete() { 163 decl := p.decl 164 specs := decl.Specs 165 if len(specs) == 1 && decl.Doc == nil { 166 if spec := specs[0].(*ast.TypeSpec); spec.Doc != nil { 167 decl.Doc, spec.Doc = spec.Doc, nil 168 } 169 } 170 for i, spec := range specs { 171 v := spec.(*ast.TypeSpec) 172 if v.Name == nil || v.Type == nil { 173 for j := i + 1; j < len(specs); j++ { 174 v = specs[j].(*ast.TypeSpec) 175 if v.Name != nil && v.Type != nil { 176 specs[i] = v 177 i++ 178 } 179 } 180 decl.Specs = specs[:i] 181 return 182 } 183 } 184 } 185 186 // ---------------------------------------------------------------------------- 187 188 // AliasType gives a specified type with a new name. 189 // 190 // Deprecated: use NewTypeDefs instead. 191 func (p *Package) AliasType(name string, typ types.Type, src ...ast.Node) *types.Named { 192 decl := p.NewTypeDefs().AliasType(name, typ, src...) 193 return decl.typ 194 } 195 196 // NewType creates a new type (which need to call InitType later). 197 // 198 // Deprecated: use NewTypeDefs instead. 199 func (p *Package) NewType(name string, src ...ast.Node) *TypeDecl { 200 return p.NewTypeDefs().NewType(name, src...) 201 } 202 203 // NewTypeDefs starts a type declaration block. 204 func (p *Package) NewTypeDefs() *TypeDefs { 205 decl := &ast.GenDecl{Tok: token.TYPE} 206 p.file.decls = append(p.file.decls, decl) 207 return &TypeDefs{decl: decl, scope: p.Types.Scope(), pkg: p} 208 } 209 210 // NewTypeDefs starts a type declaration block. 211 func (p *CodeBuilder) NewTypeDefs() *TypeDefs { 212 ret, defineHere := p.NewTypeDecls() 213 defineHere() 214 return ret 215 } 216 217 // NewTypeDecls starts a type declaration block but delay to define it. 218 func (p *CodeBuilder) NewTypeDecls() (ret *TypeDefs, defineHere func()) { 219 pkg, scope := p.pkg, p.current.scope 220 decl := &ast.GenDecl{Tok: token.TYPE} 221 return &TypeDefs{decl: decl, scope: scope, pkg: pkg}, func() { 222 if scope == pkg.Types.Scope() { 223 pkg.file.decls = append(pkg.file.decls, decl) 224 } else { 225 p.emitStmt(&ast.DeclStmt{Decl: decl}) 226 } 227 } 228 } 229 230 func (p *Package) doNewType(tdecl *TypeDefs, pos token.Pos, name string, typ types.Type, alias token.Pos) *TypeDecl { 231 scope := tdecl.scope 232 typName := types.NewTypeName(pos, p.Types, name, typ) 233 if old := scope.Insert(typName); old != nil { 234 oldPos := p.cb.fset.Position(old.Pos()) 235 p.cb.panicCodeErrorf( 236 pos, "%s redeclared in this block\n\tprevious declaration at %v", name, oldPos) 237 } 238 decl := tdecl.decl 239 spec := &ast.TypeSpec{Name: ident(name), Assign: alias} 240 decl.Specs = append(decl.Specs, spec) 241 if alias != 0 { // alias don't need to call InitType 242 spec.Type = toType(p, typ) 243 typ = typ.Underlying() // typ.Underlying() may delay load and can be nil, it's reasonable 244 } 245 named := types.NewNamed(typName, typ, nil) 246 p.useName(name) 247 return &TypeDecl{typ: named, spec: spec} 248 } 249 250 // ---------------------------------------------------------------------------- 251 252 // ValueDecl type 253 type ValueDecl struct { 254 names []string 255 typ types.Type 256 old codeBlock 257 oldv *ValueDecl 258 scope *types.Scope 259 vals *[]ast.Expr 260 tok token.Token 261 pos token.Pos 262 at int // commitStmt(at) 263 } 264 265 // Inited checkes if `InitStart` is called or not. 266 func (p *ValueDecl) Inited() bool { 267 return p.oldv != nil 268 } 269 270 // InitStart initializes a uninitialized variable or constant. 271 func (p *ValueDecl) InitStart(pkg *Package) *CodeBuilder { 272 p.oldv, pkg.cb.valDecl = pkg.cb.valDecl, p 273 p.old = pkg.cb.startInitExpr(p) 274 return &pkg.cb 275 } 276 277 func (p *ValueDecl) Ref(name string) Ref { 278 return p.scope.Lookup(name) 279 } 280 281 // End is provided for internal usage. 282 // Don't call it at any time. Please use (*CodeBuilder).EndInit instead. 283 func (p *ValueDecl) End(cb *CodeBuilder, src ast.Node) { 284 fatal("don't call End(), please use EndInit() instead") 285 } 286 287 func (p *ValueDecl) resetInit(cb *CodeBuilder) *ValueDecl { 288 cb.endInitExpr(p.old) 289 if p.at >= 0 { 290 cb.commitStmt(p.at) // to support inline call, we must emitStmt at ResetInit stage 291 } 292 return p.oldv 293 } 294 295 func checkTuple(t **types.Tuple, typ types.Type) (ok bool) { 296 *t, ok = typ.(*types.Tuple) 297 return 298 } 299 300 func (p *ValueDecl) endInit(cb *CodeBuilder, arity int) *ValueDecl { 301 var t *types.Tuple 302 var values []ast.Expr 303 n := len(p.names) 304 rets := cb.stk.GetArgs(arity) 305 defer func() { 306 cb.stk.PopN(arity) 307 cb.endInitExpr(p.old) 308 if p.at >= 0 { 309 cb.commitStmt(p.at) // to support inline call, we must emitStmt at EndInit stage 310 } 311 }() 312 if arity == 1 && checkTuple(&t, rets[0].Type) { 313 if n != t.Len() { 314 caller := getCaller(rets[0]) 315 cb.panicCodeErrorf( 316 p.pos, "assignment mismatch: %d variables but %s returns %d values", n, caller, t.Len()) 317 } 318 *p.vals = []ast.Expr{rets[0].Val} 319 rets = make([]*internal.Elem, n) 320 for i := 0; i < n; i++ { 321 rets[i] = &internal.Elem{Type: t.At(i).Type()} 322 } 323 } else if n != arity { 324 if p.tok == token.CONST { 325 if n > arity { 326 cb.panicCodeError(p.pos, "missing value in const declaration") 327 } 328 cb.panicCodeError(p.pos, "extra expression in const declaration") 329 } 330 cb.panicCodeErrorf(p.pos, "assignment mismatch: %d variables but %d values", n, arity) 331 } else { 332 values = make([]ast.Expr, arity) 333 for i, ret := range rets { 334 values[i] = ret.Val 335 } 336 *p.vals = values 337 } 338 pkg, typ := cb.pkg, p.typ 339 if typ != nil { 340 for i, ret := range rets { 341 if err := matchType(pkg, ret, typ, "assignment"); err != nil { 342 panic(err) 343 } 344 if values != nil { // ret.Val may be changed 345 values[i] = ret.Val 346 } 347 } 348 } 349 for i, name := range p.names { 350 if name == "_" { // skip underscore 351 continue 352 } 353 pkg.useName(name) 354 if p.tok == token.CONST { 355 tv := rets[i] 356 if tv.CVal == nil { 357 src, _ := cb.loadExpr(tv.Src) 358 cb.panicCodeErrorf( 359 p.pos, "const initializer %s is not a constant", src) 360 } 361 tvType := typ 362 if tvType == nil { 363 tvType = tv.Type 364 } 365 if old := p.scope.Insert(types.NewConst(p.pos, pkg.Types, name, tvType, tv.CVal)); old != nil { 366 oldpos := cb.fset.Position(old.Pos()) 367 cb.panicCodeErrorf( 368 p.pos, "%s redeclared in this block\n\tprevious declaration at %v", name, oldpos) 369 } 370 } else if typ == nil { 371 var retType = rets[i].Type 372 var parg *Element 373 if values != nil { 374 parg = &Element{Type: retType, Val: values[i]} 375 } 376 retType = DefaultConv(pkg, retType, parg) 377 if values != nil { 378 values[i] = parg.Val 379 } 380 if old := p.scope.Insert(types.NewVar(p.pos, pkg.Types, name, retType)); old != nil { 381 if p.tok != token.DEFINE { 382 oldpos := cb.fset.Position(old.Pos()) 383 cb.panicCodeErrorf( 384 p.pos, "%s redeclared in this block\n\tprevious declaration at %v", name, oldpos) 385 } 386 if err := matchType(pkg, rets[i], old.Type(), "assignment"); err != nil { 387 panic(err) 388 } 389 } 390 } 391 } 392 return p.oldv 393 } 394 395 // VarDecl type 396 type VarDecl = ValueDecl 397 398 func (p *Package) newValueDecl( 399 spec ValueAt, scope *types.Scope, pos token.Pos, tok token.Token, typ types.Type, names ...string) *ValueDecl { 400 n := len(names) 401 if tok == token.DEFINE { // a, b := expr 402 noNewVar := true 403 nameIdents := make([]ast.Expr, n) 404 for i, name := range names { 405 nameIdents[i] = ident(name) 406 if noNewVar && scope.Lookup(name) == nil { 407 noNewVar = false 408 } 409 } 410 if noNewVar { 411 p.cb.handleCodeError(pos, "no new variables on left side of :=") 412 } 413 stmt := &ast.AssignStmt{Tok: token.DEFINE, Lhs: nameIdents} 414 at := p.cb.startStmtAt(stmt) 415 return &ValueDecl{names: names, tok: tok, pos: pos, scope: scope, vals: &stmt.Rhs, at: at} 416 } else if tok == token.CONST && len(names) == 1 && isGopoConst(names[0]) { // Gopo_XXX 417 p.isGopPkg = true 418 } 419 // var a, b = expr 420 // const a, b = expr 421 nameIdents := make([]*ast.Ident, n) 422 for i, name := range names { 423 nameIdents[i] = ident(name) 424 if name == "_" { // skip underscore 425 continue 426 } 427 if typ != nil && tok == token.VAR { 428 if old := scope.Insert(types.NewVar(pos, p.Types, name, typ)); old != nil { 429 allowRedecl := p.allowRedecl && scope == p.Types.Scope() 430 if !(allowRedecl && types.Identical(old.Type(), typ)) { // for c2go 431 oldpos := p.cb.fset.Position(old.Pos()) 432 p.cb.panicCodeErrorf( 433 pos, "%s redeclared in this block\n\tprevious declaration at %v", name, oldpos) 434 } 435 } 436 } 437 } 438 spec.Names = nameIdents 439 if typ != nil { 440 if ut, ok := typ.(*unboundType); ok && ut.tBound == nil { 441 ut.ptypes = append(ut.ptypes, &spec.Type) 442 } else { 443 spec.Type = toType(p, typ) 444 } 445 } 446 return &ValueDecl{ 447 typ: typ, names: names, tok: tok, pos: pos, scope: scope, vals: &spec.Values, at: spec.at} 448 } 449 450 func (p *Package) newValueDefs(scope *types.Scope, tok token.Token) *valueDefs { 451 at := -1 452 decl := &ast.GenDecl{Tok: tok} 453 if scope == p.Types.Scope() { 454 p.file.decls = append(p.file.decls, decl) 455 } else { 456 at = p.cb.startStmtAt(&ast.DeclStmt{Decl: decl}) 457 } 458 return &valueDefs{pkg: p, scope: scope, decl: decl, at: at} 459 } 460 461 func (p *CodeBuilder) valueDefs(tok token.Token) *valueDefs { 462 at := -1 463 decl := &ast.GenDecl{Tok: tok} 464 pkg, scope := p.pkg, p.current.scope 465 if scope == pkg.Types.Scope() { 466 pkg.file.decls = append(pkg.file.decls, decl) 467 } else { 468 at = p.startStmtAt(&ast.DeclStmt{Decl: decl}) 469 } 470 return &valueDefs{pkg: pkg, scope: scope, decl: decl, at: at} 471 } 472 473 // NewConstStart creates constants with names. 474 // 475 // Deprecated: Use NewConstDefs instead. 476 func (p *Package) NewConstStart(scope *types.Scope, pos token.Pos, typ types.Type, names ...string) *CodeBuilder { 477 if debugInstr { 478 log.Println("NewConst", names) 479 } 480 at := p.newValueDefs(scope, token.CONST).NewPos() 481 return p.newValueDecl(at, scope, pos, token.CONST, typ, names...).InitStart(p) 482 } 483 484 // NewConstDefs starts a constant declaration block. 485 func (p *Package) NewConstDefs(scope *types.Scope) *ConstDefs { 486 if debugInstr { 487 log.Println("NewConstDefs") 488 } 489 return &ConstDefs{valueDefs: *p.newValueDefs(scope, token.CONST)} 490 } 491 492 // NewVar starts a var declaration block and creates uninitialized variables with 493 // specified `typ` (can be nil) and `names`. 494 // 495 // Deprecated: This is a shortcut for creating variables. `NewVarDefs` is more powerful and 496 // more recommended. 497 func (p *Package) NewVar(pos token.Pos, typ types.Type, names ...string) *VarDecl { 498 if debugInstr { 499 log.Println("NewVar", names) 500 } 501 scope := p.Types.Scope() 502 at := p.newValueDefs(scope, token.VAR).NewPos() 503 return p.newValueDecl(at, scope, pos, token.VAR, typ, names...) 504 } 505 506 // NewVarEx starts a var declaration block and creates uninitialized variables with 507 // specified `typ` (can be nil) and `names`. 508 // 509 // Deprecated: This is a shortcut for creating variables. `NewVarDefs` is more powerful and 510 // more recommended. 511 func (p *Package) NewVarEx(scope *types.Scope, pos token.Pos, typ types.Type, names ...string) *VarDecl { 512 if debugInstr { 513 log.Println("NewVar", names) 514 } 515 at := p.newValueDefs(scope, token.VAR).NewPos() 516 return p.newValueDecl(at, scope, pos, token.VAR, typ, names...) 517 } 518 519 // NewVarStart creates variables with specified `typ` (can be nil) and `names` and starts 520 // to initialize them. You should call `CodeBuilder.EndInit` to end initialization. 521 // 522 // Deprecated: This is a shortcut for creating variables. `NewVarDefs` is more powerful and more 523 // recommended. 524 func (p *Package) NewVarStart(pos token.Pos, typ types.Type, names ...string) *CodeBuilder { 525 if debugInstr { 526 log.Println("NewVar", names) 527 } 528 scope := p.Types.Scope() 529 at := p.newValueDefs(scope, token.VAR).NewPos() 530 return p.newValueDecl(at, scope, pos, token.VAR, typ, names...).InitStart(p) 531 } 532 533 // NewVarDefs starts a var declaration block. 534 func (p *Package) NewVarDefs(scope *types.Scope) *VarDefs { 535 if debugInstr { 536 log.Println("NewVarDefs") 537 } 538 return &VarDefs{*p.newValueDefs(scope, token.VAR)} 539 } 540 541 // ---------------------------------------------------------------------------- 542 543 type ValueAt struct { 544 *ast.ValueSpec 545 at int 546 } 547 548 type valueDefs struct { 549 decl *ast.GenDecl 550 scope *types.Scope 551 pkg *Package 552 at int 553 } 554 555 func (p *valueDefs) NewPos() ValueAt { 556 decl := p.decl 557 spec := &ast.ValueSpec{} 558 decl.Specs = append(decl.Specs, spec) 559 return ValueAt{spec, p.at} 560 } 561 562 // VarDefs represents a var declaration block. 563 type VarDefs struct { 564 valueDefs 565 } 566 567 // SetComments sets associated documentation. 568 func (p *VarDefs) SetComments(doc *ast.CommentGroup) *VarDefs { 569 p.decl.Doc = doc 570 return p 571 } 572 573 // New creates uninitialized variables with specified `typ` (can be nil) and `names`. 574 func (p *VarDefs) New(pos token.Pos, typ types.Type, names ...string) *VarDecl { 575 return p.NewAt(p.NewPos(), pos, typ, names...) 576 } 577 578 // NewAt creates uninitialized variables with specified `typ` (can be nil) and `names`. 579 func (p *VarDefs) NewAt(at ValueAt, pos token.Pos, typ types.Type, names ...string) *VarDecl { 580 if debugInstr { 581 log.Println("NewVar", names) 582 } 583 return p.pkg.newValueDecl(at, p.scope, pos, token.VAR, typ, names...) 584 } 585 586 // NewAndInit creates variables with specified `typ` (can be nil) and `names`, and initializes them by `fn`. 587 func (p *VarDefs) NewAndInit(fn F, pos token.Pos, typ types.Type, names ...string) *VarDefs { 588 if debugInstr { 589 log.Println("NewAndInit", names) 590 } 591 decl := p.pkg.newValueDecl(p.NewPos(), p.scope, pos, token.VAR, typ, names...) 592 if fn != nil { 593 cb := decl.InitStart(p.pkg) 594 n := fn(cb) 595 cb.EndInit(n) 596 } 597 return p 598 } 599 600 // Delete deletes an uninitialized variable who was created by `New`. 601 // If the variable is initialized, it fails to delete and returns `syscall.EACCES`. 602 // If the variable is not found, it returns `syscall.ENOENT`. 603 func (p *VarDefs) Delete(name string) error { 604 for i, spec := range p.decl.Specs { 605 vspec := spec.(*ast.ValueSpec) 606 for j, ident := range vspec.Names { 607 if ident.Name == name { 608 if vspec.Values != nil { // can't remove an initialized variable 609 return syscall.EACCES 610 } 611 if len(vspec.Names) == 1 { 612 p.decl.Specs = append(p.decl.Specs[:i], p.decl.Specs[i+1:]...) 613 return nil 614 } 615 vspec.Names = append(vspec.Names[:j], vspec.Names[j+1:]...) 616 return nil 617 } 618 } 619 } 620 return syscall.ENOENT 621 } 622 623 // ---------------------------------------------------------------------------- 624 625 // F represents an initialization callback for constants/variables. 626 type F = func(cb *CodeBuilder) int 627 628 // ConstDefs represents a const declaration block. 629 type ConstDefs struct { 630 valueDefs 631 typ types.Type 632 F F 633 } 634 635 func constInitFn(cb *CodeBuilder, iotav int, fn F) int { 636 oldv := cb.iotav 637 cb.iotav = iotav 638 defer func() { 639 cb.iotav = oldv 640 }() 641 return fn(cb) 642 } 643 644 // SetComments sets associated documentation. 645 func (p *ConstDefs) SetComments(doc *ast.CommentGroup) *ConstDefs { 646 p.decl.Doc = doc 647 return p 648 } 649 650 // New creates constants with specified `typ` (can be nil) and `names`. 651 // The values of the constants are given by the callback `fn`. 652 func (p *ConstDefs) New(fn F, iotav int, pos token.Pos, typ types.Type, names ...string) *ConstDefs { 653 return p.NewAt(p.NewPos(), fn, iotav, pos, typ, names...) 654 } 655 656 // NewAt creates constants with specified `typ` (can be nil) and `names`. 657 // The values of the constants are given by the callback `fn`. 658 func (p *ConstDefs) NewAt(at ValueAt, fn F, iotav int, pos token.Pos, typ types.Type, names ...string) *ConstDefs { 659 if debugInstr { 660 log.Println("NewConst", names, iotav) 661 } 662 pkg := p.pkg 663 cb := pkg.newValueDecl(at, p.scope, pos, token.CONST, typ, names...).InitStart(pkg) 664 n := constInitFn(cb, iotav, fn) 665 cb.EndInit(n) 666 p.F, p.typ = fn, typ 667 return p 668 } 669 670 // Next creates constants with specified `names`. 671 // The values of the constants are given by the callback `fn` which is 672 // specified by the last call to `New`. 673 func (p *ConstDefs) Next(iotav int, pos token.Pos, names ...string) *ConstDefs { 674 return p.NextAt(p.NewPos(), p.F, iotav, pos, names...) 675 } 676 677 // NextAt creates constants with specified `names`. 678 // The values of the constants are given by the callback `fn`. 679 func (p *ConstDefs) NextAt(at ValueAt, fn F, iotav int, pos token.Pos, names ...string) *ConstDefs { 680 pkg := p.pkg 681 cb := pkg.CB() 682 n := constInitFn(cb, iotav, fn) 683 if len(names) != n { 684 if len(names) < n { 685 cb.panicCodeError(pos, "extra expression in const declaration") 686 } 687 cb.panicCodeError(pos, "missing value in const declaration") 688 } 689 690 ret := cb.stk.GetArgs(n) 691 defer cb.stk.PopN(n) 692 693 idents := make([]*ast.Ident, n) 694 for i, name := range names { 695 typ := p.typ 696 if typ == nil { 697 typ = ret[i].Type 698 } 699 if name != "_" { 700 if old := p.scope.Insert(types.NewConst(pos, pkg.Types, name, typ, ret[i].CVal)); old != nil { 701 oldpos := cb.fset.Position(old.Pos()) 702 cb.panicCodeErrorf( 703 pos, "%s redeclared in this block\n\tprevious declaration at %v", name, oldpos) 704 } 705 } 706 idents[i] = ident(name) 707 } 708 at.Names = idents 709 return p 710 } 711 712 // ----------------------------------------------------------------------------