diff options
| -rw-r--r-- | src/cffc.hff | 6 | ||||
| -rw-r--r-- | src/fold.cff | 31 | ||||
| -rw-r--r-- | src/parse.cff | 118 | ||||
| -rw-r--r-- | src/type.cff | 2 |
4 files changed, 129 insertions, 28 deletions
diff --git a/src/cffc.hff b/src/cffc.hff index 4563583..53b4db5 100644 --- a/src/cffc.hff +++ b/src/cffc.hff @@ -195,6 +195,11 @@ struct EUSwitchCase { t [#]Stmt } +struct CSwitchCase { + test Expr, + t [#]Stmt, +} + struct Stmt { loc Loc, u enum union { @@ -215,6 +220,7 @@ struct Stmt { Decl *Decl, ISwitch struct { ex Expr, cs [#]ISwitchCase, f [#]Stmt }, EUSwitch struct { ex Expr, cs [#]EUSwitchCase, f [#]Stmt }, + CSwitch struct { cs [#]CSwitchCase, f [#]Stmt } } } diff --git a/src/fold.cff b/src/fold.cff index a2c95b8..c9991b7 100644 --- a/src/fold.cff +++ b/src/fold.cff @@ -53,6 +53,37 @@ fn numcast(ex *Expr, to *const Type) void { } fn funary(ex *Expr) void { + let r = ex.u.UnOp.ex; + let ty = ex.ty; + let iu = &ex.u.IntLit; + let f = &ex.u.FloLit; + let b = &ex.u.BoolLit; + + if !fold(r) { + return; + } + switch ex.u.UnOp.op { + case :neg; + *ex = *r; + if r.ty->is(:Int) { + iu.i = -iu.i; + } else if r.ty->is(:Flo) { + *f = -*f; + } else { + assert(#f, "neg"); + } + numcast(ex, ty); + case :compl; + *ex = *r; + iu.i = ~iu.i; + assert(r.ty->is(:Int), "compl"); + numcast(ex, ty); + case :not; + *ex = *r; + *b = !*b; + assert(r.ty->is(:Bool), "not"); + } + ex.ty = ty; } fn fbinary(ex *Expr) void { diff --git a/src/parse.cff b/src/parse.cff index 89a059f..379fa90 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -176,6 +176,29 @@ fn xdigit2num(c u8) int { return -1; } +fn ty4intX(i u64) *const Type { + if i < 1u64 << ((g_targ.intsize * 8) - 1) { + return ty_int; + } + if i < 1u64 << 31 { + return ty_i32; + } + if i < 1u64 << 63 { + return ty_i64; + } + return ty_u64; +} + +fn ty4uintX(i u64) *const Type { + if i < 1u64 << (g_targ.intsize * 8) { + return ty_uint; + } + if i < 1u64 << 32 { + return ty_u32; + } + return ty_u64; +} + fn readnumber(s *const u8) Option<Tok> { let c u8 #?, acc = 0u64, @@ -203,6 +226,7 @@ fn readnumber(s *const u8) Option<Tok> { if (base == 16 and !isxdigit(c)) or (base != 16 and (c < '0' or c > ('0' + base) - 1)) { suffix = s + i; + break; } ++nused; @@ -232,29 +256,6 @@ fn readnumber(s *const u8) Option<Tok> { tok.t = :int; tok.u.uint = acc; - fn ty4intX(i u64) *const Type { - if i < 1u64 << ((g_targ.intsize * 8) - 1) { - return ty_int; - } - if i < 1u64 << 31 { - return ty_i32; - } - if i < 1u64 << 63 { - return ty_i64; - } - return ty_u64; - } - - fn ty4uintX(i u64) *const Type { - if i < 1u64 << (g_targ.intsize * 8) { - return ty_uint; - } - if i < 1u64 << 32 { - return ty_u32; - } - return ty_u64; - } - switch { case suffix == #null; tok.ty = ty4intX(tok.u.uint); case strcieq(suffix, "u"); tok.ty = ty4uintX(tok.u.uint); @@ -395,6 +396,8 @@ fn lex(P *Parser) Tok { tok.t = '##'; case streq(s, "#len"); tok.t = '#len'; + case streq(s, "#ptr"); + tok.t = '#ptr'; case streq(s, "#tag"); tok.t = '#tag'; case streq(s, "#FILE"); @@ -461,6 +464,7 @@ fn lex(P *Parser) Tok { vec_each(c0, i, str) { tok.u.uint = (tok.u.uint << 8) | c0; } + tok.ty = ty4intX(tok.u.uint); } return tok; } @@ -856,7 +860,7 @@ fn parseexpandtepl(P *Parser, tepl *Tepl) *const Type { case else fatal(P, ex.loc, "expected constant expression"); } - + case else assert(#f, "unreachable %d", par.u.#tag); } args[i].name = par.name; @@ -1017,7 +1021,8 @@ fn parsetype(P *Parser) *const Type { } 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 { + if !fold(&ex) or !(ex.u.#tag == :IntLit or (ex.u.#tag == :EnumIni and ex.ty.u.Enum.lax)) + or ex.u.IntLit.i < 0 { fatal(P, ex.loc, "expected constant non-negative integer expression for array length"); } len = ex.u.IntLit.i; @@ -1474,6 +1479,7 @@ fn pexpostfix(P *Parser) Expr { let params = Fn.params; let param = ¶ms[0]; while !lexmatch(P, #null, ')') { + P.targty = args.len + 1 <= params.#len ? *param : #null; let ex = parseexpr(P); args->push(ex); if args.len >= params.#len and !Fn.variadic { @@ -1629,7 +1635,9 @@ fn pexpostfix(P *Parser) Expr { } let args Vec<Expr> = {}; args->push(ex); + let param = &Fn.params[1]; while !lexmatch(P, #null, ')') { + P.targty = *param++; args->push(parseexpr(P)); if args.len > Fn.params.#len and !Fn.variadic { fatal(P, args->last().loc, "too many args (%z, expected %z)", args.len, Fn.params.#len); @@ -1791,7 +1799,11 @@ fn pexcmp(P *Parser) Expr { let ex = pexbitarith(P); let tok Tok = {}; if matchcmpop(P, &tok) { + if tok.t == '==' or tok.t == '!=' { + P.targty = ex.ty; + } let rhs = pexbitarith(P); + P.targty = #null; if typeof2(ex.ty, rhs.ty) == #null { fatal(P, tok.loc, "incompatible operands %t and %t to binary operator %qT", ex.ty, rhs.ty, tok); @@ -1900,6 +1912,9 @@ fn pexassign(P *Parser) Expr { if okind == :None { return ex; } + if tok.t == '=' { + P.targty = ex.ty; + } let rhs = pexcond(P); switch { case !islvalue(ex); @@ -1978,6 +1993,7 @@ fn pstreturn(P *Parser, loc Loc) Stmt { } return { loc, :Return{} }; } else { + P.targty = retty; let ex = parseexpr(P); lexexpect(P, ';'); if !typematchestarg(retty, ex.ty) { @@ -2026,6 +2042,7 @@ fn pstfor(P *Parser, loc Loc, label *const u8) Stmt { } else { let ex = parseexpr(P); ini = stmtdup(P.alloc, { ex.loc, :Expr(ex) })[0::1]; + lexexpect(P, ';'); } if lexmatch(P, &tok, ';') { @@ -2149,9 +2166,36 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt { return { loc, :EUSwitch { test, cs->move(P.alloc), f }}; } +fn pstcswitch(P *Parser, loc Loc) Stmt { + let cs Vec<CSwitchCase> = {}; + let tok Tok #?; + let f [#]Stmt = {}; + let elsep = #f; + + while !lexmatch(P, &tok, '}') { + let c CSwitchCase = {}; + lexexpect(P, :kw_case); + if lexmatch(P, &tok, :kw_else) { + if elsep { + err(P, tok.loc, "duplicate 'case else' block"); + } + elsep = #t; + f = parseblock0(P); + continue; + } + c.test = parseexpr(P); + lexexpect(P, ';'); + c.t = parseblock0(P); + } + + + return { loc, :CSwitch { cs->move(P.alloc), f }}; +} + fn pstswitch(P *Parser, loc Loc) Stmt { let tok Tok #?; if lexmatch(P, &tok, '{') { + return pstcswitch(P, loc); } else { let ex = parseexpr(P); lexexpect(P, '{'); @@ -2380,6 +2424,7 @@ fn parsefn(P *Parser, loc Loc, externp bool, name *const u8) *Decl { return decl; } +fn parse4import(P *Parser) [#]Decl; fn doimport(P *Parser, loc Loc, path *const u8) [#]Decl { struct Entry { decls [#]Decl, @@ -2415,11 +2460,12 @@ fn doimport(P *Parser, loc Loc, path *const u8) [#]Decl { return d0.decls; } rpath = strcpy(malloc(strlen(rpath) + 1), rpath); + let e = seen->put(rpath, { {}, #t }); let P2 Parser #?; parser_init(&P2, rpath); P2.is_header = #t; - let e = seen->put(rpath, { {}, #t }); - let decls = parse(&P2); + P2.alloc = P.alloc; + let decls = parse4import(&P2); *e = { decls, #f }; return decls; @@ -2734,6 +2780,24 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) } } +fn parse4import(P *Parser) [#]Decl { + let decls Vec<Decl> = {}; + P.curenv = mkenv(#null, P.alloc); + + while !P.eof { + fn yield(decl *Decl, arg *void) void { + let decls *Vec<Decl> = arg; + decls->push(*decl); + } + parsedecls(P, P.tokloc, &yield, &decls, #{toplevel} #t); + if lexmatch(P, #null, :eof) { + break; + } + } + + return decls.dat[0::decls.len]; +} + extern fn parse(P *Parser) [#]Decl { let aralloc = Arena {}; let alloc = Allocator { &aralloc, &Arena:allocf, #null }; diff --git a/src/type.cff b/src/type.cff index a07ea0d..dd59517 100644 --- a/src/type.cff +++ b/src/type.cff @@ -188,7 +188,7 @@ extern fn putprimtypes(env *Env) void { { "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 }}, + { "va_list",&ty_c_valist,{ g_targ.valistsize, g_targ.valistalign, .u: :VaList }}, }; foreach(type, _, types[0::]) { |