Commit 113c4d25 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: refactor import statement parsing

Combine parser's import_stmt and import_here methods as a single new
importdcl method, and cleanup conditional logic slightly to make the
code easier to follow.

Also, eliminate importfile's unused line parameter, and get rid of all
of its duplicate type assertions.

Change-Id: Ic37ae8490afedc533f98ead9feef383e3599bc01
Reviewed-on: https://go-review.googlesource.com/19629Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent d930d69f
...@@ -492,8 +492,6 @@ var debugstr string ...@@ -492,8 +492,6 @@ var debugstr string
var Debug_checknil int var Debug_checknil int
var Debug_typeassert int var Debug_typeassert int
var importmyname *Sym // my name for package
var localpkg *Pkg // package being compiled var localpkg *Pkg // package being compiled
var importpkg *Pkg // package being imported var importpkg *Pkg // package being imported
......
...@@ -687,21 +687,21 @@ func fakeimport() { ...@@ -687,21 +687,21 @@ func fakeimport() {
cannedimports("fake.o", "$$\n") cannedimports("fake.o", "$$\n")
} }
// TODO(gri) line argument doesn't appear to be used func importfile(f *Val) {
func importfile(f *Val, line int) { path_, ok := f.U.(string)
if _, ok := f.U.(string); !ok { if !ok {
Yyerror("import statement not a string") Yyerror("import statement not a string")
fakeimport() fakeimport()
return return
} }
if len(f.U.(string)) == 0 { if len(path_) == 0 {
Yyerror("import path is empty") Yyerror("import path is empty")
fakeimport() fakeimport()
return return
} }
if isbadimport(f.U.(string)) { if isbadimport(path_) {
fakeimport() fakeimport()
return return
} }
...@@ -710,18 +710,16 @@ func importfile(f *Val, line int) { ...@@ -710,18 +710,16 @@ func importfile(f *Val, line int) {
// but we reserve the import path "main" to identify // but we reserve the import path "main" to identify
// the main package, just as we reserve the import // the main package, just as we reserve the import
// path "math" to identify the standard math package. // path "math" to identify the standard math package.
if f.U.(string) == "main" { if path_ == "main" {
Yyerror("cannot import \"main\"") Yyerror("cannot import \"main\"")
errorexit() errorexit()
} }
if myimportpath != "" && f.U.(string) == myimportpath { if myimportpath != "" && path_ == myimportpath {
Yyerror("import %q while compiling that package (import cycle)", f.U.(string)) Yyerror("import %q while compiling that package (import cycle)", path_)
errorexit() errorexit()
} }
path_ := f.U.(string)
if mapped, ok := importMap[path_]; ok { if mapped, ok := importMap[path_]; ok {
path_ = mapped path_ = mapped
} }
...@@ -763,7 +761,7 @@ func importfile(f *Val, line int) { ...@@ -763,7 +761,7 @@ func importfile(f *Val, line int) {
file, found := findpkg(path_) file, found := findpkg(path_)
if !found { if !found {
Yyerror("can't find import: %q", f.U.(string)) Yyerror("can't find import: %q", path_)
errorexit() errorexit()
} }
...@@ -788,7 +786,7 @@ func importfile(f *Val, line int) { ...@@ -788,7 +786,7 @@ func importfile(f *Val, line int) {
var imp *obj.Biobuf var imp *obj.Biobuf
imp, err = obj.Bopenr(file) imp, err = obj.Bopenr(file)
if err != nil { if err != nil {
Yyerror("can't open import: %q: %v", f.U.(string), err) Yyerror("can't open import: %q: %v", path_, err)
errorexit() errorexit()
} }
...@@ -878,7 +876,7 @@ func importfile(f *Val, line int) { ...@@ -878,7 +876,7 @@ func importfile(f *Val, line int) {
incannedimport = 0 incannedimport = 0
default: default:
Yyerror("no import in %q", f.U.(string)) Yyerror("no import in %q", path_)
} }
} }
......
...@@ -323,108 +323,92 @@ func (p *parser) import_() { ...@@ -323,108 +323,92 @@ func (p *parser) import_() {
p.want(LIMPORT) p.want(LIMPORT)
if p.got('(') { if p.got('(') {
for p.tok != EOF && p.tok != ')' { for p.tok != EOF && p.tok != ')' {
p.import_stmt() p.importdcl()
if !p.osemi(')') { if !p.osemi(')') {
break break
} }
} }
p.want(')') p.want(')')
} else { } else {
p.import_stmt() p.importdcl()
}
}
func (p *parser) import_stmt() {
if trace && Debug['x'] != 0 {
defer p.trace("import_stmt")()
}
line := int32(p.import_here())
if p.tok == LPACKAGE {
p.import_package()
p.import_there()
ipkg := importpkg
my := importmyname
importpkg = nil
importmyname = nil
if my == nil {
my = Lookup(ipkg.Name)
}
pack := Nod(OPACK, nil, nil)
pack.Sym = my
pack.Name.Pkg = ipkg
pack.Lineno = line
if strings.HasPrefix(my.Name, ".") {
importdot(ipkg, pack)
return
}
if my.Name == "init" {
lineno = line
Yyerror("cannot import package as init - init must be a func")
return
}
if my.Name == "_" {
return
}
if my.Def != nil {
lineno = line
redeclare(my, "as imported package name")
}
my.Def = pack
my.Lastlineno = line
my.Block = 1 // at top level
return
}
p.import_there()
// When an invalid import path is passed to importfile,
// it calls Yyerror and then sets up a fake import with
// no package statement. This allows us to test more
// than one invalid import statement in a single file.
if nerrors == 0 {
Fatalf("phase error in import")
} }
} }
// ImportSpec = [ "." | PackageName ] ImportPath . // ImportSpec = [ "." | PackageName ] ImportPath .
// ImportPath = string_lit . // ImportPath = string_lit .
// func (p *parser) importdcl() {
// import_here switches the underlying lexed source to the export data
// of the imported package.
func (p *parser) import_here() int {
if trace && Debug['x'] != 0 { if trace && Debug['x'] != 0 {
defer p.trace("import_here")() defer p.trace("importdcl")()
} }
importmyname = nil var my *Sym
switch p.tok { switch p.tok {
case LNAME, '@', '?': case LNAME, '@', '?':
// import with given name // import with given name
importmyname = p.sym() my = p.sym()
case '.': case '.':
// import into my name space // import into my name space
importmyname = Lookup(".") my = Lookup(".")
p.next() p.next()
} }
var path Val if p.tok != LLITERAL {
if p.tok == LLITERAL {
path = p.val
p.next()
} else {
p.syntax_error("missing import path; require quoted string") p.syntax_error("missing import path; require quoted string")
p.advance(';', ')') p.advance(';', ')')
return
}
line := int32(parserline())
path := p.val
p.next()
importfile(&path)
if p.tok != LPACKAGE {
// When an invalid import path is passed to importfile,
// it calls Yyerror and then sets up a fake import with
// no package statement. This allows us to test more
// than one invalid import statement in a single file.
p.import_there()
if nerrors == 0 {
Fatalf("phase error in import")
}
return
} }
p.import_package()
p.import_there()
ipkg := importpkg
importpkg = nil
if my == nil {
my = Lookup(ipkg.Name)
}
pack := Nod(OPACK, nil, nil)
pack.Sym = my
pack.Name.Pkg = ipkg
pack.Lineno = line
line := parserline() if strings.HasPrefix(my.Name, ".") {
importfile(&path, line) importdot(ipkg, pack)
return line return
}
if my.Name == "init" {
lineno = line
Yyerror("cannot import package as init - init must be a func")
return
}
if my.Name == "_" {
return
}
if my.Def != nil {
lineno = line
redeclare(my, "as imported package name")
}
my.Def = pack
my.Lastlineno = line
my.Block = 1 // at top level
} }
// import_package parses the header of an imported package as exported // import_package parses the header of an imported package as exported
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment