ww imports: require imports before declarations

This commit is contained in:
2026-08-21 19:20:52 +09:00
parent b03bbb1428
commit ee4573bf55
9 changed files with 730 additions and 8 deletions

View File

@@ -1361,6 +1361,10 @@ parseimports(Parser *p)
Node *head = NULL, *tail = NULL;
Node *packages = NULL, *packagetail = NULL;
int sawpackage = 0;
/* Go source files admit one import section before ordinary declarations.
* Keep recovery permissive, but diagnose the first import in each later
* section. Compiler-owned bundle markers begin a fresh source section. */
int previmport = 1;
while (p->cur.kind != TK_EOF) {
/* Compiler/driver bundle markers carry package identity out of
@@ -1368,6 +1372,7 @@ parseimports(Parser *p)
* the following package clause and imports. */
if (p->cur.kind == TK_MODPATH) {
sawpackage = 0;
previmport = 1;
p->sourceid++;
p->pathmod = p->cur.text;
p->curmod = p->cur.text;
@@ -1379,6 +1384,7 @@ parseimports(Parser *p)
if (p->cur.kind == TK_MODRESET) {
const char *rp = p->cur.text;
sawpackage = 0;
previmport = 1;
p->sourceid++;
advance(p);
p->pathmod = NULL;
@@ -1389,6 +1395,7 @@ parseimports(Parser *p)
}
if (p->cur.kind == TK_MODULE) {
Pos pp = p->cur.pos;
previmport = 1;
advance(p);
if (p->cur.kind != TK_IDENT) {
errorf(p->cur.pos, "invalid or missing package clause");
@@ -1426,6 +1433,12 @@ parseimports(Parser *p)
sawpackage = 1;
}
if (p->cur.kind == TK_USE) {
if (!previmport) {
errorf(p->cur.pos,
"imports must appear before other declarations");
p->errs++;
}
previmport = 1;
Node *d = parseuse(p);
d->module = p->curmod;
d->pkgname = p->curpkg;
@@ -1437,6 +1450,7 @@ parseimports(Parser *p)
tail = d;
continue;
}
previmport = 0;
if (p->cur.kind == TK_AT) {
skipimportattrs(p);
if (p->cur.kind == TK_EXPORT) advance(p);
@@ -1574,6 +1588,9 @@ parsefile(Parser *p)
Node *head = NULL, *tail = NULL;
Node *packages = NULL, *packagetail = NULL;
int sawpackage = 0;
/* Semantic twin of parseimports: full/direct parsing reports the same
* per-source import-section ordering error while retaining the AST. */
int previmport = 1;
while (p->cur.kind != TK_EOF) {
/* `package foo;` — directory-as-module declaration. Every
* primary section opens with one (`package main;` for an
@@ -1584,6 +1601,7 @@ parsefile(Parser *p)
if (p->cur.kind == TK_MODULE) {
Pos packagepos = p->cur.pos;
sawpackage = 1;
previmport = 1;
advance(p);
const char *name = expectident(p);
expect(p, TK_SEMI);
@@ -1611,6 +1629,7 @@ parsefile(Parser *p)
* root-only bare-`main` rule, #32). */
if (p->cur.kind == TK_MODPATH) {
sawpackage = 0;
previmport = 1;
p->sourceid++;
p->pathmod = p->cur.text;
p->curmod = p->cur.text;
@@ -1630,6 +1649,7 @@ parsefile(Parser *p)
* decls to bare — that usage is deliberate-only. */
if (p->cur.kind == TK_MODRESET) {
sawpackage = 0;
previmport = 1;
p->sourceid++;
/* #57: a path-carrying reset (sep primary body) mangles
* decls on the dotted path so definer == importer, but
@@ -1668,6 +1688,13 @@ parsefile(Parser *p)
p->errs++;
sawpackage = 1;
}
int thisimport = p->cur.kind == TK_USE;
if (thisimport && !previmport) {
errorf(p->cur.pos,
"imports must appear before other declarations");
p->errs++;
}
previmport = thisimport;
Node *attrs = parseattrs(p);
int exp = accept(p, TK_EXPORT);
Node *d = NULL;