compiler: drop semicolons in export data
The export data, which is approximately readable and looks something like Go, was first implemented back when Go still used semicolons. Drop the semicolons, to make it look slightly more Go like and make it slightly smaller. This updates the compiler and the gccgoimporter package. This introduces a new version of the export data. There are going to be more changes to the export data, so this version is still subject to change. Reviewed-on: https://go-review.googlesource.com/c/143018 From-SVN: r265284
This commit is contained in:
parent
d047723321
commit
e8ce849a48
@ -1,4 +1,4 @@
|
||||
e32e9aaee598eeb43f9616cf6ca1d11acaa9d167
|
||||
0494dc5737f0c89ad6f45e04e8313e4161678861
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -26,14 +26,18 @@ const int Export::magic_len;
|
||||
// Current version magic string.
|
||||
const char Export::cur_magic[Export::magic_len] =
|
||||
{
|
||||
'v', '2', ';', '\n'
|
||||
'v', '3', ';', '\n'
|
||||
};
|
||||
|
||||
// Magic string for previous version (still supported)
|
||||
// Magic strings for previous versions (still supported).
|
||||
const char Export::v1_magic[Export::magic_len] =
|
||||
{
|
||||
'v', '1', ';', '\n'
|
||||
};
|
||||
const char Export::v2_magic[Export::magic_len] =
|
||||
{
|
||||
'v', '2', ';', '\n'
|
||||
};
|
||||
|
||||
const int Export::checksum_len;
|
||||
|
||||
@ -147,7 +151,7 @@ Export::export_globals(const std::string& package_name,
|
||||
// The package name.
|
||||
this->write_c_string("package ");
|
||||
this->write_string(package_name);
|
||||
this->write_c_string(";\n");
|
||||
this->write_c_string("\n");
|
||||
|
||||
// The prefix or package path, used for all global symbols.
|
||||
if (prefix.empty())
|
||||
@ -161,7 +165,7 @@ Export::export_globals(const std::string& package_name,
|
||||
this->write_c_string("prefix ");
|
||||
this->write_string(prefix);
|
||||
}
|
||||
this->write_c_string(";\n");
|
||||
this->write_c_string("\n");
|
||||
|
||||
this->write_packages(packages);
|
||||
|
||||
@ -191,7 +195,7 @@ Export::export_globals(const std::string& package_name,
|
||||
dig = c & 0xf;
|
||||
s += dig < 10 ? '0' + dig : 'A' + dig - 10;
|
||||
}
|
||||
s += ";\n";
|
||||
s += "\n";
|
||||
this->stream_->write_checksum(s);
|
||||
}
|
||||
|
||||
@ -233,7 +237,7 @@ Export::write_packages(const std::map<std::string, Package*>& packages)
|
||||
this->write_string((*p)->pkgpath());
|
||||
this->write_c_string(" ");
|
||||
this->write_string((*p)->pkgpath_symbol());
|
||||
this->write_c_string(";\n");
|
||||
this->write_c_string("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,7 +275,7 @@ Export::write_imports(const std::map<std::string, Package*>& imports)
|
||||
this->write_string(p->second->pkgpath());
|
||||
this->write_c_string(" \"");
|
||||
this->write_string(p->first);
|
||||
this->write_c_string("\";\n");
|
||||
this->write_c_string("\"\n");
|
||||
|
||||
this->packages_.insert(p->second);
|
||||
}
|
||||
@ -347,7 +351,7 @@ Export::write_imported_init_fns(const std::string& package_name,
|
||||
|
||||
if (imported_init_fns.empty())
|
||||
{
|
||||
this->write_c_string(";\n");
|
||||
this->write_c_string("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -394,7 +398,7 @@ Export::write_imported_init_fns(const std::string& package_name,
|
||||
it->second.push_back(ii->init_name());
|
||||
}
|
||||
}
|
||||
this->write_c_string(";\n");
|
||||
this->write_c_string("\n");
|
||||
|
||||
// Create the init graph. Start by populating the graph with
|
||||
// all the edges we inherited from imported packages.
|
||||
@ -494,7 +498,7 @@ Export::write_imported_init_fns(const std::string& package_name,
|
||||
this->write_unsigned(sink);
|
||||
}
|
||||
}
|
||||
this->write_c_string(";\n");
|
||||
this->write_c_string("\n");
|
||||
}
|
||||
|
||||
// Write a name to the export stream.
|
||||
|
@ -57,7 +57,8 @@ enum Export_data_version {
|
||||
EXPORT_FORMAT_UNKNOWN = 0,
|
||||
EXPORT_FORMAT_V1 = 1,
|
||||
EXPORT_FORMAT_V2 = 2,
|
||||
EXPORT_FORMAT_CURRENT = EXPORT_FORMAT_V2
|
||||
EXPORT_FORMAT_V3 = 3,
|
||||
EXPORT_FORMAT_CURRENT = EXPORT_FORMAT_V3
|
||||
};
|
||||
|
||||
// This class manages exporting Go declarations. It handles the main
|
||||
@ -119,9 +120,10 @@ class Export : public String_dump
|
||||
// Size of export data magic string (which includes version number).
|
||||
static const int magic_len = 4;
|
||||
|
||||
// Magic strings (current version and older v1 version).
|
||||
// Magic strings (current version and older versions).
|
||||
static const char cur_magic[magic_len];
|
||||
static const char v1_magic[magic_len];
|
||||
static const char v2_magic[magic_len];
|
||||
|
||||
// The length of the checksum string.
|
||||
static const int checksum_len = 20;
|
||||
|
@ -5391,7 +5391,7 @@ Function::export_func_with_type(Export* exp, const std::string& name,
|
||||
exp->write_c_string(")");
|
||||
}
|
||||
}
|
||||
exp->write_c_string(";\n");
|
||||
exp->write_c_string("\n");
|
||||
}
|
||||
|
||||
// Import a function.
|
||||
@ -5498,7 +5498,8 @@ Function::import_func(Import* imp, std::string* pname,
|
||||
imp->require_c_string(")");
|
||||
}
|
||||
}
|
||||
imp->require_c_string(";\n");
|
||||
imp->require_semicolon_if_old_version();
|
||||
imp->require_c_string("\n");
|
||||
*presults = results;
|
||||
}
|
||||
|
||||
@ -6885,7 +6886,7 @@ Variable::export_var(Export* exp, const std::string& name) const
|
||||
exp->write_string(name);
|
||||
exp->write_c_string(" ");
|
||||
exp->write_type(this->type());
|
||||
exp->write_c_string(";\n");
|
||||
exp->write_c_string("\n");
|
||||
}
|
||||
|
||||
// Import a variable.
|
||||
@ -6897,7 +6898,8 @@ Variable::import_var(Import* imp, std::string* pname, Type** ptype)
|
||||
*pname = imp->read_identifier();
|
||||
imp->require_c_string(" ");
|
||||
*ptype = imp->read_type();
|
||||
imp->require_c_string(";\n");
|
||||
imp->require_semicolon_if_old_version();
|
||||
imp->require_c_string("\n");
|
||||
}
|
||||
|
||||
// Convert a variable to the backend representation.
|
||||
@ -7089,7 +7091,7 @@ Named_constant::export_const(Export* exp, const std::string& name) const
|
||||
}
|
||||
exp->write_c_string("= ");
|
||||
this->expr()->export_expression(exp);
|
||||
exp->write_c_string(";\n");
|
||||
exp->write_c_string("\n");
|
||||
}
|
||||
|
||||
// Import a constant.
|
||||
@ -7110,7 +7112,8 @@ Named_constant::import_const(Import* imp, std::string* pname, Type** ptype,
|
||||
}
|
||||
imp->require_c_string("= ");
|
||||
*pexpr = Expression::import_expression(imp);
|
||||
imp->require_c_string(";\n");
|
||||
imp->require_semicolon_if_old_version();
|
||||
imp->require_c_string("\n");
|
||||
}
|
||||
|
||||
// Get the backend representation.
|
||||
|
@ -241,8 +241,9 @@ Import::find_export_data(const std::string& filename, int fd, Location location)
|
||||
return NULL;
|
||||
|
||||
// Check for a file containing nothing but Go export data.
|
||||
if (memcmp(buf, Export::cur_magic, Export::magic_len) == 0 ||
|
||||
memcmp(buf, Export::v1_magic, Export::magic_len) == 0)
|
||||
if (memcmp(buf, Export::cur_magic, Export::magic_len) == 0
|
||||
|| memcmp(buf, Export::v1_magic, Export::magic_len) == 0
|
||||
|| memcmp(buf, Export::v2_magic, Export::magic_len) == 0)
|
||||
return new Stream_from_file(fd);
|
||||
|
||||
// See if we can read this as an archive.
|
||||
@ -325,6 +326,12 @@ Import::import(Gogo* gogo, const std::string& local_name,
|
||||
Export::magic_len);
|
||||
this->version_ = EXPORT_FORMAT_V1;
|
||||
}
|
||||
else if (stream->match_bytes(Export::v2_magic, Export::magic_len))
|
||||
{
|
||||
stream->require_bytes(this->location_, Export::v2_magic,
|
||||
Export::magic_len);
|
||||
this->version_ = EXPORT_FORMAT_V2;
|
||||
}
|
||||
else
|
||||
{
|
||||
go_error_at(this->location_,
|
||||
@ -335,7 +342,8 @@ Import::import(Gogo* gogo, const std::string& local_name,
|
||||
|
||||
this->require_c_string("package ");
|
||||
std::string package_name = this->read_identifier();
|
||||
this->require_c_string(";\n");
|
||||
this->require_semicolon_if_old_version();
|
||||
this->require_c_string("\n");
|
||||
|
||||
std::string pkgpath;
|
||||
std::string pkgpath_symbol;
|
||||
@ -343,7 +351,8 @@ Import::import(Gogo* gogo, const std::string& local_name,
|
||||
{
|
||||
this->advance(7);
|
||||
std::string unique_prefix = this->read_identifier();
|
||||
this->require_c_string(";\n");
|
||||
this->require_semicolon_if_old_version();
|
||||
this->require_c_string("\n");
|
||||
pkgpath = unique_prefix + '.' + package_name;
|
||||
pkgpath_symbol = (Gogo::pkgpath_for_symbol(unique_prefix) + '.'
|
||||
+ Gogo::pkgpath_for_symbol(package_name));
|
||||
@ -352,10 +361,14 @@ Import::import(Gogo* gogo, const std::string& local_name,
|
||||
{
|
||||
this->require_c_string("pkgpath ");
|
||||
pkgpath = this->read_identifier();
|
||||
this->require_c_string(";\n");
|
||||
this->require_semicolon_if_old_version();
|
||||
this->require_c_string("\n");
|
||||
pkgpath_symbol = Gogo::pkgpath_for_symbol(pkgpath);
|
||||
}
|
||||
|
||||
if (stream->saw_error())
|
||||
return NULL;
|
||||
|
||||
this->package_ = gogo->add_imported_package(package_name, local_name,
|
||||
is_local_name_exported,
|
||||
pkgpath, pkgpath_symbol,
|
||||
@ -418,7 +431,8 @@ Import::import(Gogo* gogo, const std::string& local_name,
|
||||
// load time.
|
||||
this->require_c_string("checksum ");
|
||||
stream->advance(Export::checksum_len * 2);
|
||||
this->require_c_string(";\n");
|
||||
this->require_semicolon_if_old_version();
|
||||
this->require_c_string("\n");
|
||||
}
|
||||
|
||||
return this->package_;
|
||||
@ -436,7 +450,8 @@ Import::read_one_package()
|
||||
std::string pkgpath = this->read_identifier();
|
||||
this->require_c_string(" ");
|
||||
std::string pkgpath_symbol = this->read_identifier();
|
||||
this->require_c_string(";\n");
|
||||
this->require_semicolon_if_old_version();
|
||||
this->require_c_string("\n");
|
||||
|
||||
Package* p = this->gogo_->register_package(pkgpath, pkgpath_symbol,
|
||||
Linemap::unknown_location());
|
||||
@ -456,7 +471,9 @@ Import::read_one_import()
|
||||
Stream* stream = this->stream_;
|
||||
while (stream->peek_char() != '"')
|
||||
stream->advance(1);
|
||||
this->require_c_string("\";\n");
|
||||
this->require_c_string("\"");
|
||||
this->require_semicolon_if_old_version();
|
||||
this->require_c_string("\n");
|
||||
|
||||
Package* p = this->gogo_->register_package(pkgpath, "",
|
||||
Linemap::unknown_location());
|
||||
@ -474,7 +491,7 @@ Import::read_import_init_fns(Gogo* gogo)
|
||||
// to read the init_graph section.
|
||||
std::map<std::string, unsigned> init_idx;
|
||||
|
||||
while (!this->match_c_string(";"))
|
||||
while (!this->match_c_string("\n") && !this->match_c_string(";"))
|
||||
{
|
||||
int priority = -1;
|
||||
|
||||
@ -499,7 +516,8 @@ Import::read_import_init_fns(Gogo* gogo)
|
||||
unsigned idx = init_idx.size();
|
||||
init_idx[init_name] = idx;
|
||||
}
|
||||
this->require_c_string(";\n");
|
||||
this->require_semicolon_if_old_version();
|
||||
this->require_c_string("\n");
|
||||
|
||||
if (this->match_c_string("init_graph"))
|
||||
{
|
||||
@ -524,7 +542,7 @@ Import::read_import_init_fns(Gogo* gogo)
|
||||
//
|
||||
// where src + sink are init functions indices.
|
||||
|
||||
while (!this->match_c_string(";"))
|
||||
while (!this->match_c_string("\n") && !this->match_c_string(";"))
|
||||
{
|
||||
this->require_c_string(" ");
|
||||
std::string src_string = this->read_identifier();
|
||||
@ -543,7 +561,8 @@ Import::read_import_init_fns(Gogo* gogo)
|
||||
|
||||
ii_src->record_precursor_fcn(ii_sink->init_name());
|
||||
}
|
||||
this->require_c_string(";\n");
|
||||
this->require_semicolon_if_old_version();
|
||||
this->require_c_string("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -967,7 +986,7 @@ Import::read_identifier()
|
||||
while (true)
|
||||
{
|
||||
c = stream->peek_char();
|
||||
if (c == -1 || c == ' ' || c == ';')
|
||||
if (c == -1 || c == ' ' || c == '\n' || c == ';')
|
||||
break;
|
||||
ret += c;
|
||||
stream->advance(1);
|
||||
|
@ -184,6 +184,15 @@ class Import
|
||||
advance(size_t skip)
|
||||
{ this->stream_->advance(skip); }
|
||||
|
||||
// Skip a semicolon if using an older version.
|
||||
void
|
||||
require_semicolon_if_old_version()
|
||||
{
|
||||
if (this->version_ == EXPORT_FORMAT_V1
|
||||
|| this->version_ == EXPORT_FORMAT_V2)
|
||||
this->require_c_string(";");
|
||||
}
|
||||
|
||||
// Read an identifier.
|
||||
std::string
|
||||
read_identifier();
|
||||
|
@ -10892,7 +10892,7 @@ Named_type::export_named_type(Export* exp, const std::string&) const
|
||||
// be written by Export::write_type anyhow.
|
||||
exp->write_c_string("type ");
|
||||
exp->write_type(this);
|
||||
exp->write_c_string(";\n");
|
||||
exp->write_c_string("\n");
|
||||
}
|
||||
|
||||
// Import a named type.
|
||||
@ -10904,7 +10904,8 @@ Named_type::import_named_type(Import* imp, Named_type** ptype)
|
||||
Type *type = imp->read_type();
|
||||
*ptype = type->named_type();
|
||||
go_assert(*ptype != NULL);
|
||||
imp->require_c_string(";\n");
|
||||
imp->require_semicolon_if_old_version();
|
||||
imp->require_c_string("\n");
|
||||
}
|
||||
|
||||
// Export the type when it is referenced by another type. In this
|
||||
|
@ -64,6 +64,7 @@ func findExportFile(searchpaths []string, pkgpath string) (string, error) {
|
||||
const (
|
||||
gccgov1Magic = "v1;\n"
|
||||
gccgov2Magic = "v2;\n"
|
||||
gccgov3Magic = "v3;\n"
|
||||
goimporterMagic = "\n$$ "
|
||||
archiveMagic = "!<ar"
|
||||
aixbigafMagic = "<big"
|
||||
@ -93,7 +94,7 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
|
||||
|
||||
var objreader io.ReaderAt
|
||||
switch string(magic[:]) {
|
||||
case gccgov1Magic, gccgov2Magic, goimporterMagic:
|
||||
case gccgov1Magic, gccgov2Magic, gccgov3Magic, goimporterMagic:
|
||||
// Raw export data.
|
||||
reader = f
|
||||
return
|
||||
@ -208,7 +209,7 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
|
||||
}
|
||||
|
||||
switch magics {
|
||||
case gccgov1Magic, gccgov2Magic:
|
||||
case gccgov1Magic, gccgov2Magic, gccgov3Magic:
|
||||
var p parser
|
||||
p.init(fpath, reader, imports)
|
||||
pkg = p.parsePackage()
|
||||
|
@ -34,7 +34,7 @@ func (p *parser) init(filename string, src io.Reader, imports map[string]*types.
|
||||
p.scanner.Init(src)
|
||||
p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
|
||||
p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
|
||||
p.scanner.Whitespace = 1<<'\t' | 1<<'\n' | 1<<' '
|
||||
p.scanner.Whitespace = 1<<'\t' | 1<<' '
|
||||
p.scanner.Filename = filename // for good error messages
|
||||
p.next()
|
||||
p.imports = imports
|
||||
@ -71,6 +71,13 @@ func (p *parser) expect(tok rune) string {
|
||||
return lit
|
||||
}
|
||||
|
||||
func (p *parser) expectEOL() {
|
||||
if p.version == "v1" || p.version == "v2" {
|
||||
p.expect(';')
|
||||
}
|
||||
p.expect('\n')
|
||||
}
|
||||
|
||||
func (p *parser) expectKeyword(keyword string) {
|
||||
lit := p.expect(scanner.Ident)
|
||||
if lit != keyword {
|
||||
@ -96,7 +103,7 @@ func (p *parser) parseUnquotedString() string {
|
||||
buf.WriteString(p.scanner.TokenText())
|
||||
// This loop needs to examine each character before deciding whether to consume it. If we see a semicolon,
|
||||
// we need to let it be consumed by p.next().
|
||||
for ch := p.scanner.Peek(); ch != ';' && ch != scanner.EOF && p.scanner.Whitespace&(1<<uint(ch)) == 0; ch = p.scanner.Peek() {
|
||||
for ch := p.scanner.Peek(); ch != '\n' && ch != ';' && ch != scanner.EOF && p.scanner.Whitespace&(1<<uint(ch)) == 0; ch = p.scanner.Peek() {
|
||||
buf.WriteRune(ch)
|
||||
p.scanner.Next()
|
||||
}
|
||||
@ -431,19 +438,22 @@ func (p *parser) parseNamedType(n int) types.Type {
|
||||
nt.SetUnderlying(underlying.Underlying())
|
||||
}
|
||||
|
||||
// collect associated methods
|
||||
for p.tok == scanner.Ident {
|
||||
p.expectKeyword("func")
|
||||
p.expect('(')
|
||||
receiver, _ := p.parseParam(pkg)
|
||||
p.expect(')')
|
||||
name := p.parseName()
|
||||
params, isVariadic := p.parseParamList(pkg)
|
||||
results := p.parseResultList(pkg)
|
||||
p.expect(';')
|
||||
if p.tok == '\n' {
|
||||
p.next()
|
||||
// collect associated methods
|
||||
for p.tok == scanner.Ident {
|
||||
p.expectKeyword("func")
|
||||
p.expect('(')
|
||||
receiver, _ := p.parseParam(pkg)
|
||||
p.expect(')')
|
||||
name := p.parseName()
|
||||
params, isVariadic := p.parseParamList(pkg)
|
||||
results := p.parseResultList(pkg)
|
||||
p.expectEOL()
|
||||
|
||||
sig := types.NewSignature(receiver, params, results, isVariadic)
|
||||
nt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
|
||||
sig := types.NewSignature(receiver, params, results, isVariadic)
|
||||
nt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
|
||||
}
|
||||
}
|
||||
|
||||
return nt
|
||||
@ -740,11 +750,12 @@ func (p *parser) parsePackageInit() PackageInit {
|
||||
return PackageInit{Name: name, InitFunc: initfunc, Priority: priority}
|
||||
}
|
||||
|
||||
// Throw away tokens until we see a ';'. If we see a '<', attempt to parse as a type.
|
||||
// Throw away tokens until we see a newline or ';'.
|
||||
// If we see a '<', attempt to parse as a type.
|
||||
func (p *parser) discardDirectiveWhileParsingTypes(pkg *types.Package) {
|
||||
for {
|
||||
switch p.tok {
|
||||
case ';':
|
||||
case '\n', ';':
|
||||
return
|
||||
case '<':
|
||||
p.parseType(pkg)
|
||||
@ -763,7 +774,7 @@ func (p *parser) maybeCreatePackage() {
|
||||
}
|
||||
}
|
||||
|
||||
// InitDataDirective = ( "v1" | "v2" ) ";" |
|
||||
// InitDataDirective = ( "v1" | "v2" | "v3" ) ";" |
|
||||
// "priority" int ";" |
|
||||
// "init" { PackageInit } ";" |
|
||||
// "checksum" unquotedString ";" .
|
||||
@ -774,31 +785,32 @@ func (p *parser) parseInitDataDirective() {
|
||||
}
|
||||
|
||||
switch p.lit {
|
||||
case "v1", "v2":
|
||||
case "v1", "v2", "v3":
|
||||
p.version = p.lit
|
||||
p.next()
|
||||
p.expect(';')
|
||||
p.expect('\n')
|
||||
|
||||
case "priority":
|
||||
p.next()
|
||||
p.initdata.Priority = int(p.parseInt())
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "init":
|
||||
p.next()
|
||||
for p.tok != ';' && p.tok != scanner.EOF {
|
||||
for p.tok != '\n' && p.tok != ';' && p.tok != scanner.EOF {
|
||||
p.initdata.Inits = append(p.initdata.Inits, p.parsePackageInit())
|
||||
}
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "init_graph":
|
||||
p.next()
|
||||
// The graph data is thrown away for now.
|
||||
for p.tok != ';' && p.tok != scanner.EOF {
|
||||
for p.tok != '\n' && p.tok != ';' && p.tok != scanner.EOF {
|
||||
p.parseInt()
|
||||
p.parseInt()
|
||||
}
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "checksum":
|
||||
// Don't let the scanner try to parse the checksum as a number.
|
||||
@ -808,7 +820,7 @@ func (p *parser) parseInitDataDirective() {
|
||||
p.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats
|
||||
p.next()
|
||||
p.parseUnquotedString()
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
default:
|
||||
p.errorf("unexpected identifier: %q", p.lit)
|
||||
@ -831,29 +843,29 @@ func (p *parser) parseDirective() {
|
||||
}
|
||||
|
||||
switch p.lit {
|
||||
case "v1", "v2", "priority", "init", "init_graph", "checksum":
|
||||
case "v1", "v2", "v3", "priority", "init", "init_graph", "checksum":
|
||||
p.parseInitDataDirective()
|
||||
|
||||
case "package":
|
||||
p.next()
|
||||
p.pkgname = p.parseUnquotedString()
|
||||
p.maybeCreatePackage()
|
||||
if p.version == "v2" && p.tok != ';' {
|
||||
if p.version != "v1" && p.tok != '\n' && p.tok != ';' {
|
||||
p.parseUnquotedString()
|
||||
p.parseUnquotedString()
|
||||
}
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "pkgpath":
|
||||
p.next()
|
||||
p.pkgpath = p.parseUnquotedString()
|
||||
p.maybeCreatePackage()
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "prefix":
|
||||
p.next()
|
||||
p.pkgpath = p.parseUnquotedString()
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "import":
|
||||
p.next()
|
||||
@ -861,7 +873,7 @@ func (p *parser) parseDirective() {
|
||||
pkgpath := p.parseUnquotedString()
|
||||
p.getPkg(pkgpath, pkgname)
|
||||
p.parseString()
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "func":
|
||||
p.next()
|
||||
@ -869,24 +881,24 @@ func (p *parser) parseDirective() {
|
||||
if fun != nil {
|
||||
p.pkg.Scope().Insert(fun)
|
||||
}
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "type":
|
||||
p.next()
|
||||
p.parseType(p.pkg)
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "var":
|
||||
p.next()
|
||||
v := p.parseVar(p.pkg)
|
||||
p.pkg.Scope().Insert(v)
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
case "const":
|
||||
p.next()
|
||||
c := p.parseConst(p.pkg)
|
||||
p.pkg.Scope().Insert(c)
|
||||
p.expect(';')
|
||||
p.expectEOL()
|
||||
|
||||
default:
|
||||
p.errorf("unexpected identifier: %q", p.lit)
|
||||
|
@ -19,7 +19,7 @@ var typeParserTests = []struct {
|
||||
{id: "foo", typ: "<type 1 *<type -19>>", want: "*error"},
|
||||
{id: "foo", typ: "<type 1 *any>", want: "unsafe.Pointer"},
|
||||
{id: "foo", typ: "<type 1 \"Bar\" <type 2 *<type 1>>>", want: "foo.Bar", underlying: "*foo.Bar"},
|
||||
{id: "foo", typ: "<type 1 \"bar.Foo\" \"bar\" <type -1> func (? <type 1>) M (); >", want: "bar.Foo", underlying: "int8", methods: "func (bar.Foo).M()"},
|
||||
{id: "foo", typ: "<type 1 \"bar.Foo\" \"bar\" <type -1>\n func (? <type 1>) M ()\n>", want: "bar.Foo", underlying: "int8", methods: "func (bar.Foo).M()"},
|
||||
{id: "foo", typ: "<type 1 \".bar.foo\" \"bar\" <type -1>>", want: "bar.foo", underlying: "int8"},
|
||||
{id: "foo", typ: "<type 1 []<type -1>>", want: "[]int8"},
|
||||
{id: "foo", typ: "<type 1 [42]<type -1>>", want: "[42]int8"},
|
||||
|
Loading…
Reference in New Issue
Block a user