aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-18 09:47:54 +0200
committerlemon <lsof@mailbox.org>2022-08-18 09:47:54 +0200
commitf0214ff61b5a94b9629db6f43d7a5b010bd4ffbc (patch)
treec8517b4950bc3937e82ff49c757fb24a7364e3b0
parent8c81c70b904a41b8a0d44dc418b7c39bf325c2a2 (diff)
fix bodyarg
-rw-r--r--bootstrap/all.h4
-rw-r--r--bootstrap/parse.c8
-rw-r--r--src/cffc.hff18
-rw-r--r--src/common.hff4
-rw-r--r--src/env.cff12
-rw-r--r--src/fmt.cff12
-rw-r--r--src/libc.hff1
-rw-r--r--src/parse.cff179
-rw-r--r--src/set.hff4
-rw-r--r--src/targ.cff4
-rw-r--r--src/type.cff22
-rw-r--r--src/util.cff6
-rw-r--r--src/vec.hff2
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, &paramnames, &paramtys);
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 {