lib/ww + wcc + w6c + wwdump: strip *arena cascade (γ-6)
amalloc has 0 callers post-γ-2; the *arena threaded through
newnode/newscope/newtype/prim/typesinit/type{ptr,slice,array,chan,
named}/lexinit/parserinit/joindotted/checkinit/arenau64tos/cgeninit
and the scope.a / tctx.a / lex.a / parser.a / checker.a / cgen.a
fields are vestigial.
Drop `import mem;` from 15 files, remove six struct fields, strip
*arena from 14 signatures, update ~120 call sites across lib/ww +
wcc + w6c + wwdump. selfhost/test/sym_link.ww fixture drops the
newarena/freearena probe; still exits 42 on scopedefine/scopelookup.
Both main.combined.ww auto-regenerated.
Comments retidied: typ.ww "once per arena" → "once per program";
parse.ww drops "arena-build" qualifier on joindotted; sym.ww drops
mem-sibling-imports rationale.
Verified 132/132 incl. 994_w6c_ww + 995_self_rebuild byte-identity
(the primary symmetric-stages gate).
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,6 @@ package main;
|
||||
|
||||
import os;
|
||||
import rt;
|
||||
import mem;
|
||||
import strings;
|
||||
import tok;
|
||||
import lex;
|
||||
@@ -135,7 +134,6 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
os.close(ofd);
|
||||
};
|
||||
|
||||
let ar: *arena = newarena();
|
||||
let nlen: u64 = cstrlen(src);
|
||||
let view: str;
|
||||
view.ptr = src;
|
||||
@@ -143,10 +141,10 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
let fname: str = strings.dup(view);
|
||||
|
||||
let l: lex;
|
||||
lexinit(&l, ar, fname, buf, blen);
|
||||
lexinit(&l, fname, buf, blen);
|
||||
|
||||
let ps: parser;
|
||||
parserinit(&ps, ar, &l);
|
||||
parserinit(&ps, &l);
|
||||
let f: *node = parsefile(&ps);
|
||||
// Gate cgen on parse-stage errors. Mirrors cmd/w6c/main.c's
|
||||
// `if (l.errs || p.errs) return 1;` — broken AST otherwise reaches
|
||||
@@ -160,14 +158,14 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
// enum↔int reinterpret, #53 N_BLOCK scoping, #55 nominal-first variant
|
||||
// compare, #56 bare-leaf same-module preference.
|
||||
let tc: tctx;
|
||||
typesinit(&tc, ar);
|
||||
typesinit(&tc);
|
||||
let ck: checker;
|
||||
checkinit(&ck, ar, &tc);
|
||||
checkinit(&ck, &tc);
|
||||
checkfile(&ck, f);
|
||||
if (ck.errs > 0) { return 1; };
|
||||
|
||||
let cg: cgen;
|
||||
cgeninit(&cg, ar);
|
||||
cgeninit(&cg);
|
||||
cgfile(&cg, f);
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
package wcc;
|
||||
|
||||
import os;
|
||||
import mem;
|
||||
import ast;
|
||||
import tok;
|
||||
import typ;
|
||||
@@ -68,9 +67,9 @@ fn collectaliases(c: *cgen, file: *node) void = {
|
||||
// same-module / any-match passes in aliaslookup then let a local
|
||||
// `type nomem = !void;` shadow this fallback within its module.
|
||||
let empty: str;
|
||||
let tnvoid: *node = newnode(c.a, nkind.N_TNAME, empty, 0, 0);
|
||||
let tnvoid: *node = newnode(nkind.N_TNAME, empty, 0, 0);
|
||||
tnvoid.str = "void";
|
||||
let bang: *node = newnode(c.a, nkind.N_TBANG, empty, 0, 0);
|
||||
let bang: *node = newnode(nkind.N_TBANG, empty, 0, 0);
|
||||
bang.lhs = tnvoid;
|
||||
let nomemal: *aliasent = alloc(aliasent{aname="nomem", amod=empty, target=bang, aanext=nil})!;
|
||||
c.aliases = nomemal;
|
||||
@@ -435,7 +434,6 @@ def LOOP_MAX: i32 = 16;
|
||||
def DEFER_MAX: i32 = 16;
|
||||
|
||||
type cgen = struct {
|
||||
a: *arena,
|
||||
locals: *local,
|
||||
// atlocals — persistent registry of `@`-prefix scratch slots
|
||||
// for the current fn. cgblock save/restores c.locals to scope
|
||||
@@ -522,8 +520,7 @@ type letvar = struct {
|
||||
lvnext: *letvar,
|
||||
};
|
||||
|
||||
fn cgeninit(c: *cgen, a: *arena) void = {
|
||||
c.a = a;
|
||||
fn cgeninit(c: *cgen) void = {
|
||||
c.locals = nil;
|
||||
c.atlocals = nil;
|
||||
c.frame = 0;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
package wcc;
|
||||
|
||||
import os;
|
||||
import mem;
|
||||
import ast;
|
||||
import tok;
|
||||
import typ;
|
||||
@@ -339,7 +338,7 @@ fn cgfnparams(c: *cgen, params: *node) void = {
|
||||
};
|
||||
|
||||
fn cgfn(c: *cgen, fn_: *node) void = {
|
||||
cgeninit(c, c.a);
|
||||
cgeninit(c);
|
||||
c.fnname = fn_.str;
|
||||
c.curmod = fn_.nmod;
|
||||
c.fnret = fn_.lhs;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package wcc;
|
||||
|
||||
import os;
|
||||
import mem;
|
||||
import ast;
|
||||
import tok;
|
||||
import typ;
|
||||
@@ -3172,7 +3171,7 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff((soff + 16): i64);
|
||||
emitline("(BP)\n");
|
||||
let sn: *node = newnode(c.a, nkind.N_IDENT,
|
||||
let sn: *node = newnode(nkind.N_IDENT,
|
||||
"", 0, 0);
|
||||
sn.str = sname;
|
||||
if (prevarg == nil) { n.list = sn; }
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
package wcc;
|
||||
|
||||
import os;
|
||||
import mem;
|
||||
import ast;
|
||||
import tok;
|
||||
import typ;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package wcc;
|
||||
|
||||
import os;
|
||||
import mem;
|
||||
import ast;
|
||||
import tok;
|
||||
import typ;
|
||||
@@ -30,7 +29,7 @@ import strconv;
|
||||
// (caller side) both advertise their effective type as []ELEM —
|
||||
// every isslicetype / nodeisslice check then succeeds naturally.
|
||||
fn slicewrap(c: *cgen, elem: *node) *node = {
|
||||
let s: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0);
|
||||
let s: *node = newnode(nkind.N_TSLICE, "", 0, 0);
|
||||
s.lhs = elem;
|
||||
return s;
|
||||
};
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
package wcc;
|
||||
|
||||
import os;
|
||||
import mem;
|
||||
import tok;
|
||||
|
||||
type checker = struct {
|
||||
a: *arena,
|
||||
tc: *tctx,
|
||||
top: *scope,
|
||||
cur: *scope,
|
||||
@@ -72,11 +70,11 @@ fn seedprimitives(c: *checker) void = {
|
||||
// separate alias chain — see collectaliases in cgen.ww for the
|
||||
// companion seed.
|
||||
let empty: str;
|
||||
let tnvoid: *node = newnode(c.a, nkind.N_TNAME, empty, 0, 0);
|
||||
let tnvoid: *node = newnode(nkind.N_TNAME, empty, 0, 0);
|
||||
tnvoid.str = "void";
|
||||
let bang: *node = newnode(c.a, nkind.N_TBANG, empty, 0, 0);
|
||||
let bang: *node = newnode(nkind.N_TBANG, empty, 0, 0);
|
||||
bang.lhs = tnvoid;
|
||||
let nomemdecl: *node = newnode(c.a, nkind.N_TYPEDECL, empty, 0, 0);
|
||||
let nomemdecl: *node = newnode(nkind.N_TYPEDECL, empty, 0, 0);
|
||||
nomemdecl.str = "nomem";
|
||||
nomemdecl.lhs = bang;
|
||||
scopedefine(c.top, "nomem", skind.SK_TYPE, nil, nomemdecl);
|
||||
@@ -350,7 +348,7 @@ fn resolvewalk(c: *checker, n: *node) void = {
|
||||
if (k == nkind.N_MCASE) {
|
||||
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
|
||||
let outer: *scope = c.cur;
|
||||
c.cur = newscope(c.a, outer);
|
||||
c.cur = newscope(outer);
|
||||
let nm: str = n.str;
|
||||
if (nm.len > 0) {
|
||||
checkmoduleshadow(c, nm, "binding");
|
||||
@@ -372,7 +370,7 @@ fn resolvewalk(c: *checker, n: *node) void = {
|
||||
// Mirrors cstage cstmt N_BLOCK at cmd/wcc/check.c:1559-1566.
|
||||
if (k == nkind.N_BLOCK) {
|
||||
let outer: *scope = c.cur;
|
||||
c.cur = newscope(c.a, outer);
|
||||
c.cur = newscope(outer);
|
||||
let m: *node = n.list;
|
||||
for (m != nil) {
|
||||
resolvewalk(c, m);
|
||||
@@ -651,7 +649,7 @@ fn scruttype(c: *checker, e: *node) *node = {
|
||||
// exprtype to return primitive type nodes for literal
|
||||
// expressions. The arena keeps them around as long as the checker.
|
||||
fn mktname(c: *checker, nm: str) *node = {
|
||||
let n: *node = newnode(c.a, nkind.N_TNAME, "", 0, 0);
|
||||
let n: *node = newnode(nkind.N_TNAME, "", 0, 0);
|
||||
n.str = nm;
|
||||
return n;
|
||||
};
|
||||
@@ -838,7 +836,7 @@ fn astoffset(c: *checker, dot: *node) i64 = {
|
||||
// wwstage cgen only reads `uval` for N_INTLIT codegen so `str` is
|
||||
// just for the AST printer, but set it for parity with the parser's
|
||||
// own literal-emit shape.
|
||||
fn arenau64tos(a: *arena, v: u64) str = {
|
||||
fn arenau64tos(v: u64) str = {
|
||||
let buf: []u8 = alloc([], 24u64)!;
|
||||
let i: i32 = 23;
|
||||
buf[i] = 0u8;
|
||||
@@ -862,7 +860,7 @@ fn arenau64tos(a: *arena, v: u64) str = {
|
||||
fn foldtointlit(c: *checker, n: *node, v: i64) void = {
|
||||
n.kind = nkind.N_INTLIT;
|
||||
n.uval = v: u64;
|
||||
n.str = arenau64tos(c.a, v: u64);
|
||||
n.str = arenau64tos(v: u64);
|
||||
n.lhs = nil;
|
||||
n.list = nil;
|
||||
let empty: str;
|
||||
@@ -1014,11 +1012,11 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = {
|
||||
// site that needs iserror discrimination.
|
||||
r = tinfofornode(c, n.lhs);
|
||||
} else { if (k == nkind.N_TPTR) {
|
||||
r = typeptr(c.a, tinfofornode(c, n.lhs));
|
||||
r = typeptr(tinfofornode(c, n.lhs));
|
||||
} else { if (k == nkind.N_TSLICE) {
|
||||
r = typeslice(c.a, tinfofornode(c, n.lhs));
|
||||
r = typeslice(tinfofornode(c, n.lhs));
|
||||
} else { if (k == nkind.N_TCHAN) {
|
||||
r = typechan(c.a, tinfofornode(c, n.lhs));
|
||||
r = typechan(tinfofornode(c, n.lhs));
|
||||
} else { if (k == nkind.N_TARRAY) {
|
||||
// Cstage cmd/wcc/check.c:314-326: length must be an integer
|
||||
// literal (`[_]T` keeps alen=0 as the inferred-length sentinel
|
||||
@@ -1034,14 +1032,14 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = {
|
||||
if (n.rhs.kind == nkind.N_INTLIT) { elen = n.rhs.uval; };
|
||||
};
|
||||
let sub: *tinfo = tinfofornode(c, n.lhs);
|
||||
r = typearray(c.a, sub, elen);
|
||||
r = typearray(sub, elen);
|
||||
} else { if (k == nkind.N_TFN) {
|
||||
// Cstage cmd/wcc/check.c:437-466: function types are 8B / 8B
|
||||
// (call-target pointer shape). Pre-bind before recursing into
|
||||
// the return type so a recursive `type F = fn() F` self-ref
|
||||
// doesn't spin (cycle-break mirror of the TSTRUCT/TTAGGED
|
||||
// pattern below).
|
||||
r = newtype(c.a, tykind.TY_FN);
|
||||
r = newtype(tykind.TY_FN);
|
||||
r.size = 8u64;
|
||||
r.align = 8u64;
|
||||
r.slotsize = 8u64;
|
||||
@@ -1052,7 +1050,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = {
|
||||
// (default i32 = 4B/4B). Cgen's slotsize-TENUM fallback pads
|
||||
// to 8B per its stack-slot contract; tinfo.size carries the
|
||||
// raw storage width so size(EnumT) folds to the correct value.
|
||||
r = newtype(c.a, tykind.TY_ENUM);
|
||||
r = newtype(tykind.TY_ENUM);
|
||||
let storage: *tinfo = nil;
|
||||
if (n.lhs != nil) { storage = tinfofornode(c, n.lhs); };
|
||||
if (storage == nil) { storage = c.tc.tyi32; };
|
||||
@@ -1071,7 +1069,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = {
|
||||
// slotsize TTUPLE — narrow scalars pad to 8 (cgen spills each
|
||||
// tuple element into its own register / stack-slot eightbyte),
|
||||
// composites contribute their own ti.slotsize.
|
||||
r = newtype(c.a, tykind.TY_TUPLE);
|
||||
r = newtype(tykind.TY_TUPLE);
|
||||
tinfocachebind(c.tc, n, r);
|
||||
let total: u64 = 0u64;
|
||||
let slottotal: u64 = 0u64;
|
||||
@@ -1109,7 +1107,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = {
|
||||
// struct; size-derived alignment; final round to 8). That
|
||||
// slot total lands in ti.slotsize so the cgen fast-path can
|
||||
// graduate TY_STRUCT off the AST walker.
|
||||
r = newtype(c.a, tykind.TY_STRUCT);
|
||||
r = newtype(tykind.TY_STRUCT);
|
||||
tinfocachebind(c.tc, n, r);
|
||||
let off: u64 = 0u64;
|
||||
let maxalign: u64 = 1u64;
|
||||
@@ -1151,7 +1149,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = {
|
||||
// Cstage cmd/wcc/check.c:347-435: 8B tag + max(variant)
|
||||
// rounded up to 8. Pre-bind for cycle protection (recursive
|
||||
// sum-type shapes through NAMED variants).
|
||||
r = newtype(c.a, tykind.TY_TAGGED);
|
||||
r = newtype(tykind.TY_TAGGED);
|
||||
tinfocachebind(c.tc, n, r);
|
||||
// #61 A.3 nullable fold: `(*T | void)` collapses to a single
|
||||
// 8B pointer slot, null is the void variant. Mirrors
|
||||
@@ -1310,11 +1308,11 @@ fn exprtype(c: *checker, e: *node) *node = {
|
||||
if (e.list.list == nil) {
|
||||
if (e.list.next != nil) {
|
||||
if (e.list.next.next == nil) {
|
||||
let sl: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0);
|
||||
let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0);
|
||||
sl.lhs = mktname(c, "u8");
|
||||
let nome: *node = mktname(c, "nomem");
|
||||
sl.next = nome;
|
||||
let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0);
|
||||
let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0);
|
||||
tt.list = sl;
|
||||
return tt;
|
||||
};
|
||||
@@ -1324,11 +1322,11 @@ fn exprtype(c: *checker, e: *node) *node = {
|
||||
// Value form: `alloc(value)`.
|
||||
if (e.list.next == nil) {
|
||||
let argt: *node = exprtype(c, e.list);
|
||||
let ptr: *node = newnode(c.a, nkind.N_TPTR, "", 0, 0);
|
||||
let ptr: *node = newnode(nkind.N_TPTR, "", 0, 0);
|
||||
ptr.lhs = argt;
|
||||
let nome: *node = mktname(c, "nomem");
|
||||
ptr.next = nome;
|
||||
let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0);
|
||||
let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0);
|
||||
tt.list = ptr;
|
||||
return tt;
|
||||
};
|
||||
@@ -1845,14 +1843,14 @@ fn checkletassign(c: *checker, n: *node) void = {
|
||||
};
|
||||
};
|
||||
if (!shadowed) {
|
||||
let sl: *node = newnode(c.a, nkind.N_TSLICE, "", 0, 0);
|
||||
let sl: *node = newnode(nkind.N_TSLICE, "", 0, 0);
|
||||
sl.lhs = n.lhs.lhs;
|
||||
if (wrapped) {
|
||||
src = sl;
|
||||
} else {
|
||||
let nome: *node = mktname(c, "nomem");
|
||||
sl.next = nome;
|
||||
let tt: *node = newnode(c.a, nkind.N_TTAGGED, "", 0, 0);
|
||||
let tt: *node = newnode(nkind.N_TTAGGED, "", 0, 0);
|
||||
tt.list = sl;
|
||||
src = tt;
|
||||
};
|
||||
@@ -2043,7 +2041,7 @@ fn installparams(c: *checker, params: *node) void = {
|
||||
// per-statement scopes.
|
||||
fn resolvefnbody(c: *checker, fnnode: *node) void = {
|
||||
let outer: *scope = c.cur;
|
||||
c.cur = newscope(c.a, c.cur);
|
||||
c.cur = newscope(c.cur);
|
||||
installparams(c, fnnode.list);
|
||||
// #61 audit §1.8 — A.2: walk each param's declared type-expr so
|
||||
// tinfofornode stamps n.type_ on it. installparams binds the name
|
||||
@@ -2065,10 +2063,9 @@ fn resolvefnbody(c: *checker, fnnode: *node) void = {
|
||||
c.cur = outer;
|
||||
};
|
||||
|
||||
export fn checkinit(c: *checker, a: *arena, tc: *tctx) void = {
|
||||
c.a = a;
|
||||
export fn checkinit(c: *checker, tc: *tctx) void = {
|
||||
c.tc = tc;
|
||||
c.top = newscope(a, nil);
|
||||
c.top = newscope(nil);
|
||||
c.cur = c.top;
|
||||
c.nresolved = 0;
|
||||
c.nunresolved = 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,6 @@
|
||||
package main;
|
||||
|
||||
import os;
|
||||
import mem;
|
||||
import tok;
|
||||
import lex;
|
||||
import ast;
|
||||
@@ -99,7 +98,6 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
};
|
||||
};
|
||||
|
||||
let a: *arena = newarena();
|
||||
let buf: []u8 = alloc([], sz: u64)!;
|
||||
buf.len = sz: i32;
|
||||
let rr: (i64 | os.oserror) = os.readall(fd, buf.ptr, sz: u64);
|
||||
@@ -118,7 +116,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
};
|
||||
|
||||
let l: lex;
|
||||
lexinit(&l, a, argstr(path), buf.ptr, sz: u64);
|
||||
lexinit(&l, argstr(path), buf.ptr, sz: u64);
|
||||
|
||||
if (mode == 116) { // '-t'
|
||||
for (true) {
|
||||
@@ -130,17 +128,17 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
};
|
||||
} else { if (mode == 97) { // '-a'
|
||||
let ps: parser;
|
||||
parserinit(&ps, a, &l);
|
||||
parserinit(&ps, &l);
|
||||
let f: *node = parsefile(&ps);
|
||||
astprint(1i32, f);
|
||||
} else { if (mode == 114) { // '-r' — name resolve report
|
||||
let ps: parser;
|
||||
parserinit(&ps, a, &l);
|
||||
parserinit(&ps, &l);
|
||||
let f: *node = parsefile(&ps);
|
||||
let tc: tctx;
|
||||
typesinit(&tc, a);
|
||||
typesinit(&tc);
|
||||
let ck: checker;
|
||||
checkinit(&ck, a, &tc);
|
||||
checkinit(&ck, &tc);
|
||||
// Quiet by default; flip to 1 when debugging missing names.
|
||||
ck.verbose = 0;
|
||||
checkfile(&ck, f);
|
||||
@@ -158,7 +156,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
if (ck.nunresolved > 0) { return 1; };
|
||||
} else { if (mode == 99) { // '-c' — codegen / emit asm
|
||||
let ps: parser;
|
||||
parserinit(&ps, a, &l);
|
||||
parserinit(&ps, &l);
|
||||
let f: *node = parsefile(&ps);
|
||||
// #50: mirror w6c — run check before cgen so AST mutations
|
||||
// from #42 (size/align/offset fold) and audit §1.8 (node.type_
|
||||
@@ -166,13 +164,13 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
// (the byte-identity probe for 994) would diverge from w6c_ww
|
||||
// on any program that uses the size/align/offset typed builtins.
|
||||
let tc: tctx;
|
||||
typesinit(&tc, a);
|
||||
typesinit(&tc);
|
||||
let ck: checker;
|
||||
checkinit(&ck, a, &tc);
|
||||
checkinit(&ck, &tc);
|
||||
checkfile(&ck, f);
|
||||
if (ck.errs > 0) { return 1; };
|
||||
let cg: cgen;
|
||||
cgeninit(&cg, a);
|
||||
cgeninit(&cg);
|
||||
cgfile(&cg, f);
|
||||
};};};};
|
||||
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
// selfhost/test/sym_link.ww — link-and-run probe for the ww-cgen
|
||||
// against the sym/typ/ast/mem dep stack. Exercises arena (mem),
|
||||
// hashtable scope (sym), and pulls in typ/ast as type carriers.
|
||||
// against the sym/typ/ast dep stack. Exercises hashtable scope
|
||||
// (sym), and pulls in typ/ast as type carriers.
|
||||
// Returns 42 on success; smaller values name the probe that broke.
|
||||
|
||||
package test;
|
||||
|
||||
import mem;
|
||||
import typ;
|
||||
import ast;
|
||||
import sym;
|
||||
|
||||
export fn main() i32 = {
|
||||
let a: *arena = newarena();
|
||||
if (a == nil) { return 1; };
|
||||
|
||||
let s: *scope = newscope(a, nil);
|
||||
let s: *scope = newscope(nil);
|
||||
if (s == nil) { return 2; };
|
||||
|
||||
let n1: str = "foo";
|
||||
@@ -42,6 +38,5 @@ export fn main() i32 = {
|
||||
let l3: *sym = scopelookup(s, n3);
|
||||
if (l3 != nil) { return 10; };
|
||||
|
||||
freearena(a);
|
||||
return 42;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user