aboutsummaryrefslogtreecommitdiff
path: root/src/fmt.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-15 12:22:47 +0200
committerlemon <lsof@mailbox.org>2022-08-15 12:22:47 +0200
commitf906d0b350b0b4ceb747669c9a9845d11bd0e486 (patch)
tree5f09a7b714e6ce93f6094a06e5f736513110fb8d /src/fmt.cff
parentf802bb99263aaa5be492999babd44cd2fdb1c65f (diff)
self hosted progress
Diffstat (limited to 'src/fmt.cff')
-rw-r--r--src/fmt.cff121
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);
+}
+