Commit e8ce849a by Ian Lance Taylor

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