diff options
| author | 2022-08-19 08:00:19 +0200 | |
|---|---|---|
| committer | 2022-08-19 08:00:19 +0200 | |
| commit | 3481ab142293bd82fdd59e3ec86dd66352e457c3 (patch) | |
| tree | a22bfef6fc5ce7b310ca5752b0765775d5bc921a | |
| parent | c82ffed2326500d1df4058cf629f341190b84b89 (diff) | |
enum union size,align and enumty
| -rw-r--r-- | bootstrap/test.cff | 6 | ||||
| -rw-r--r-- | src/cffc.hff | 1 | ||||
| -rw-r--r-- | src/parse.cff | 63 |
3 files changed, 59 insertions, 11 deletions
diff --git a/bootstrap/test.cff b/bootstrap/test.cff index ef0bbfb..31dfd6b 100644 --- a/bootstrap/test.cff +++ b/bootstrap/test.cff @@ -76,6 +76,12 @@ defmacro transmute(Type, x) [ ) ] +enum union Number { + none, + int i64, + flo f32, +} + extern fn main (argc int, argv **u8) int { let colors [3]Color = { :Red, :Green, :Blue } ; diff --git a/src/cffc.hff b/src/cffc.hff index af5bd6a..eff95e4 100644 --- a/src/cffc.hff +++ b/src/cffc.hff @@ -100,6 +100,7 @@ struct Type { name *const u8, id int, fwd bool, + enumty *const Type, flds [#]AggField, decls *Env, }, diff --git a/src/parse.cff b/src/parse.cff index 1449eab..84df71a 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -692,14 +692,25 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type let size = 0, align = 1; let flds Vec<AggField> = {}; let havedecls = #f; - while !lexmatch(P, #null, '}') { + let f0align = -1i64; + while !lexmatch(P, &tok, '}') { if isdecltokt(lexpeek(P).t) { havedecls = #t; break; } let off = size; - let name = lexexpects(P, :ident, "field name").u.ident; - let type = parsetype(P); + let name = (tok = lexexpects(P, :ident, "field name")).u.ident; + let type *const Type = #null; + + if !(kind == :EUnion and lexpeek(P).t == ',') { + type = parsetype(P); + if f0align < 0 { + f0align = type.align; + } + } + if type != #null and !completetype(type) { + err(P, tok.loc, "field `%s' is of incomplete type (%t)", name, type); + } if type { off = ALIGNUP(off, type.align); align = MAX(align, type.align); @@ -713,9 +724,39 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type break; } } + size = ALIGNUP(size, align); ty.size = size; ty.align = align; agg.flds = flds.dat[0::flds.len]; + if kind == :EUnion { + // add enum tag field on top and offset every other field down + static id int = 0; + let enumty Type = { .u: :Enum { #null, name, .id: --id }}; + let n = flds.len; + enumty.u.Enum.vals = (as(*EnumVal)malloc(n * sizeof EnumVal))[0::n]; + if n < 256 { + enumty.u.Enum.intty = ty_u8; + } else if n < 65536 { + enumty.u.Enum.intty = ty_u16; + } else { assert(#f, "wow"); } + enumty.size = enumty.u.Enum.intty.size; + enumty.align = enumty.u.Enum.intty.align; + vec_each(fld, i, flds) { + let ev = &enumty.u.Enum.vals[i]; + ev.name = fld.name; + ev.i = i; + } + agg.enumty = interntype(enumty); + + let off = f0align < 0 ? 0z : ALIGNUP(enumty.size, f0align); + ty.size += off; + align = MAX(align, enumty.align); + ty.size = ALIGNUP(ty.size, align); + + foreach_ptr(fld, _, agg.flds) { + fld.off += off; + } + } if havedecls { agg.decls = mkenv(P.curenv, P.alloc); pushenv(P, agg.decls); @@ -1758,9 +1799,9 @@ fn pstwhile(P *Parser) Stmt { } lexexpect(P, '{'); let t [#]Stmt #?; - with_tmpchange(P.curloop, ++P.loopid, + with_tmpchange(P.curloop, ++P.loopid) { t = parseblock(P); - ) + } return { loc, :While { test, t, P.loopid }}; } @@ -1799,9 +1840,9 @@ fn pstfor(P *Parser) Stmt { lexexpect(P, '{'); } let body [#]Stmt #?; - with_tmpchange(P.curloop, ++P.loopid, + with_tmpchange(P.curloop, ++P.loopid) { body = parseblock(P); - ) + } return { loc, :For { ini, test, next, body, P.loopid }}; } @@ -2040,8 +2081,8 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl { return decl; } - with_tmpchange(P.alloc, &Allocator { &Arena {}, &Arena:allocf }, - with_tmpchange(P.curfn, Fn, + with_tmpchange(P.alloc, &Allocator { &Arena {}, &Arena:allocf }) { + with_tmpchange(P.curfn, Fn) { let env = mkenv(P.curenv, P.alloc); pushenv(P, env); foreach(name, i, Fn.paramnames) { @@ -2055,8 +2096,8 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl { popenv(P); envfree(env); (as(*Arena)P.alloc.a)->destroy(); - ); - ); + } + } return decl; } |