diff options
| author | 2022-08-17 12:21:57 +0200 | |
|---|---|---|
| committer | 2022-08-17 12:24:19 +0200 | |
| commit | 37cd29c0299dc3a726c7f8273cf203a868133f57 (patch) | |
| tree | fca34a77b01fbc922f66ca2e99041b2222e603b3 /src | |
| parent | ffc52a0ecb61d0f7488f91d9b124344e50f7855f (diff) | |
struct,union
Diffstat (limited to 'src')
| -rw-r--r-- | src/fmt.cff | 3 | ||||
| -rw-r--r-- | src/parse.cff | 122 | ||||
| -rw-r--r-- | src/type.cff | 6 |
3 files changed, 98 insertions, 33 deletions
diff --git a/src/fmt.cff b/src/fmt.cff index 37b6dc9..00b9b54 100644 --- a/src/fmt.cff +++ b/src/fmt.cff @@ -292,6 +292,9 @@ extern fn ssfmt(fmt *const u8, ...) *const u8 { fn eprifileline(loc Loc) void { let path = fileid2path(loc.fileid); let fp = fopen(path, "rb"); + if fp == #null { + return; + } let line_begin = 0; for let i = 0; i < loc.idx; ++i { if fgetc(fp) == '\n' { diff --git a/src/parse.cff b/src/parse.cff index 13c89f5..34e7943 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -566,6 +566,8 @@ fn putdecl(P *Parser, eloc Loc, decl Decl) *Decl { // Types Parsing // /////////////////// +fn parsetype(P *Parser) *const Type; + fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type { let loc = P.tokloc; let tok Tok #?; @@ -577,9 +579,10 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type } } let ty = decl ? decl.u.Ty : interntype({ .u: :Agg { kind, name, id++ }}); - let agg = &(as(*Type)ty).u.Agg; + let ty = as(*Type)ty; + let agg = &ty.u.Agg; - if name != #null and lexmatch(P, &tok, ';') { + if name != #null { agg.fwd = #t; if decl == #null { decl = putdecl(P, loc, { name, loc, .u: :Ty(ty)}); @@ -587,11 +590,34 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type *retdecl = decl; } } - return ty; - } else { + } + if !lexmatch(P, &tok, ';') { agg.fwd = #f; - + lexexpect(P, '{'); + let size = 0, align = 1; + let flds Vec<AggField> = {}; + while !lexmatch(P, #null, '}') { + let off = size; + let name = lexexpect(P, :ident).u.ident; + let type = parsetype(P); + if type { + off = ALIGNUP(off, type.align); + align = MAX(align, type.align); + size = kind == :Struct ? off + type.size + : MAX(size, type.size); + } + flds->push({ name, type, off }); + + if !lexmatch(P, #null, ',') { + lexexpect(P, '}'); + break; + } + } + ty.size = size; + ty.align = align; + agg.flds = flds.dat[0::flds.len]; } + return ty; } fn xident2type(P *Parser, eloc Loc, name *const u8) *const Type { @@ -605,15 +631,68 @@ fn xident2type(P *Parser, eloc Loc, name *const u8) *const Type { return decl.u.Ty; } +fn parsefnparams(P *Parser, variadic *bool, paramnames *Vec<*const u8>, paramtys *Vec<*const Type>) void { + lexexpect(P, '('); + let tok Tok #?; + *variadic = #t; + while !lexmatch(P, &tok, ')') { + if lexmatch(P, #null, '...') { + *variadic = #t; + lexmatch(P, #null, ','); + lexexpect(P, ')'); + break; + } + let name *const u8 = #null; + let type *const Type #?; + if lexmatch(P, &tok, :ident) { + let tok2 Tok #?; + if (tok2 = lexpeek(P)).t == ',' or tok2.t == ')' { + type = xident2type(P, tok.loc, tok.u.ident); + } else { + name = tok.u.ident; + type = parsetype(P); + } + } else { + type = parsetype(P); + } + if paramnames { + paramnames->push(name); + } + paramtys->push(type); + if !lexmatch(P, &tok, ',') { + lexexpect(P, ')'); + break; + } + } +} + +fn parsefntype(P *Parser) *const Type { + let variadic = #f; + let paramtys Vec<*const Type> = {}; + parsefnparams(P, &variadic, #null, ¶mtys); + let ret = parsetype(P); + return interntype({ .u: :Fn { + paramtys->move(P.alloc), + variadic, + ret, + }}); +} + fn parsetype(P *Parser) *const Type { let tok Tok = {}; switch { case lexmatch(P, &tok, :kw_const); return constify(parsetype(P)); + case lexmatch(P, &tok, '*'); return mkptrtype(parsetype(P)); + case lexmatch(P, &tok, :ident); return xident2type(P, tok.loc, tok.u.ident); + + case lexmatch(P, &tok, :kw_fn); + return parsefntype(P); + case else; fatal(P, tok.loc, "expected type (near %qT)", tok); } @@ -1252,34 +1331,7 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl { paramnames Vec<*const u8> = {}, paramtys Vec<*const Type> = {}; - lexexpect(P, '('); - while !lexmatch(P, &tok, ')') { - if lexmatch(P, #null, '...') { - Fn.variadic = #t; - lexmatch(P, #null, ','); - lexexpect(P, ')'); - break; - } - let name *const u8 = #null; - let type *const Type #?; - if lexmatch(P, &tok, :ident) { - let tok2 Tok #?; - if (tok2 = lexpeek(P)).t == ',' or tok2.t == ')' { - type = xident2type(P, tok.loc, tok.u.ident); - } else { - name = tok.u.ident; - type = parsetype(P); - } - } else { - type = parsetype(P); - } - paramnames->push(name); - paramtys->push(type); - if !lexmatch(P, &tok, ',') { - lexexpect(P, ')'); - break; - } - } + parsefnparams(P, &Fn.variadic, ¶mnames, ¶mtys); Fn.paramnames = paramnames->move(P.alloc); let retty = parsetype(P); Fn.ty = interntype({ .size: 0, .align: 1, .u: :Fn { @@ -1393,6 +1445,10 @@ fn parsedecls(P *Parser, yield DeclYielder, yarg *void, toplevel bool) void { let name = lexexpect(P, :ident).u.ident; parseagg(P, :Struct, name, &decl); + case lexmatch(P, &tok, :kw_union); + let name = lexexpect(P, :ident).u.ident; + parseagg(P, :Union, name, &decl); + case lexmatch(P, &tok, :kw_static); struct Arg { P *Parser, diff --git a/src/type.cff b/src/type.cff index b18c5c4..1d224cc 100644 --- a/src/type.cff +++ b/src/type.cff @@ -93,6 +93,12 @@ struct TypeTraits { static id int = 0; *p = *ty; p.id = id++; + switch p.u { + case Fn *f; + let params = f.params; + f.params = (as(**const Type)xmalloc(params.#len * sizeof *Type))[0::params.#len]; + memcpy(f.params.#ptr, params.#ptr, params.#len * sizeof *Type); + } return p; } } |