}
fmt.Fprintf(bout, "\n")
- var p *Pkg
- for i := int32(0); i < int32(len(phash)); i++ {
- for p = phash[i]; p != nil; p = p.Link {
- if p.Direct != 0 {
- dumppkg(p)
- }
+ for _, p := range pkgs {
+ if p.Direct != 0 {
+ dumppkg(p)
}
}
return s.Def.Type
}
+var numImport = make(map[string]int)
+
func importimport(s *Sym, path string) {
// Informational: record package name
// associated with import path, for use in
p := mkpkg(path)
if p.Name == "" {
p.Name = s.Name
- Pkglookup(s.Name, nil).Npkg++
+ numImport[s.Name]++
} else if p.Name != s.Name {
Yyerror("conflicting names %s and %s for package %q", p.Name, s.Name, p.Path)
}
}
// If the name was used by multiple packages, display the full path,
- if s.Pkg.Name != "" && Pkglookup(s.Pkg.Name, nil).Npkg > 1 {
+ if s.Pkg.Name != "" && numImport[s.Pkg.Name] > 1 {
return fmt.Sprintf("%q.%s", s.Pkg.Path, s.Name)
}
var fp string
Path string
Pathsym *Sym
Prefix string
- Link *Pkg
Imported uint8
Exported int8
Direct int8
Safe bool
+ Syms map[string]*Sym
}
type Sym struct {
Flags uint8
Sym uint8
Link *Sym
- Npkg int32
Uniqgen uint32
Importdef *Pkg
Linkname string
var Debug_checknil int
-var hash [NHASH]*Sym
-
var importmyname *Sym // my name for package
var localpkg *Pkg // package being compiled
var rawpkg *Pkg // fake package for raw symbol names
-var phash [128]*Pkg
-
var Tptr int // either TPTR32 or TPTR64
var myimportpath string
{
if importpkg.Name == "" {
importpkg.Name = $2.Name;
- Pkglookup($2.Name, nil).Npkg++;
+ numImport[$2.Name]++
} else if importpkg.Name != $2.Name {
Yyerror("conflicting names %s and %s for package %q", importpkg.Name, $2.Name, importpkg.Path);
}
}
// are there any imported init functions
- for h := uint32(0); h < NHASH; h++ {
- for s = hash[h]; s != nil; s = s.Link {
- if s.Name[0] != 'i' || s.Name != "init" {
- continue
- }
- if s.Def == nil {
- continue
- }
+ for _, s := range initSyms {
+ if s.Def != nil {
return true
}
}
r = list(r, a)
// (7)
- var s *Sym
- for h := uint32(0); h < NHASH; h++ {
- for s = hash[h]; s != nil; s = s.Link {
- if s.Name[0] != 'i' || s.Name != "init" {
- continue
- }
- if s.Def == nil {
- continue
- }
- if s == initsym {
- continue
- }
-
+ for _, s := range initSyms {
+ if s.Def != nil && s != initsym {
// could check that it is fn of no args/returns
a = Nod(OCALL, s.Def, nil)
-
r = list(r, a)
}
}
// could check that it is fn of no args/returns
for i := 1; ; i++ {
namebuf = fmt.Sprintf("init.%d", i)
- s = Lookup(namebuf)
+ s := Lookup(namebuf)
if s.Def == nil {
break
}
cp = nil
ungetc(c)
- s = Lookup(lexbuf.String())
+ s = LookupBytes(lexbuf.Bytes())
switch s.Lexical {
case LIGNORE:
goto l0
if pkgname != localpkg.Name {
Yyerror("package %s; expected %s", pkgname, localpkg.Name)
}
- var s *Sym
- for h := int32(0); h < NHASH; h++ {
- for s = hash[h]; s != nil; s = s.Link {
- if s.Def == nil || s.Pkg != localpkg {
- continue
- }
- if s.Def.Op == OPACK {
- // throw away top-level package name leftover
- // from previous file.
- // leave s->block set to cause redeclaration
- // errors if a conflicting top-level name is
- // introduced by a different file.
- if s.Def.Used == 0 && nsyntaxerrors == 0 {
- pkgnotused(int(s.Def.Lineno), s.Def.Pkg.Path, s.Name)
- }
- s.Def = nil
- continue
+ for _, s := range localpkg.Syms {
+ if s.Def == nil {
+ continue
+ }
+ if s.Def.Op == OPACK {
+ // throw away top-level package name leftover
+ // from previous file.
+ // leave s->block set to cause redeclaration
+ // errors if a conflicting top-level name is
+ // introduced by a different file.
+ if s.Def.Used == 0 && nsyntaxerrors == 0 {
+ pkgnotused(int(s.Def.Lineno), s.Def.Pkg.Path, s.Name)
}
+ s.Def = nil
+ continue
+ }
- if s.Def.Sym != s {
- // throw away top-level name left over
- // from previous import . "x"
- if s.Def.Pack != nil && s.Def.Pack.Used == 0 && nsyntaxerrors == 0 {
- pkgnotused(int(s.Def.Pack.Lineno), s.Def.Pack.Pkg.Path, "")
- s.Def.Pack.Used = 1
- }
-
- s.Def = nil
- continue
+ if s.Def.Sym != s {
+ // throw away top-level name left over
+ // from previous import . "x"
+ if s.Def.Pack != nil && s.Def.Pack.Used == 0 && nsyntaxerrors == 0 {
+ pkgnotused(int(s.Def.Pack.Lineno), s.Def.Pack.Pkg.Path, "")
+ s.Def.Pack.Used = 1
}
+
+ s.Def = nil
+ continue
}
}
}
}
// generate import strings for imported packages
- var p *Pkg
- for i := 0; i < len(phash); i++ {
- for p = phash[i]; p != nil; p = p.Link {
- if p.Direct != 0 {
- dimportpath(p)
- }
+ for _, p := range pkgs {
+ if p.Direct != 0 {
+ dimportpath(p)
}
}
return lno
}
-func stringhash(p string) uint32 {
- var c int
+func Lookup(name string) *Sym {
+ return localpkg.Lookup(name)
+}
- h := uint32(0)
- for {
- c, p = intstarstringplusplus(p)
- if c == 0 {
- break
- }
- h = h*PRIME1 + uint32(c)
- }
+func LookupBytes(name []byte) *Sym {
+ return localpkg.LookupBytes(name)
+}
- if int32(h) < 0 {
- h = -h
- if int32(h) < 0 {
- h = 0
- }
+var initSyms []*Sym
+
+var nopkg = new(Pkg)
+
+func (pkg *Pkg) Lookup(name string) *Sym {
+ if pkg == nil {
+ pkg = nopkg
+ }
+ if s := pkg.Syms[name]; s != nil {
+ return s
}
- return h
+ s := &Sym{
+ Name: name,
+ Pkg: pkg,
+ Lexical: LNAME,
+ }
+ if s.Name == "init" {
+ initSyms = append(initSyms, s)
+ }
+ if pkg.Syms == nil {
+ pkg.Syms = make(map[string]*Sym)
+ }
+ pkg.Syms[name] = s
+ return s
}
-func Lookup(name string) *Sym {
- return Pkglookup(name, localpkg)
+func (pkg *Pkg) LookupBytes(name []byte) *Sym {
+ if pkg == nil {
+ pkg = nopkg
+ }
+ if s := pkg.Syms[string(name)]; s != nil {
+ return s
+ }
+ str := internString(name)
+ return pkg.Lookup(str)
}
func Pkglookup(name string, pkg *Pkg) *Sym {
- h := stringhash(name) % NHASH
- c := int(name[0])
- for s := hash[h]; s != nil; s = s.Link {
- if int(s.Name[0]) != c || s.Pkg != pkg {
- continue
- }
- if s.Name == name {
- return s
- }
- }
-
- s := new(Sym)
- s.Name = name
-
- s.Pkg = pkg
-
- s.Link = hash[h]
- hash[h] = s
- s.Lexical = LNAME
-
- return s
+ return pkg.Lookup(name)
}
func restrictlookup(name string, pkg *Pkg) *Sym {
// find all the exported symbols in package opkg
// and make them available in the current package
func importdot(opkg *Pkg, pack *Node) {
- var s *Sym
var s1 *Sym
var pkgerror string
n := 0
- for h := uint32(0); h < NHASH; h++ {
- for s = hash[h]; s != nil; s = s.Link {
- if s.Pkg != opkg {
- continue
- }
- if s.Def == nil {
- continue
- }
- if !exportname(s.Name) || strings.ContainsRune(s.Name, 0xb7) { // 0xb7 = center dot
- continue
- }
- s1 = Lookup(s.Name)
- if s1.Def != nil {
- pkgerror = fmt.Sprintf("during import %q", opkg.Path)
- redeclare(s1, pkgerror)
- continue
- }
-
- s1.Def = s.Def
- s1.Block = s.Block
- s1.Def.Pack = pack
- s1.Origpkg = opkg
- n++
+ for _, s := range opkg.Syms {
+ if s.Def == nil {
+ continue
}
+ if !exportname(s.Name) || strings.ContainsRune(s.Name, 0xb7) { // 0xb7 = center dot
+ continue
+ }
+ s1 = Lookup(s.Name)
+ if s1.Def != nil {
+ pkgerror = fmt.Sprintf("during import %q", opkg.Path)
+ redeclare(s1, pkgerror)
+ continue
+ }
+
+ s1.Def = s.Def
+ s1.Block = s.Block
+ s1.Def.Pack = pack
+ s1.Origpkg = opkg
+ n++
}
if n == 0 {
return s
}
+var pkgMap = make(map[string]*Pkg)
+var pkgs []*Pkg
+
func mkpkg(path string) *Pkg {
- h := int(stringhash(path) & uint32(len(phash)-1))
- for p := phash[h]; p != nil; p = p.Link {
- if p.Path == path {
- return p
- }
+ if p := pkgMap[path]; p != nil {
+ return p
}
p := new(Pkg)
p.Path = path
p.Prefix = pathtoprefix(path)
- p.Link = phash[h]
- phash[h] = p
+ pkgMap[path] = p
+ pkgs = append(pkgs, p)
return p
}
/*
* type check composite
*/
-func fielddup(n *Node, hash []*Node) {
+func fielddup(n *Node, hash map[string]bool) {
if n.Op != ONAME {
Fatal("fielddup: not ONAME")
}
- s := n.Sym.Name
- h := uint(stringhash(s) % uint32(len(hash)))
- for a := hash[h]; a != nil; a = a.Ntest {
- if a.Sym.Name == s {
- Yyerror("duplicate field name in struct literal: %s", s)
- return
- }
+ name := n.Sym.Name
+ if hash[name] {
+ Yyerror("duplicate field name in struct literal: %s", name)
+ return
}
-
- n.Ntest = hash[h]
- hash[h] = n
+ hash[name] = true
}
func keydup(n *Node, hash []*Node) {
Yyerror("too few values in struct initializer")
}
} else {
- var autohash [101]*Node
- hash := inithash(n, autohash[:])
+ hash := make(map[string]bool)
// keyed list
var s *Sym
{
if importpkg.Name == "" {
importpkg.Name = yyDollar[2].sym.Name
- Pkglookup(yyDollar[2].sym.Name, nil).Npkg++
+ numImport[yyDollar[2].sym.Name]++
} else if importpkg.Name != yyDollar[2].sym.Name {
Yyerror("conflicting names %s and %s for package %q", importpkg.Name, yyDollar[2].sym.Name, importpkg.Path)
}