Files
ww/test/wcc/200_parse.c
Hojun-Cho 83f5956df2 test: banner purge + WHY-only comment sweep (rule 8)
Every section banner dies (103 -> 0) across test/lang, the observer
suites, the C carriers, and the five comment-heavy corpus fixtures;
banner provenance (#N cites, carrier numbers, repair-cluster labels)
folded into headers or adjacent WHY comments. Narration deleted; row
provenance, ref cites, divergence pins, and layout contracts kept
(fwd-ref decl-order guards and bootstrap-gate corpus rationale
restored where the sweep over-cut). Comment-only proven: all 3742
wwbuild workdir .s byte-identical before/after; test-commit and
test-byteid (161 lang + 1399 data, 0 pinned-divergent) green.
2026-08-08 21:40:23 +09:00

189 lines
6.0 KiB
C

/*
* Shape rows compare astprint output against a substring, not a full
* golden, so tests stay readable without binding to every position
* field.
*/
#include "ww.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "wwtestpkg.h"
static int
must_parse(const char *src)
{
Arena *a = newarena();
Lex l;
Parser p;
char *ws = wwtest_wrap(src);
lexinit(&l, a, "<test>", ws, strlen(ws));
parserinit(&p, a, &l);
Node *n = parsefile(&p);
int ok = (n != NULL && p.errs == 0 && l.errs == 0);
free(ws);
freearena(a);
return ok;
}
static char *
parse_to_str(const char *src, int *errs)
{
Arena *a = newarena();
Lex l;
Parser p;
char *ws = wwtest_wrap(src);
lexinit(&l, a, "<test>", ws, strlen(ws));
parserinit(&p, a, &l);
Node *n = parsefile(&p);
*errs = p.errs + l.errs;
char *buf = NULL;
size_t len = 0;
FILE *f = open_memstream(&buf, &len);
if (f == NULL) {
free(ws);
freearena(a);
return NULL;
}
astprint(f, n);
fclose(f);
char *out = malloc(len + 1);
memcpy(out, buf, len);
out[len] = '\0';
free(buf);
free(ws);
freearena(a);
return out;
}
static int
must_contain(const char *src, const char *needle)
{
int errs;
char *got = parse_to_str(src, &errs);
if (got == NULL || errs > 0) {
fprintf(stderr, "parse errs=%d:\n%s\n", errs, src);
free(got);
return 0;
}
if (strstr(got, needle) == NULL) {
fprintf(stderr, "shape mismatch:\n src: %s\n"
" want: %s\n got:\n%s\n", src, needle, got);
free(got);
return 0;
}
free(got);
return 1;
}
int
main(void)
{
int fail = 0;
const char *parses[] = {
"import io;",
"import io.bufio;",
"def MAX: i32 = 4096;",
"export def MAX: i32 = 4096;",
"type point = struct { x: i32, y: i32 };",
"type stream = fn(b: []u8) i32;",
"type chans = chan i32;",
"type box = struct { p: *point, n: i32, items: []i32 };",
"type arr = [16]u8;",
"fn nop() void = {};",
"export fn id(x: i32) i32 = { return x; };",
"fn add(a: i32, b: i32) i32 = { return a + b; };",
"@symbol(\"malloc\") fn cmalloc(n: u64) *void;",
"fn varadic(a: i32, ...) void;",
"fn f() void = { let x: i32 = 0; let y = 1.5; let s: str = \"hi\"; };",
"fn f() void = { if (x > 0) { return; } else { x += 1; }; };",
"fn f() void = { for (let i: i32 = 0; i < 10; i += 1) { x += i; }; };",
"fn f() void = { for (i < 10) { i += 1; }; };",
"fn f() void = { for () { i += 1; }; };",
"fn f() void = { defer free(p); };",
"fn f() void = { switch (x) { case 1, 2: y = 1; case: y = 0; }; };",
"fn ptr(p: *point) i32 = { return p.x; };",
"fn cast() void = { let x = (5 + 1): i64; };",
"fn deref(p: *i32) i32 = { return *p; };",
"fn addr(x: i32) *i32 = { return &x; };",
"fn lit() void = { let p: point = point { x = 1, y = 2 }; };",
"fn pkg() void = { fmt.println(1); };",
"fn arr() void = { let a = [1, 2, 3]; };",
"fn idx() i32 = { return a[3]; };",
"fn neg() i32 = { return -a + ~b * !c; };",
"fn ops() void = { x = 1; x += 1; x -= 1; x *= 2; x /= 2; x %= 2; "
"x &= 1; x |= 1; x ^= 1; x <<= 1; x >>= 1; };",
"fn cmp() bool = { return a == b && c != d || e < f && g <= h; };",
"fn bits() i32 = { return (a & b) | (c ^ d); };",
"fn shift() i32 = { return a << 2 | b >> 1; };",
"fn nested() void = { if (a > 0) { if (b > 0) { c = 1; }; }; };",
"fn many(a: i32, b: i32, c: i32, d: i32, e: i32) i32 = "
"{ return a + b * c - d / e; };",
"fn slc(s: []u8) []u8 = { return s; };",
"fn ssn(p: **point) i32 = { return (*p).x; };",
"fn arrptr(p: *[16]u8) u8 = { return p[0]; };",
"fn fnt(f: fn(i32) i32, x: i32) i32 = { return f(x); };",
"fn anontype() void = { let f: fn(i32) i32 = id; };",
"import io;\nimport fmt;\ndef N: i32 = 8;\ntype p = struct{x:i32};\nfn f() void = {};",
"@symbol(\"strlen\") fn cstrlen(s: *u8) u64;",
"fn f(a: i32, b: i32,) void = {};",
"fn f() void = { let p: *i32 = nil; let x: bool = true; let y: bool = false; };",
"fn ch() void = { let c: chan i32; let v = <-c; };",
"fn lit2() void = { let q = box { p = nil, n = 0, items = [1, 2] }; };",
"fn f() void = { defer close(fd); return; };",
"fn f() void = { for () { if (x) { break; }; continue; }; };",
"fn deep() i32 = { return ((((((1 + 2) * 3) - 4) / 5) % 6) << 7); };",
"fn ix() i32 = { return a[b][c[d]]; };",
"fn dot() i32 = { return a.b.c.d; };",
"fn cc() i32 = { return f()()(); };",
"fn mx() i32 = { return obj.method(arg)[idx].field; };",
"fn divmod(a: i64, b: i64) (i64, i64) = { return a / b, a % b; };",
"fn try() (i32, str) = { return 0, \"\"; };",
"fn use_tuple() void = { let q, r = divmod(10, 3); };",
"fn assign_tuple() void = { q, r = divmod(10, 3); };",
/* Hare-style type test / type assertion (postfix) */
"fn ti(r: (i64 | i32)) bool = { return r is i64; };",
"fn ai(r: (i64 | i32)) i64 = { return r as i64; };",
"fn br(r: (i64 | str)) i32 = { if (r is i64) { return 1; }; return 0; };",
/* Hare-style enum types */
"type color = enum { RED, GREEN, BLUE, };",
"type mode = enum u8 { NONE = 0, READ = 1, WRITE = 2, RDWR = READ | WRITE };",
"type whence = enum i32 { SET = 0, CUR, END };",
};
int n = sizeof parses / sizeof parses[0];
for (int i = 0; i < n; i++) {
if (!must_parse(parses[i])) {
fprintf(stderr, "parse fail [%d]: %s\n", i, parses[i]);
fail++;
}
}
if (!must_contain("import io;", "(use \"io\"")) fail++;
if (!must_contain("def N: i32 = 4;", "(def \"N\"")) fail++;
if (!must_contain("def N: i32 = 4;", "(int 4")) fail++;
if (!must_contain("export fn f() void = {};", "(fn \"f\" export")) fail++;
if (!must_contain("type p = struct { x: i32 };", "(typedecl \"p\"")) fail++;
if (!must_contain("fn f() i32 = { return 1; };", "(return")) fail++;
if (!must_contain("fn f() void = { x = 1; };", "(assign =")) fail++;
if (!must_contain("fn f() i32 = { return a + b; };", "(bin +")) fail++;
if (!must_contain("@symbol(\"x\") fn f() void;", "(attr \"symbol\""))fail++;
if (fail) {
fprintf(stderr, "%d parse tests failed\n", fail);
return 1;
}
printf("parse: %d/%d ok + 9 shape ok\n", n, n);
return 0;
}