diff options
| author | 2022-08-19 16:31:16 +0200 | |
|---|---|---|
| committer | 2022-08-19 16:31:16 +0200 | |
| commit | 57af02b91cb3a9eef66137c85aab7e47bdd7d0a5 (patch) | |
| tree | c0597811c61d473263559ab7ffefe68ab8785c47 /src | |
| parent | 9e408967cbdfa1d04e4bd4bc963399e7be78c0a7 (diff) | |
labels, #FILE #LINE, some bugfixes, c types
Diffstat (limited to 'src')
| -rw-r--r-- | src/cffc.hff | 48 | ||||
| -rw-r--r-- | src/env.cff | 8 | ||||
| -rw-r--r-- | src/mem.hff | 2 | ||||
| -rw-r--r-- | src/parse.cff | 92 | ||||
| -rw-r--r-- | src/type.cff | 52 |
5 files changed, 136 insertions, 66 deletions
diff --git a/src/cffc.hff b/src/cffc.hff index 131b3d9..920f74a 100644 --- a/src/cffc.hff +++ b/src/cffc.hff @@ -108,6 +108,7 @@ struct Type { flds [#]AggField, decls *Env, }, + VaList, }, fn is(ty *const Type, tag typeof((Type{}).u.#tag)) bool { @@ -282,6 +283,7 @@ struct Decl { Fn Fn, Macro Macro, Tepl Tepl, + Label #{loopid} int, }, myenv *Env, } @@ -297,8 +299,8 @@ struct Expan { name *const u8, loc Loc, tepl bool, + peektok Option<Tok>, idx int, - peektok Option<Tok> } struct DeclList { @@ -340,25 +342,31 @@ extern static g_targ *const Targ; extern fn targ_ini(name *const u8) bool; // type.cff -extern static ty_void *const Type, - ty_bool *const Type, - ty_i8 *const Type, - ty_u8 *const Type, - ty_i16 *const Type, - ty_u16 *const Type, - ty_i32 *const Type, - ty_u32 *const Type, - ty_int *const Type, - ty_uint *const Type, - ty_i64 *const Type, - ty_u64 *const Type, - ty_isize *const Type, - ty_usize *const Type, - ty_iptrint *const Type, - ty_uptrint *const Type, - ty_f32 *const Type, - ty_f64 *const Type, - ty_voidptr *const Type; +extern static ty_void *const Type, + ty_bool *const Type, + ty_i8 *const Type, + ty_u8 *const Type, + ty_i16 *const Type, + ty_u16 *const Type, + ty_i32 *const Type, + ty_u32 *const Type, + ty_int *const Type, + ty_uint *const Type, + ty_i64 *const Type, + ty_u64 *const Type, + ty_isize *const Type, + ty_usize *const Type, + ty_iptrint *const Type, + ty_uptrint *const Type, + ty_f32 *const Type, + ty_f64 *const Type, + ty_voidptr *const Type, + ty_c_char *const Type, + ty_c_long *const Type, + ty_c_ulong *const Type, + ty_c_llong *const Type, + ty_c_ullong *const Type, + ty_c_valist *const Type; extern fn interntype(Type) *const Type; extern fn putprimtypes(env *Env) void; fn constify(ty *const Type) *const Type { diff --git a/src/env.cff b/src/env.cff index aa5c6d4..816053e 100644 --- a/src/env.cff +++ b/src/env.cff @@ -30,7 +30,13 @@ extern fn envput(env *Env, decl Decl, old **const Decl) *Decl { if *l { // decl with this name exists 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 old.u.#tag == :Fn and decl.u.#tag == :Fn + and decl.u.Fn.ty == old.u.Fn.ty and (old.u.Fn.body->empty() or decl.u.Fn.body->empty()); + case old.u.#tag == :Ty and decl.u.#tag == :Ty and old.u.Ty == decl.u.Ty; + case old.u.#tag == :Def and decl.u.#tag == :Def + and memcmp(&old.u.Def, &decl.u.Def, sizeof(old.u.Def)) == 0; + case old.u.#tag == :Macro and decl.u.#tag == :Macro + and memcmp(&old.u.Macro, &decl.u.Macro, sizeof(old.u.Macro)) == 0; case decl.u.#tag == :Let; case env != old.myenv; diff --git a/src/mem.hff b/src/mem.hff index 3f3b8c9..f3689ac 100644 --- a/src/mem.hff +++ b/src/mem.hff @@ -1,7 +1,7 @@ import "libc.hff"; defmacro ALIGNUP(x,a) [ (((x) + ((a) - 1)) & -(a)) ] -def ARENA_SIZE = 4 * 1024; +def ARENA_SIZE = 4z * 1024; extern fn xmalloc(n usize) *void; extern fn xcalloc(n usize, m usize) *void; extern fn xrealloc(p *void, n usize) *void; diff --git a/src/parse.cff b/src/parse.cff index cbeccb1..2f5fbe2 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -299,7 +299,9 @@ fn lex(P *Parser) Tok { --P.expanno; free(ep.args.#ptr); P.curexpan = ep.prev; - P.peektok = ep.peektok; + if !ep.tepl { + P.peektok = ep.peektok; + } free(ep); return lex(P); } @@ -395,11 +397,15 @@ fn lex(P *Parser) Tok { tok.t = '#len'; case streq(s, "#tag"); tok.t = '#tag'; + case streq(s, "#FILE"); + tok.t = '#FIL'; + case streq(s, "#LINE"); + tok.t = '#LIN'; case streq(s, "#?"); tok.t = '#?'; case s[0] == '#' and s[1] == '\''; tok.t = :label; - tok.u.str = spanz(internstr(s)); + tok.u.ident = internstr(s); case else fatal(P, P.tokloc, "invalid #keyword `%s'", s); } @@ -677,6 +683,8 @@ fn parseagg(P *Parser, loc Loc, kind AggKind, name *const u8, retdecl **Decl) *c if !ty->is(:Agg) or !ty.u.Agg.fwd or ty.u.Agg.kind != kind { decl = #null; } + case else + decl = #null; } } let ty = decl ? decl.u.Ty : interntype({ .u: :Agg { kind, name, id++ }}); @@ -904,12 +912,14 @@ fn parseexpandtepl(P *Parser, tepl *Tepl) *const Type { let env = mkenv(tepl.env, P.alloc); with_tmpchange(P.curenv, env) { let decl *Decl #?; - let expan Expan = { P.curexpan, args[0::nparam], tepl.toks, tname, tok.loc, #{tepl?} #t }; + let expan Expan = { + P.curexpan, args[0::nparam], tepl.toks, tname, tok.loc, #{tepl?} #t, + }; ++P.expanno; P.curexpan = memcpy(xmalloc(sizeof Expan), &expan, sizeof Expan); ty = parseagg(P, loc, tepl.kind, tname, &decl); - } + P.peektok = :None; envfree(env); (as(*Type)ty).u.Agg.tpargs = tpargs; cache = P.alloc->alloc(sizeof(*cache), alignof(*cache)); @@ -1275,6 +1285,7 @@ fn pexprimary(P *Parser) Expr { case :ident; let ident = tok.u.ident; let decl = finddecl(P, ident); + let fakedecl Decl = {}; if decl == #null { fatal(P, tok.loc, "%qT is not defined", tok); } @@ -1294,7 +1305,7 @@ fn pexprimary(P *Parser) Expr { ex = parseexpr(P); case Ty ty; if (tok = lexpeek(P)).t != ':' and tok.t != '{' { - fatal(P, tok.loc, "expected `:' or `{' after type name"); + lexexpects(P, ':', "`:' or `{' after type name"); } if tok.t == ':' and ty->is(:Agg) and ty.u.Agg.kind != :EUnion { lex(P); @@ -1310,6 +1321,10 @@ fn pexprimary(P *Parser) Expr { P.targty = ty; return parseexpr(P); } + case Tepl *tepl; + fakedecl = { .u: :Ty(parseexpandtepl(P, tepl)) }; + decl = &fakedecl; + continue; } break; } @@ -1949,20 +1964,27 @@ fn pstreturn(P *Parser, loc Loc) Stmt { } } -fn pstwhile(P *Parser, loc Loc) Stmt { +fn pstwhile(P *Parser, loc Loc, label *const u8) Stmt { let test = parseexpr(P); if !test.ty->is(:Bool) and !test.ty->is(:Ptr) { err(P, test.loc, "while condition must be bool or pointer (%t)", test.ty); } lexexpect(P, '{'); - let t [#]Stmt #?; + let body [#]Stmt #?; with_tmpchange(P.curloop, ++P.loopid) { - t = parseblock(P); + let env = mkenv(P.curenv, P.alloc); + pushenv(P, env); + if label { + putdecl(P, loc, { label, loc, .u: :Label(P.loopid) }); + } + body = parseblock(P); + popenv(P); + envfree(env); } - return { loc, :While { test, t, P.loopid }}; + return { loc, :While { test, body, P.loopid }}; } -fn pstfor(P *Parser, loc Loc) Stmt { +fn pstfor(P *Parser, loc Loc, label *const u8) Stmt { let ini [#]Stmt = {}; let test Expr #?; let next = Option<Expr>:None; @@ -1998,7 +2020,14 @@ fn pstfor(P *Parser, loc Loc) Stmt { } let body [#]Stmt #?; with_tmpchange(P.curloop, ++P.loopid) { + let env = mkenv(P.curenv, P.alloc); + pushenv(P, env); + if label { + putdecl(P, loc, { label, loc, .u: :Label(P.loopid) }); + } body = parseblock(P); + popenv(P); + envfree(env); } return { loc, :For { ini, test, next, body, P.loopid }}; } @@ -2129,25 +2158,39 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void { case lexmatch(P, &tok, :kw_return); return yield(pstreturn(P, tok.loc), yarg); + case lexmatch(P, &tok, :label); + let label = tok.u.ident; + switch { + case lexmatch(P, &tok, :kw_while); + return yield(pstwhile(P, tok.loc, label), yarg); + case lexmatch(P, &tok, :kw_for); + return yield(pstfor(P, tok.loc, label), yarg); + case else + fatal(P, tok.loc, "label can only precede looping statement"); + } + case lexmatch(P, &tok, :kw_while); - return yield(pstwhile(P, tok.loc), yarg); + return yield(pstwhile(P, tok.loc, #null), yarg); case lexmatch(P, &tok, :kw_for); - return yield(pstfor(P, tok.loc), yarg); + return yield(pstfor(P, tok.loc, #null), yarg); - case lexmatch(P, &tok, :kw_break); + case lexmatch(P, &tok, :kw_break) or lexmatch(P, &tok, :kw_continue); if P.curloop == 0 { - err(P, tok.loc, "break outside loop"); + err(P, tok.loc, "%s outside loop", tok.t == :kw_break ? "break" : "continue"); } - lexexpect(P, ';'); - return yield({ tok.loc, :Break(P.curloop) }, yarg); - - case lexmatch(P, &tok, :kw_continue); - if P.curloop == 0 { - err(P, tok.loc, "continue outside loop"); + let tok2 Tok #?; + let loop = P.curloop; + if lexmatch(P, &tok2, :label) { + let decl = finddecl(P, tok2.u.ident); + if decl == #null { + fatal(P, tok2.loc, "no such label %qT", tok2); + } + assert(decl.u.#tag == :Label, "label?"); + loop = decl.u.Label; } lexexpect(P, ';'); - return yield({ tok.loc, :Continue(P.curloop) }, yarg); + return yield({ tok.loc, tok.t == :kw_break ? :Break(loop) : :Continue(loop) }, yarg); case lexmatch(P, &tok, :kw_switch); return yield(pstswitch(P, tok.loc), yarg); @@ -2622,9 +2665,10 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) err(P, ini.loc, "incompatible initializer (%t, expected %t)", ini.ty, ty); } fold(&ini); - yield(putdecl(P, tok.loc, { - name, tok.loc, .u: :Def(ini) - }), yarg); + decl = putdecl(P, tok.loc, { name, tok.loc, .u: :Def(ini) }); + if yield { + yield(decl, yarg); + } if !lexmatch(P, &tok, ',') { lexexpects(P, ';', "`,' or `;'"); break; diff --git a/src/type.cff b/src/type.cff index 713716b..b0cb259 100644 --- a/src/type.cff +++ b/src/type.cff @@ -135,26 +135,32 @@ extern fn completetype(ty *const Type) bool { return #t; } -extern static ty_void *const Type = {}, - ty_bool *const Type = {}, - ty_intbool *const Type = {}, - ty_i8 *const Type = {}, - ty_u8 *const Type = {}, - ty_i16 *const Type = {}, - ty_u16 *const Type = {}, - ty_i32 *const Type = {}, - ty_u32 *const Type = {}, - ty_int *const Type = {}, - ty_uint *const Type = {}, - ty_i64 *const Type = {}, - ty_u64 *const Type = {}, - ty_isize *const Type = {}, - ty_usize *const Type = {}, - ty_iptrint *const Type = {}, - ty_uptrint *const Type = {}, - ty_f32 *const Type = {}, - ty_f64 *const Type = {}, - ty_voidptr *const Type = {}; +extern static ty_void *const Type = {}, + ty_bool *const Type = {}, + ty_intbool *const Type = {}, + ty_i8 *const Type = {}, + ty_u8 *const Type = {}, + ty_i16 *const Type = {}, + ty_u16 *const Type = {}, + ty_i32 *const Type = {}, + ty_u32 *const Type = {}, + ty_int *const Type = {}, + ty_uint *const Type = {}, + ty_i64 *const Type = {}, + ty_u64 *const Type = {}, + ty_isize *const Type = {}, + ty_usize *const Type = {}, + ty_iptrint *const Type = {}, + ty_uptrint *const Type = {}, + ty_f32 *const Type = {}, + ty_f64 *const Type = {}, + ty_voidptr *const Type = {}, + ty_c_char *const Type = {}, + ty_c_long *const Type = {}, + ty_c_ulong *const Type = {}, + ty_c_llong *const Type = {}, + ty_c_ullong *const Type = {}, + ty_c_valist *const Type = {}; extern fn putprimtypes(env *Env) void { let types []struct { name *const u8, gty **const Type, ty Type } = { @@ -177,6 +183,12 @@ extern fn putprimtypes(env *Env) void { { "u64", &ty_u64, { .size: 8, g_targ.i64align, .u: :Int { .sgn: #f }}}, { "iptrint",&ty_iptrint, { g_targ.ptrsize, .u: :Int { .sgn: #t }}}, { "uptrint",&ty_uptrint, { g_targ.ptrsize, .u: :Int { .sgn: #f }}}, + { "c_char", &ty_c_char, { .size: 1, .u: :Int { .sgn: g_targ.charsigned }}}, + { "c_long", &ty_c_long, { g_targ.longsize, g_targ.longalign, .u: :Int { .sgn : #t }}}, + { "c_ulong",&ty_c_ulong, { g_targ.longsize, g_targ.longalign, .u: :Int { .sgn : #f }}}, + { "c_llong",&ty_c_llong, { g_targ.llongsize, g_targ.llongalign, .u: :Int { .sgn : #t }}}, + { "c_ullong",&ty_c_ullong,{ g_targ.llongsize, g_targ.llongalign, .u: :Int { .sgn : #f }}}, + { "c_valist",&ty_c_valist,{ g_targ.valistsize, g_targ.valistalign, .u: :VaList }}, }; foreach(type, _, types[0::]) { |