diff options
| author | 2022-08-18 09:47:54 +0200 | |
|---|---|---|
| committer | 2022-08-18 09:47:54 +0200 | |
| commit | f0214ff61b5a94b9629db6f43d7a5b010bd4ffbc (patch) | |
| tree | c8517b4950bc3937e82ff49c757fb24a7364e3b0 | |
| parent | 8c81c70b904a41b8a0d44dc418b7c39bf325c2a2 (diff) | |
fix bodyarg
| -rw-r--r-- | bootstrap/all.h | 4 | ||||
| -rw-r--r-- | bootstrap/parse.c | 8 | ||||
| -rw-r--r-- | src/cffc.hff | 18 | ||||
| -rw-r--r-- | src/common.hff | 4 | ||||
| -rw-r--r-- | src/env.cff | 12 | ||||
| -rw-r--r-- | src/fmt.cff | 12 | ||||
| -rw-r--r-- | src/libc.hff | 1 | ||||
| -rw-r--r-- | src/parse.cff | 179 | ||||
| -rw-r--r-- | src/set.hff | 4 | ||||
| -rw-r--r-- | src/targ.cff | 4 | ||||
| -rw-r--r-- | src/type.cff | 22 | ||||
| -rw-r--r-- | src/util.cff | 6 | ||||
| -rw-r--r-- | src/vec.hff | 2 |
13 files changed, 210 insertions, 66 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h index 720c7ea..bebdaf5 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -130,6 +130,8 @@ struct parser { struct toktree toks; const char *name; struct span span; + struct tok peektok; + bool have_peektok; int idx; bool tepl; } *curexpan; // macro expansions @@ -226,7 +228,7 @@ struct fn { }; struct macrocase { - bool variadic; + bool variadic, bodyarg; slice_t(const char *) params; struct toktree body; }; diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 078e3dd..c018262 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -308,6 +308,8 @@ lex(struct parser *P) { --P->expanno; free(ep->args.d); P->curexpan = ep->prev; + P->have_peektok = ep->have_peektok; + P->peektok = ep->peektok; free(ep); return lex(P); } @@ -2319,8 +2321,7 @@ parseexpandmacro(struct parser *P, const struct macro *macro) { break; } } - eatspaces(P); - if (chrpeek(P) == '{') { + if (lexpeek(P).t == '{') { for (int i = 0; i < macro->cs.n; ++i) { c = macro->cs.d[i]; if (args.length == c.params.n - 1 && c.bodyarg) { @@ -2375,6 +2376,9 @@ ok: expan.name = macro->name; expan.args.d = expanargs; expan.args.n = c.params.n; + expan.peektok = P->peektok; + expan.have_peektok = P->have_peektok; + P->have_peektok = 0; expan.toks = c.body; ++P->expanno; P->curexpan = memcpy(xmalloc(sizeof expan), &expan, sizeof expan); diff --git a/src/cffc.hff b/src/cffc.hff index aad2ee4..ad6a8aa 100644 --- a/src/cffc.hff +++ b/src/cffc.hff @@ -119,11 +119,13 @@ struct Parser { curenv *Env, curloop int, loopid int, + targty *const Type, tokloc Loc, curloc Loc, eof bool, is_header bool, peekchr Option<int>, + peektok Option<Tok>, } @@ -152,6 +154,8 @@ struct Expr { BinOp struct { op TokT, lhs *Expr, rhs *Expr }, UnOp struct { op UnOp, ex *Expr }, Cond struct { test *Expr, t *Expr, f *Expr }, + Cast *Expr, + Dot struct { lhs *Expr, fld *const AggField }, Index struct { lhs *Expr, rhs *Expr }, Slice struct { lhs *Expr, begin *Expr, end *Expr }, Call struct { lhs *Expr, args [#]Expr }, @@ -200,6 +204,7 @@ struct Var { struct MacroCase { variadic bool, + bodyarg bool, params [#]*const u8, body [#]Tok, } @@ -220,6 +225,7 @@ struct Decl { Macro Macro, Ty *const Type, }, + myenv *Env, } struct DeclList { @@ -311,12 +317,8 @@ fn mkptrtype(child *const Type) *const Type { .u: :Ptr(child) }); } -fn mkslicetype(child *const Type) *const Type { - return interntype({ - g_targ.ptrsize, - .u: :Ptr(child) - }); -} +extern fn mkslicetype(child *const Type) *const Type; + fn childtype(ty *const Type) *const Type { switch ty.u { case Ptr t; return t; @@ -326,7 +328,9 @@ fn childtype(ty *const Type) *const Type { return #null; } extern fn completetype(ty *const Type) bool; -extern fn isnumtype(ty *const Type) bool; +fn isnumtype(ty *const Type) bool { + return ty->is(:Int) or ty->is(:Flo); +} extern fn typeof2(a *const Type, b *const Type) *const Type; // env.cff diff --git a/src/common.hff b/src/common.hff index 3d90c55..4da1398 100644 --- a/src/common.hff +++ b/src/common.hff @@ -15,7 +15,7 @@ defmacro assert { ] } -defmacro foreach(x, i, a, ...body) [ +defmacro foreach(x, i, a, &body) [ { let $a = a; for let i = 0; i < $a.#len; ++i { @@ -33,7 +33,7 @@ defmacro coalesce(a,b) [ $x ? $x : b; ) ] -defmacro with_tmpchange(var,x,...body) [ +defmacro with_tmpchange(var,x,&body) [ { let $tmp = (var); (var) = x; { body } diff --git a/src/env.cff b/src/env.cff index f18fe49..aa5c6d4 100644 --- a/src/env.cff +++ b/src/env.cff @@ -28,11 +28,19 @@ extern fn envput(env *Env, decl Decl, old **const Decl) *Decl { let l **DeclList = env.decls->get_slot(decl.name); let n *DeclList = anew(env.alloc, DeclList); if *l { // decl with this name exists - *old = &(*l).decl; - return #null; + let old = (*old = &(*l).decl); + switch { + case old.u.#tag == :Fn and decl.u.#tag == :Fn and decl.u.Fn.ty == old.u.Fn.ty and old.u.Fn.body->empty(); + case decl.u.#tag == :Let; + case env != old.myenv; + + case else; + return #null; + } } n.link = *l; n.decl = decl; + n.decl.myenv = env; *l = n; return &n.decl; } diff --git a/src/fmt.cff b/src/fmt.cff index 755bbda..0dce9d3 100644 --- a/src/fmt.cff +++ b/src/fmt.cff @@ -155,12 +155,12 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) pfmt(proc, parg, "[#]%t", child); case Fn f; ps("fn ("); - foreach(ty, i, f.params, + foreach(ty, i, f.params) { pfmt(proc, parg, "%t", ty); if f.variadic or i < f.params.#len - 1 { ps(", "); } - ) + } if f.variadic { ps("..."); } @@ -220,7 +220,9 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) } case 's'; let s = ap->arg(*const u8); - if quote { + if s == #null { + ps("(null)"); + } else if quote { extern fn isprint(int) int; p('\"'); for let c u8 #?; (c = *s++) != 0; { @@ -233,9 +235,9 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) case 'S'; let str = ap->arg([#]const u8); p('"'); - foreach(c, i, str, + foreach(c, i, str) { pch(c); - ) + } p('"'); case 'T'; let tok = ap->arg(Tok); diff --git a/src/libc.hff b/src/libc.hff index 6fb32f7..2778a79 100644 --- a/src/libc.hff +++ b/src/libc.hff @@ -39,3 +39,4 @@ extern fn tolower(int) int; // errno.h extern fn c_errno() int; +def errno = c_errno(); diff --git a/src/parse.cff b/src/parse.cff index f19b586..7d083fb 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -407,9 +407,9 @@ fn lex(P *Parser) Tok { fatal(P, P.tokloc, "too long multichar literal %qs", str.dat); } tok.u.uint = 0; - vec_each(c0, i, str, + vec_each(c0, i, str) { tok.u.uint = (tok.u.uint << 8) | c0; - ) + } } return tok; } @@ -540,6 +540,16 @@ defmacro lexexpect(P, t) [lexexpects(P, t, #null)] static primenv *Env = {}; +fn pushenv(P *Parser, env *Env) void { + assert(P.curenv == envparent(env), "pushenv"); + P.curenv = env; +} + +fn popenv(P *Parser) void { + P.curenv = envparent(P.curenv); + assert(P.curenv != #null, "popenv"); +} + fn finddecl(P *Parser, name *const u8) *Decl { let p = envfind(primenv, name); return p ?? envfind(P.curenv, name); @@ -568,6 +578,8 @@ fn putdecl(P *Parser, eloc Loc, decl Decl) *Decl { fn parseexpr(P *Parser) Expr; fn parsetype(P *Parser) *const Type; +typedef DeclYielder *fn(*Decl, *void) void; +fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void; fn parseenum(P *Parser, name *const u8, lax bool) *const Type { lexexpect(P, '{'); @@ -597,6 +609,15 @@ fn parseenum(P *Parser, name *const u8, lax bool) *const Type { return interntype({ .u: :Enum { intty, name, lax, id++, vals->move(P.alloc) }}); } +fn isdecltokt(t TokT) bool { + switch t { + case :kw_fn, :kw_static, :kw_def, :kw_defmacro, :kw_struct, :kw_union, :kw_enum, + :kw_extern; + return #t; + } + return #f; +} + fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type { let loc = P.tokloc; let tok Tok #?; @@ -625,7 +646,12 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type lexexpect(P, '{'); let size = 0, align = 1; let flds Vec<AggField> = {}; + let havedecls = #f; while !lexmatch(P, #null, '}') { + if isdecltokt(lexpeek(P).t) { + havedecls = #t; + break; + } let off = size; let name = lexexpects(P, :ident, "field name").u.ident; let type = parsetype(P); @@ -645,6 +671,14 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type ty.size = size; ty.align = align; agg.flds = flds.dat[0::flds.len]; + if havedecls { + agg.decls = mkenv(P.curenv, P.alloc); + pushenv(P, agg.decls); + while !lexmatch(P, #null, '}') { + parsedecls(P, #null, #null, #{toplevel} #f); + } + popenv(P); + } } return ty; } @@ -716,6 +750,22 @@ fn parsetype(P *Parser) *const Type { case lexmatch(P, &tok, '*'); return mkptrtype(parsetype(P)); + case lexmatch(P, &tok, '['); + let len = -1i64; + if lexmatch(P, &tok, '#') { + lexexpect(P, ']'); + return mkslicetype(parsetype(P)); + } else if !lexmatch(P, &tok, ']') { + let ex = parseexpr(P); + lexexpect(P, ']'); + if !fold(&ex) or ex.u.#tag != :IntLit or ex.u.IntLit.i < 0 { + fatal(P, ex.loc, "expected constant non-negative integer expression for array length"); + } + len = ex.u.IntLit.i; + } + let child = parsetype(P); + return mkarrtype(len, #f, child); + case lexmatch(P, &tok, :ident); return xident2type(P, tok.loc, tok.u.ident); @@ -755,28 +805,31 @@ fn islvalue(ex Expr) bool { return u.op == :deref; case Index; return #t; + case Dot; + return #t; } return #f; } fn pexprimary(P *Parser) Expr { let tok Tok = lex(P); + let ex Expr #?; switch tok.t { case :int, :chr; - return { tok.loc, tok.ty, .u: :IntLit { tok.u.int }}; + ex = { tok.loc, tok.ty, .u: :IntLit { tok.u.int }}; case :flo; - return { tok.loc, tok.ty, .u: :FloLit(tok.u.flo) }; + ex = { tok.loc, tok.ty, .u: :FloLit(tok.u.flo) }; case :bool; - return { tok.loc, ty_bool, .u: :BoolLit(tok.u.bool) }; + ex = { tok.loc, ty_bool, .u: :BoolLit(tok.u.bool) }; case :null; - return { tok.loc, ty_voidptr, .u: :NullLit }; + ex = { tok.loc, ty_voidptr, .u: :NullLit }; case :str; let ty = mkarrtype(tok.u.str.#len + 1, #t, ty_u8); - return { tok.loc, ty, .u: :StrLit(tok.u.str) }; + ex = { tok.loc, ty, .u: :StrLit(tok.u.str) }; case :ident; let ident = tok.u.ident; @@ -786,14 +839,14 @@ fn pexprimary(P *Parser) Expr { } switch decl.u { case Fn f; - return { tok.loc, f.ty, .u: :Symbol(decl) }; + ex = { tok.loc, f.ty, .u: :Symbol(decl) }; case Let var; - return { tok.loc, var.ty, .u: :Symbol(decl) }; + ex = { tok.loc, var.ty, .u: :Symbol(decl) }; case Static var; - return { tok.loc, var.ty, .u: :Symbol(decl) }; - case Def ex; - ex.loc = tok.loc; - return ex; + ex = { tok.loc, var.ty, .u: :Symbol(decl) }; + case Def dex; + dex.loc = tok.loc; + ex = dex; } case :kw_sizeof; let ty *const Type #?; @@ -807,16 +860,27 @@ fn pexprimary(P *Parser) Expr { if !completetype(ty) { err(P, tok.loc, "sizeof incomplete type (%t)", ty); } - return { tok.loc, ty_usize, :IntLit { ty.size }}; + ex = { tok.loc, ty_usize, :IntLit { ty.size }}; case '('; - let ex = parseexpr(P); + ex = parseexpr(P); lexexpect(P, ')'); - return ex; + case '{'; + if P.targty == #null { + fatal(P, tok.loc, "cannot infer type for initializer"); + } + let ty = P.targty; + if lexmatch(P, #null, '}') { + ex = { tok.loc, ty, .u: :ZeroIni }; + } else { + assert(#f, "NYI"); + } case else; fatal(P, tok.loc, "expected expression (near %qT)", tok); } + P.targty = #null; + return ex; } fn pexpostfix(P *Parser) Expr { @@ -890,8 +954,33 @@ fn pexpostfix(P *Parser) Expr { tok.t == '++' ? :postinc : :postdec, exprdup(P.alloc, ex) } }; + case lexmatch(P, &tok, '.'); + let name = (tok = lexexpects(P, :ident, "field name")).u.ident; + let ty = ex.ty; + if ty->is(:Ptr) { + ty = ty.u.Ptr; + } + if !ty->is(:Agg) { + fatal(P, tok.loc, "left-hand-side is not an aggregate (%t)", ty); + } + let agg = &ty.u.Agg; + let fld *AggField = #null; + foreach(f, i, agg.flds) { + if streq(name, f.name) { + fld = &agg.flds[i]; + break; + } + } + if fld == #null { + fatal(P, tok.loc, "%t has no such field %qT", ty, tok); + } + if fld.ty == #null { + fatal(P, tok.loc, "field %qT has no type", tok); + } + ex = { tok.loc, fld.ty, :Dot { exprdup(P.alloc, ex), fld }}; + case else; - break; + break; } } return ex; @@ -956,6 +1045,15 @@ fn pexprefix(P *Parser) Expr { err(P, ex.loc, "invalid operand to `&': not an lvalue"); } return { tok.loc, ty2, .u: :UnOp { :addrof, exprdup(P.alloc, ex) }}; + + case lexmatch(P, &tok, :kw_as); + let loc = tok.loc; + lexexpect(P, '('); + let ty = parsetype(P); + lexexpect(P, ')'); + let ex = pexprefix(P); + // TODO check valid cast + return { loc, ty, :Cast(exprdup(P.alloc, ex)) }; } return pexpostfix(P); } @@ -1161,7 +1259,6 @@ fn stmtdup(alloc *Allocator, st Stmt) *Stmt { return memcpy(alloc->alloc(sizeof(st)), &st, sizeof(st)); } -typedef DeclYielder *fn(*Decl, *void) void; typedef StmtYielder *fn(Stmt, *void) void; fn parseblock(P *Parser) [#]Stmt; fn parsevardecl(P *Parser, toplevel bool, externp bool, letp bool, DeclYielder, *void) void; @@ -1314,6 +1411,18 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void { lexexpect(P, ';'); return yield({ tok.loc, :Continue(P.curloop) }, yarg); + case isdecltokt(tok.t); + struct Arg { + P *Parser, + yield StmtYielder, + yarg *void, + } + fn declyield(decl *Decl, arg *void) void { + let a *Arg = arg; + a.yield({ decl.loc, :Decl(decl) }, a.yarg); + } + parsedecls(P, &declyield, &Arg { P, yield, yarg }, #{toplevel?} #f); + case else; let ex = parseexpr(P); lexexpect(P, ';'); @@ -1324,6 +1433,8 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void { fn parseblock0(P *Parser) [#]Stmt { let sts Vec<Stmt> = {}; let tok Tok = {}; + let env = mkenv(P.curenv, P.alloc); + pushenv(P, env); while (tok = lexpeek(P)).t != '}' and tok.t != :kw_case and tok.t != '}' { if lexmatch(P, #null, ';') { continue; } fn pushstmt(st Stmt, arg *void) void { @@ -1332,6 +1443,7 @@ fn parseblock0(P *Parser) [#]Stmt { } parsestmts(P, &pushstmt, &sts); } + popenv(P); return sts->move(P.alloc); } @@ -1362,6 +1474,7 @@ fn parsevardecl(P *Parser, toplevel bool, externp bool, letp bool, yield DeclYie ty = parsetype(P); if lexmatch(P, #null, '=') { + P.targty = ty; ini = :Some(parseexpr(P)); } else if lexmatch(P, #null, '#?') { ini = :None; @@ -1400,10 +1513,10 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl { }; let Fn = &decl.u.Fn, - tok Tok = {}, paramnames Vec<*const u8> = {}, paramtys Vec<*const Type> = {}; + let loc = P.tokloc; parsefnparams(P, &Fn.variadic, ¶mnames, ¶mtys); Fn.paramnames = paramnames->move(P.alloc); let retty = parsetype(P); @@ -1412,7 +1525,7 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl { }}); static id int = 0; Fn.id = ++id; - let decl = putdecl(P, tok.loc, decl); + let decl = putdecl(P, loc, decl); if !lexmatch(P, #null, '{') { lexexpects(P, ';', "';' or '{'"); @@ -1422,16 +1535,16 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl { with_tmpchange(P.alloc, &Allocator { &Arena {}, &Arena:allocf }, with_tmpchange(P.curfn, Fn, let env = mkenv(P.curenv, P.alloc); - P.curenv = env; - foreach(name, i, Fn.paramnames, + pushenv(P, env); + foreach(name, i, Fn.paramnames) { if name { - putdecl(P, tok.loc, { name, tok.loc, .u: :Let { + putdecl(P, loc, { name, loc, .u: :Let { Fn.ty.u.Fn.params[i], :None, #f, Fn.id, }}); } - ) + } Fn.body = :Some(parseblock(P)); - P.curenv = envparent(env); + popenv(P); envfree(env); (as(*Arena)P.alloc.a)->destroy(); ); @@ -1467,7 +1580,7 @@ fn doimport(P *Parser, path *const u8) [#]Decl { snprintf(path2, sizeof(path2) - 1, "%s/%s", basedir, path); let rpath *const u8 = realpath(path2, _rpath); if rpath == #null { - fatal(P, P.tokloc, "import %qs: %s", path, strerror(c_errno())); + fatal(P, P.tokloc, "import %qs: %s", path, strerror(errno)); } let d0 = seen->get(rpath); if d0 != #null { @@ -1505,6 +1618,12 @@ fn parsemacro(P *Parser, name *const u8) *Decl { lexmatch(P, &tok, ','); lexexpect(P, ')'); break; + } else if lexmatch(P, &tok, '&') { + params->push(lexexpects(P, :ident, "parameter name").u.ident); + c.bodyarg = #t; + lexmatch(P, &tok, ','); + lexexpect(P, ')'); + break; } else { params->push(lexexpects(P, :ident, "parameter name").u.ident); if !lexmatch(P, &tok, ',') { @@ -1526,11 +1645,11 @@ fn parsemacro(P *Parser, name *const u8) *Decl { fatal(P, eloc, "unterminated macro definition"); } if tok.t == :ident { - vec_each(par, _, params, + vec_each(par, _, params) { if streq(par, tok.u.ident) { tok.t = :macident; } - ) + } } else if tok.t == :gensym { let gs *Gensyms #?; let found = #f; @@ -1605,12 +1724,12 @@ fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void { case lexmatch(P, &tok, :kw_import); let path = (tok = lexexpects(P, :str, "import path")).u.str.#ptr; let decls = doimport(P, path); - foreach(decl, _, decls, + foreach(decl, _, decls) { let decl = putdecl(P, tok.loc, decl); if yield { yield(decl, yarg); } - ) + } lexexpect(P, ';'); return; diff --git a/src/set.hff b/src/set.hff index 82c213f..6f472b3 100644 --- a/src/set.hff +++ b/src/set.hff @@ -25,7 +25,7 @@ struct Set<T, Traits> { if self.count == self.N / 2 { free(self.set); self.set = xcalloc(self.N *= 2, sizeof int); - vec_each(p, i, self.buf, + vec_each(p, i, self.buf) { let h = Traits:hash(p); let j = h & (self.N - 1); for ;; { @@ -35,7 +35,7 @@ struct Set<T, Traits> { } j = _nexthash(&h) & (self.N - 1); } - ) + } } let h u32 = Traits:hash(x); diff --git a/src/targ.cff b/src/targ.cff index c74e1d3..895a20a 100644 --- a/src/targ.cff +++ b/src/targ.cff @@ -20,11 +20,11 @@ static const targs []const Targ = { extern static g_targ *const Targ = {}; extern fn targ_ini(name *const u8) bool { - foreach(targ, i, targs[0::], + foreach(targ, i, targs[0::]) { if streq(name, targ.name) { g_targ = &targs[i]; return #t; } - ) + } return #f; } diff --git a/src/type.cff b/src/type.cff index 980a83a..593ec3c 100644 --- a/src/type.cff +++ b/src/type.cff @@ -34,9 +34,9 @@ struct TypeTraits { case Fn f; h = fnv1a_i(h, f.ret.id); - foreach(p, _, f.params, + foreach(p, _, f.params) { h = fnv1a_i(h, p.id); - ) + } case Agg agg; h = fnv1a_i(h, agg.id); @@ -77,11 +77,11 @@ struct TypeTraits { if f0.params.#len != f1.params.#len { return #f; } - foreach(p, i, f0.params, + foreach(p, i, f0.params) { if p != f1.params[i] { return #f; } - ) + } return #t; case Agg agg; @@ -123,7 +123,7 @@ extern fn completetype(ty *const Type) bool { switch ty.u { case Void; return #f; case Fn; return #f; - case Arr a; return a.length >= 0; + case Arr a; return a.length >= 0 and completetype(a.child); case Agg agg; return !agg.fwd; } return #t; @@ -173,14 +173,18 @@ extern fn putprimtypes(env *Env) void { { "uptrint",&ty_uptrint, { g_targ.ptrsize, .u: :Int { .sgn: #f }}}, }; - foreach(type, _, types[0::], + foreach(type, _, types[0::]) { envput(env, { type.name, .u: :Ty(*type.gty = interntype(type.ty)) }, #null); - ) + } ty_voidptr = interntype({ .size: g_targ.ptrsize, .u: :Ptr(ty_void) }); } -extern fn isnumtype(ty *const Type) bool { - return ty->is(:Int) or ty->is(:Flo); +extern fn mkslicetype(child *const Type) *const Type { + let align = MAX(g_targ.ptrsize, g_targ.sizesize); + return interntype({ + ALIGNUP(g_targ.ptrsize + g_targ.sizesize, align), align, + .u: :Slice(child) + }); } fn numtype2rank(ty *const Type) int { diff --git a/src/util.cff b/src/util.cff index d3e40bb..30175a3 100644 --- a/src/util.cff +++ b/src/util.cff @@ -29,10 +29,10 @@ extern fn xstrdup(str *const u8) *u8 { } extern fn fnv1a(h u32, d [#]const u8) u32 { - foreach(i, x, d, + foreach(i, x, d) { h ^= x; h *= 0x01000193; - ) + } return h; } @@ -70,7 +70,7 @@ extern fn addfilepath(s *const u8) int { extern fn fileid2path(id int) *const u8 { assert(id >= 0 and id < filepaths.#len, "fileid"); let s = filepaths[id]; - assert(s != #null, "fileid"); + // assert(s != #null, "fileid %d", id); return s; } diff --git a/src/vec.hff b/src/vec.hff index 003b13a..2966579 100644 --- a/src/vec.hff +++ b/src/vec.hff @@ -49,7 +49,7 @@ struct Vec<T> { fn lastp(vec *Vec) *T { return &vec.dat[vec.len - 1]; } } -defmacro vec_each(x, i, v, ...body) [ +defmacro vec_each(x, i, v, &body) [ { let $v = v; for let i = 0; i < $v.len; ++i { |