compiler: implement blank package name semantics
This commit is contained in:
@@ -133,6 +133,9 @@ export type node = struct {
|
||||
usefile: str, // N_USE: first spec token (alias, otherwise path)
|
||||
useline: i32,
|
||||
usecol: i32,
|
||||
usepathfile: str,// N_USE: first path token, independent of alias
|
||||
usepathline: i32,
|
||||
usepathcol: i32,
|
||||
usepkgname: str,// N_USE: imported declared package name
|
||||
useblank: i32, // N_USE: `_` spelling; no source binding
|
||||
pkgname: str, // declared package name; independent of canonical nmod
|
||||
@@ -153,7 +156,7 @@ export fn newnode(k: nkind, file: str, line: i32, col: i32) *node = {
|
||||
// fval cast-init: 990's wwdump TK_FLOAT diff requires this file
|
||||
// to tokenise identically through C and ww (lex.ww:382 has the
|
||||
// same workaround for the cstage %g-formats vs ww-skips divergence).
|
||||
let n: *node = alloc(node{kind=k, file=file, line=line, col=col, op=tkind.TK_NONE, str="", uval=0u64, fval=0: f64, lhs=nil, rhs=nil, cond=nil, body=nil, els=nil, list=nil, next=nil, attr=nil, exported=0, packed=0, type_=nil, tsuffix="", nmod="", usesource="", usepath="", usealias="", usefile="", useline=0, usecol=0, usepkgname="", useblank=0, pkgname="", sourceid=0, used=0, initfn=0, initsynthetic=0, runtimeinit=0, initorder=0u64, linksym="", refdecl=nil, initmark=0u64, imported=0})!;
|
||||
let n: *node = alloc(node{kind=k, file=file, line=line, col=col, op=tkind.TK_NONE, str="", uval=0u64, fval=0: f64, lhs=nil, rhs=nil, cond=nil, body=nil, els=nil, list=nil, next=nil, attr=nil, exported=0, packed=0, type_=nil, tsuffix="", nmod="", usesource="", usepath="", usealias="", usefile="", useline=0, usecol=0, usepathfile="", usepathline=0, usepathcol=0, usepkgname="", useblank=0, pkgname="", sourceid=0, used=0, initfn=0, initsynthetic=0, runtimeinit=0, initorder=0u64, linksym="", refdecl=nil, initmark=0u64, imported=0})!;
|
||||
return n;
|
||||
};
|
||||
|
||||
|
||||
@@ -19,19 +19,31 @@ fn parseuse(p: *parser) *node = {
|
||||
n.usefile = p.curfile;
|
||||
n.useline = p.curline;
|
||||
n.usecol = p.curcol;
|
||||
let pathfile: str = p.curfile;
|
||||
let pathline: i32 = p.curline;
|
||||
let pathcol: i32 = p.curcol;
|
||||
let alias: str;
|
||||
let first: str;
|
||||
if (p.curkind == tkind.TK_UNDER) {
|
||||
n.useblank = 1;
|
||||
advance(p);
|
||||
pathfile = p.curfile;
|
||||
pathline = p.curline;
|
||||
pathcol = p.curcol;
|
||||
expectident(p, &first);
|
||||
} else {
|
||||
expectident(p, &first);
|
||||
if (p.curkind == tkind.TK_IDENT) {
|
||||
alias = first;
|
||||
pathfile = p.curfile;
|
||||
pathline = p.curline;
|
||||
pathcol = p.curcol;
|
||||
expectident(p, &first);
|
||||
};
|
||||
};
|
||||
n.usepathfile = pathfile;
|
||||
n.usepathline = pathline;
|
||||
n.usepathcol = pathcol;
|
||||
let leaf: str = first;
|
||||
let path: str = leaf;
|
||||
for (p.curkind == tkind.TK_DOT) {
|
||||
|
||||
@@ -145,6 +145,19 @@ fn expectident(p: *parser, into: *str) bool = {
|
||||
return true;
|
||||
};
|
||||
|
||||
// Package declarations admit the blank identifier syntactically. Keep this
|
||||
// private to the package-name slot; the checker owns BlankPkgName rejection.
|
||||
fn expectpackagename(p: *parser, into: *str) bool = {
|
||||
if (p.curkind != tkind.TK_IDENT && p.curkind != tkind.TK_UNDER) {
|
||||
errmsg(p, strings.concat("expected identifier, got ",
|
||||
tokname(p.curkind)));
|
||||
return false;
|
||||
};
|
||||
*into = p.curtext;
|
||||
advance(p);
|
||||
return true;
|
||||
};
|
||||
|
||||
// On `_`, returns "" so the checker skips scope_define for the binding.
|
||||
fn expectbindname(p: *parser, into: *str) bool = {
|
||||
if (p.curkind == tkind.TK_UNDER) {
|
||||
@@ -513,11 +526,17 @@ fn parseheaderuse(p: *parser) *node = {
|
||||
n.usefile = p.curfile;
|
||||
n.useline = p.curline;
|
||||
n.usecol = p.curcol;
|
||||
let pathfile: str = p.curfile;
|
||||
let pathline: i32 = p.curline;
|
||||
let pathcol: i32 = p.curcol;
|
||||
let alias: str;
|
||||
let first: str;
|
||||
if (p.curkind == tkind.TK_UNDER) {
|
||||
n.useblank = 1;
|
||||
advance(p);
|
||||
pathfile = p.curfile;
|
||||
pathline = p.curline;
|
||||
pathcol = p.curcol;
|
||||
};
|
||||
if (p.curkind != tkind.TK_IDENT) {
|
||||
errmsg(p, strings.concat("expected identifier, got ",
|
||||
@@ -528,9 +547,15 @@ fn parseheaderuse(p: *parser) *node = {
|
||||
advance(p);
|
||||
if (n.useblank == 0 && p.curkind == tkind.TK_IDENT) {
|
||||
alias = first;
|
||||
pathfile = p.curfile;
|
||||
pathline = p.curline;
|
||||
pathcol = p.curcol;
|
||||
first = p.curtext;
|
||||
advance(p);
|
||||
};
|
||||
n.usepathfile = pathfile;
|
||||
n.usepathline = pathline;
|
||||
n.usepathcol = pathcol;
|
||||
let leaf: str = first;
|
||||
let path: str = leaf;
|
||||
for (p.curkind == tkind.TK_DOT) {
|
||||
@@ -585,12 +610,12 @@ export fn parsepackageheader(p: *parser) *node = {
|
||||
let pl: i32 = p.curline;
|
||||
let pc: i32 = p.curcol;
|
||||
advance(p);
|
||||
if (p.curkind != tkind.TK_IDENT) {
|
||||
if (p.curkind != tkind.TK_IDENT && p.curkind != tkind.TK_UNDER) {
|
||||
errmsg(p, "invalid or missing package clause");
|
||||
return f;
|
||||
};
|
||||
let name: str = p.curtext;
|
||||
advance(p);
|
||||
let name: str;
|
||||
expectpackagename(p, &name);
|
||||
if (p.curkind != tkind.TK_SEMI) {
|
||||
errmsg(p, "expected ';' after package name");
|
||||
return f;
|
||||
@@ -659,14 +684,15 @@ export fn parseimports(p: *parser) *node = {
|
||||
let pc: i32 = p.curcol;
|
||||
previmport = true;
|
||||
advance(p);
|
||||
if (p.curkind != tkind.TK_IDENT) {
|
||||
if (p.curkind != tkind.TK_IDENT
|
||||
&& p.curkind != tkind.TK_UNDER) {
|
||||
errmsg(p, "invalid or missing package clause");
|
||||
sawpackage = true;
|
||||
skipimportdecl(p);
|
||||
continue;
|
||||
};
|
||||
let name: str;
|
||||
expectident(p, &name);
|
||||
expectpackagename(p, &name);
|
||||
expecttok(p, tkind.TK_SEMI, "expected ';' after module name");
|
||||
p.curpkg = name;
|
||||
if (p.pathmod.len == 0 && p.resetmod.len == 0) {
|
||||
@@ -771,14 +797,25 @@ export fn parsefile(p: *parser) *node = {
|
||||
sawpackage = 1;
|
||||
previmport = true;
|
||||
advance(p);
|
||||
let nf: str = p.curfile;
|
||||
let nl: i32 = p.curline;
|
||||
let nc: i32 = p.curcol;
|
||||
let name: str;
|
||||
expectident(p, &name);
|
||||
expectpackagename(p, &name);
|
||||
expecttok(p, tkind.TK_SEMI, "expected ';' after module name");
|
||||
p.curpkg = name;
|
||||
if (p.pathmod.len == 0 && p.resetmod.len == 0) {
|
||||
p.curmod = name;
|
||||
};
|
||||
let pm: *node = newnode(nkind.N_FILE, pf, pl, pc);
|
||||
let mf: str = pf;
|
||||
let ml: i32 = pl;
|
||||
let mc: i32 = pc;
|
||||
if (streq(name, "_")) {
|
||||
mf = nf;
|
||||
ml = nl;
|
||||
mc = nc;
|
||||
};
|
||||
let pm: *node = newnode(nkind.N_FILE, mf, ml, mc);
|
||||
pm.nmod = p.curmod;
|
||||
pm.pkgname = name;
|
||||
pm.sourceid = p.sourceid;
|
||||
|
||||
Reference in New Issue
Block a user