diff options
Diffstat (limited to 'src/fmt.cff')
| -rw-r--r-- | src/fmt.cff | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/fmt.cff b/src/fmt.cff index 90fcd47..5635103 100644 --- a/src/fmt.cff +++ b/src/fmt.cff @@ -1,5 +1,6 @@ import "cffc.hff"; import "common.hff"; +import "util.hff"; extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) void { defmacro p(x) [ proc(x, parg) ] @@ -67,6 +68,8 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) if quote { p('\''); } case :type; pfmt(proc, parg, "%t", tok.ty); + case :eof; + ps("<end of file>"); case else if tok.t >= 0 and tok.t < NUM_KEYWORDS { if quote { p('`'); } @@ -86,6 +89,83 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) } } + fn pritokt(proc typeof(proc), parg *void, t TokT) void { + switch t { + case :int; + ps("integer literal"); + case :flo; + ps("float literal"); + case :bool; + ps("boolean literal"); + case :str; + ps("string literal"); + case :chr; + ps("character literal"); + case :null; + ps("#null"); + case :ident, :macident; + ps("identifier"); + case :label; + ps("label"); + case :gensym; + ps("gensym"); + case :type; + ps("type argument"); + case else + if t >= 0 and t < NUM_KEYWORDS { + p('`'); + ps(keyword2str[t]); + p('\''); + } else if t > 0 { + p('`'); + let t = bswap32(t); + while t != 0 { + if t & 0xFF != 0 { + p(t); + } + t >>= 8; + } + p('\''); + } + } + } + + fn pritype(proc typeof(proc), parg *void, ty *const Type) void { + if ty.konst { + ps("const "); + } + switch ty.u { + case Void; ps("void"); + case Bool; ps("bool"); + case Int i; + p(i.sgn ? 'i' : 'u'); + sprintf(buf, "%zu", ty.size * 8); + ps(buf); + case Flo; + p('f'); + sprintf(buf, "%zu", ty.size * 8); + ps(buf); + case Ptr child; + pfmt(proc, parg, "*%t", child); + case Arr arr; + pfmt(proc, parg, "[%I]%t", arr.length, arr.child); + case Slice child; + pfmt(proc, parg, "[#]%t", child); + case Fn f; + ps("fn ("); + foreach(ty, i, f.params, + pritype(proc, parg, ty); + if f.variadic or i < f.params.#len - 1 { + ps(", "); + } + ) + if f.variadic { + ps("..."); + } + pfmt(proc, parg, ") %t", f.ret); + } + } + for let c u8 = *fmt; c != 0; c = *++fmt { assert(c != 0, "?"); if c != '%' { @@ -102,6 +182,12 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) case 'i', 'd'; sprintf(buf, "%d", ap->arg(int)); ps(buf); + case 'I', 'D'; + sprintf(buf, "%lld", as(c_llong)ap->arg(i64)); + ps(buf); + case 'z'; + sprintf(buf, "%zu", ap->arg(usize)); + ps(buf); case 'p'; sprintf(buf, "%p", ap->arg(*void)); ps(buf); @@ -147,6 +233,11 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) case 'T'; let tok = ap->arg(Tok); pritok(proc, parg, quote, &tok); + case 'k'; + let tokt = ap->arg(TokT); + pritokt(proc, parg, tokt); + case 't'; + pritype(proc, parg, ap->arg(*const Type)); case else assert(#f, "bad fmt '%c'", c); } @@ -175,3 +266,33 @@ extern fn efmt(fmt *const u8, ...) void { vefmt(fmt, ap); ap->end(); } + +extern fn ssfmt(fmt *const u8, ...) *const u8 { + static buf [1024]u8 = {}; + let ap va_list #?; + ap->start(fmt); + fn sputc(c u8, arg *void) void { + let pidx *int = arg; + if *pidx < buf.#len - 1 { + buf[*pidx++] = c; + } + } + let idx = 0; + vpfmt(&sputc, &idx, fmt, ap); + ap->end(); +} + +extern fn vdiag(P *Parser, loc Loc, kind *const u8, fmt *const u8, ap va_list) void { + efmt("%s:%i:%i: %s: ", fileid2path(loc.fileid), loc.line, loc.col, kind); + vefmt(fmt, ap); + efmt("\n"); +} + +extern fn fatal(P *Parser, loc Loc, fmt *const u8, ...) void { + let ap va_list #?; + ap->start(fmt); + vdiag(P, loc, "error", fmt, ap); + ap->end(); + exit(1); +} + |