wcc,lib/ww/syntax: resolve qualified struct-literal pkg.Type{...} (#76)

The parser folded a qualified type pkg.Type into two different node shapes by position: declaration position collapsed it into one N_TNAME (resolved via the strrchr-leaf path), but literal position left an N_DOT chain that the struct-literal typeref handoff had no resolver arm for, so pkg.Type{...} rejected with "expected type expression".

Normalize the literal-position N_DOT chain into the same source-order N_TNAME the declaration path emits, reusing the existing resolver; no new checker arm. cstage flattens at parseprimary struct-lit handoff; wwstage (no token peek) folds dots in parsepostfix and normalizes there, guarding numeric tuple components and staying in the postfix loop so trailing ops still chain. Both stages emit identical N_STRUCTLIT(N_TNAME). Prereq for qualifying wcc syntax refs (#75).
This commit is contained in:
2026-06-16 22:20:42 +09:00
parent 697e413113
commit 01b657a7ff
6 changed files with 656 additions and 1 deletions

View File

@@ -427,6 +427,28 @@ parsearglist(Parser *p, Tkind close)
return head;
}
/* #76: a qualified path `pkg.Type` reaches a struct-literal handoff as an
* N_DOT chain (parseprimary's dotted fold). Flatten it into one N_TNAME
* whose str joins the chain in SOURCE order — byte-identical to parsetype's
* dotted collapse (parse.c: aprintf("%s.%s", ...)) — so resolve_type's
* existing N_TNAME arm resolves it with no new checker arm. */
static const char *
flattendotstr(Parser *p, Node *n)
{
if (n->kind == N_IDENT)
return n->str;
return aprintf(p->a, "%s.%s", flattendotstr(p, n->lhs), n->str);
}
static Node *
flattendot(Parser *p, Node *n)
{
Node *t = newnode(p->a, N_TNAME, n->pos);
t->str = flattendotstr(p, n);
t->strlen = strlen(t->str);
return t;
}
static Node *
parsestructlit(Parser *p, Node *typeref)
{
@@ -636,8 +658,13 @@ parseprimary(Parser *p)
n = mr;
}
/* struct literal: ident '{' ... '}' (only if ident-shaped) */
if (p->cur.kind == TK_LBRACE)
if (p->cur.kind == TK_LBRACE) {
/* #76: bare `Foo{}` keeps the N_IDENT fast-path; a
* qualified `pkg.Type{}` (N_DOT chain) flattens first. */
if (n->kind == N_DOT)
n = flattendot(p, n);
return parsestructlit(p, n);
}
return n;
}
default: