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
var Debug_checknil int
var Debug_typeassert int
var importmyname *Sym // my name for package
var localpkg *Pkg // package being compiled
var importpkg *Pkg // package being imported
......
......@@ -687,21 +687,21 @@ func fakeimport() {
cannedimports("fake.o", "$$\n")
}
// TODO(gri) line argument doesn't appear to be used
func importfile(f *Val, line int) {
if _, ok := f.U.(string); !ok {
func importfile(f *Val) {
path_, ok := f.U.(string)
if !ok {
Yyerror("import statement not a string")
fakeimport()
return
}
if len(f.U.(string)) == 0 {
if len(path_) == 0 {
Yyerror("import path is empty")
fakeimport()
return
}
if isbadimport(f.U.(string)) {
if isbadimport(path_) {
fakeimport()
return
}
......@@ -710,18 +710,16 @@ func importfile(f *Val, line int) {
// but we reserve the import path "main" to identify
// the main package, just as we reserve the import
// path "math" to identify the standard math package.
if f.U.(string) == "main" {
if path_ == "main" {
Yyerror("cannot import \"main\"")
errorexit()
}
if myimportpath != "" && f.U.(string) == myimportpath {
Yyerror("import %q while compiling that package (import cycle)", f.U.(string))
if myimportpath != "" && path_ == myimportpath {
Yyerror("import %q while compiling that package (import cycle)", path_)
errorexit()
}
path_ := f.U.(string)
if mapped, ok := importMap[path_]; ok {
path_ = mapped
}
......@@ -763,7 +761,7 @@ func importfile(f *Val, line int) {
file, found := findpkg(path_)
if !found {
Yyerror("can't find import: %q", f.U.(string))
Yyerror("can't find import: %q", path_)
errorexit()
}
......@@ -788,7 +786,7 @@ func importfile(f *Val, line int) {
var imp *obj.Biobuf
imp, err = obj.Bopenr(file)
if err != nil {
Yyerror("can't open import: %q: %v", f.U.(string), err)
Yyerror("can't open import: %q: %v", path_, err)
errorexit()
}
......@@ -878,7 +876,7 @@ func importfile(f *Val, line int) {
incannedimport = 0
default:
Yyerror("no import in %q", f.U.(string))
Yyerror("no import in %q", path_)
}
}
......
......@@ -323,108 +323,92 @@ func (p *parser) import_() {
p.want(LIMPORT)
if p.got('(') {
for p.tok != EOF && p.tok != ')' {
p.import_stmt()
p.importdcl()
if !p.osemi(')') {
break
}
}
p.want(')')
} else {
p.import_stmt()
}
}
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")
p.importdcl()
}
}
// ImportSpec = [ "." | PackageName ] ImportPath .
// ImportPath = string_lit .
//
// import_here switches the underlying lexed source to the export data
// of the imported package.
func (p *parser) import_here() int {
func (p *parser) importdcl() {
if trace && Debug['x'] != 0 {
defer p.trace("import_here")()
defer p.trace("importdcl")()
}
importmyname = nil
var my *Sym
switch p.tok {
case LNAME, '@', '?':
// import with given name
importmyname = p.sym()
my = p.sym()
case '.':
// import into my name space
importmyname = Lookup(".")
my = Lookup(".")
p.next()
}
var path Val
if p.tok == LLITERAL {
path = p.val
p.next()
} else {
if p.tok != LLITERAL {
p.syntax_error("missing import path; require quoted string")
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()
importfile(&path, line)
return 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
}
// 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