diff --git a/src/h.h b/src/h.h index b1c0a36d..6fed9315 100644 --- a/src/h.h +++ b/src/h.h @@ -7,9 +7,6 @@ #include #include -#define usz u64 -#define ur u8 - #define i8 int8_t #define u8 uint8_t #define i16 int16_t @@ -23,6 +20,9 @@ #define U16_MAX ((u16)-1) #define UD __builtin_unreachable(); +#define usz u32 +#define ur u8 + #ifdef DEBUG #include #define VALIDATE(x) validate(x) // preferred validating level @@ -72,7 +72,7 @@ enum Type { enum PrimFns { pf_none, pf_add, pf_sub, pf_mul, pf_div, pf_pow, pf_floor, pf_eq, pf_le, pf_log, // arith.c - pf_shape, pf_pick, pf_ud, pf_pair, pf_fne, pf_lt, pf_rt, // sfns.c + pf_shape, pf_pick, pf_ud, pf_pair, pf_fne, pf_lt, pf_rt, pf_fmtF, pf_fmtN, // sfns.c pf_fork, pf_atop, pf_md1d, pf_md2d, // derv.c pf_type, pf_decp, pf_primInd, pf_glyph, pf_fill, pf_grLen, pf_grOrd, pf_asrt, // sysfn.c }; @@ -80,7 +80,7 @@ char* format_pf(u8 u) { switch(u) { default: case pf_none: return"(unknown fn)"; case pf_add:return"+"; case pf_sub:return"-"; case pf_mul:return"×"; case pf_div:return"÷"; case pf_pow:return"⋆"; case pf_floor:return"⌊"; case pf_eq:return"="; case pf_le:return"≤"; case pf_log:return"⋆⁼"; - case pf_shape:return"⥊"; case pf_pick:return"⊑"; case pf_ud:return"↕"; case pf_pair:return"{𝕨‿𝕩}"; case pf_fne:return"≢"; case pf_lt:return"⊣"; case pf_rt:return"⊢"; + case pf_shape:return"⥊"; case pf_pick:return"⊑"; case pf_ud:return"↕"; case pf_pair:return"{𝕨‿𝕩}"; case pf_fne:return"≢"; case pf_lt:return"⊣"; case pf_rt:return"⊢"; case pf_fmtF:case pf_fmtN:return"⍕"; case pf_fork:return"(fork)"; case pf_atop:return"(atop)"; case pf_md1d:return"(derived 1-modifier)"; case pf_md2d:return"(derived 2-modifier)"; case pf_type:return"•Type"; case pf_decp:return"•Decompose"; case pf_primInd:return"•PrimInd"; case pf_glyph:return"•Glyph"; case pf_fill:return"•FillFn"; case pf_grLen:return"•GroupLen"; case pf_grOrd:return"•GroupOrd"; case pf_asrt:return"!"; } } @@ -270,8 +270,8 @@ typedef struct TypeInfo { B2V visit; // for GC when that comes around B2V print; // doesn't consume BS2B get; // increments result, doesn't consume arg - BB2B m1_d; // consume all args - BBB2B m2_d; // consume all args + BB2B m1_d; // consume all args; (m, f) + BBB2B m2_d; // consume all args; (m, f, g) B2B decompose; // consumes; must return a HArr BS2B slice; // consumes; create slice from given starting position; add ia, rank, shape yourself } TypeInfo; @@ -349,6 +349,22 @@ void print(B x) { else if (x.u==bi_badHdr.u) printf("(bad header note)"); else printf("(todo tag %lx)", x.u>>48); } +void printRaw(B x) { + if (isAtm(x)) { + if (isF64(x)) printf("%g", x.f); + else if (isC32(x)) printUTF8((u32)x.u); + else err("bad printRaw argument: atom arguments should be either numerical or characters"); + } else { + usz ia = a(x)->ia; + BS2B xget = TI(x).get; + for (usz i = 0; i < ia; i++) { + B c = xget(x,i); + if (c.u==0) { printf(" "); continue; } + if (!isC32(c)) err("bad printRaw argument: expected all character items"); + printUTF8((u32)c.u); + } + } +} diff --git a/src/harr.c b/src/harr.c index d284274f..75783b5d 100644 --- a/src/harr.c +++ b/src/harr.c @@ -48,16 +48,28 @@ HArr* toHArr(B x) { -B m_caf64(usz sz, f64* a) { - HArr_p r = m_harrv(sz); - for (usz i = 0; i < sz; i++) r.a[i] = m_f64(a[i]); - return r.b; -} B m_caB(usz ia, B* a) { HArr_p r = m_harrv(ia); for (usz i = 0; i < ia; i++) r.a[i] = a[i]; return r.b; } +B m_str8(u64 sz, char* s) { + HArr_p r = m_harrv(sz); + for (u64 i = 0; i < sz; i++) r.a[i] = m_c32(s[i]); + return r.b; +} +B m_str32(u32* s) { // meant to be used as m_str32(U"{𝕨‿𝕩}") + u64 sz = 0; + while(s[sz])sz++; + HArr_p r = m_harrv(sz); + for (u64 i = 0; i < sz; i++) r.a[i] = m_c32(s[i]); + return r.b; +} +B m_caf64(usz sz, f64* a) { + HArr_p r = m_harrv(sz); + for (usz i = 0; i < sz; i++) r.a[i] = m_f64(a[i]); + return r.b; +} B m_v1(B a ) { HArr_p r = m_harrv(1); r.a[0] = a; return r.b; } B m_v2(B a, B b ) { HArr_p r = m_harrv(2); r.a[0] = a; r.a[1] = b; return r.b; } diff --git a/src/main.c b/src/main.c index 7126f59b..ef61f310 100644 --- a/src/main.c +++ b/src/main.c @@ -3,11 +3,13 @@ // #define DEBUG_VM #endif // #define ALLOC_STAT +// #define FORMATTER #include "h.h" #include "mm.c" #include "harr.c" #include "i32arr.c" +#include "utf.c" #include "arith.c" #include "sfns.c" #include "md1.c" @@ -15,7 +17,6 @@ #include "sysfn.c" #include "derv.c" #include "vm.c" -#include "utf.c" void pr(char* a, B b) { printf("%s", a); @@ -32,19 +33,6 @@ Block* ca3(B b) { return r; } -B m_str8(char* s) { - u64 sz = strlen(s); - HArr_p r = m_harrv(sz); - for (u64 i = 0; i < sz; i++) r.a[i] = m_c32(s[i]); - return r.b; -} -B m_str32(u32* s) { - u64 sz = 0; - while(s[sz])sz++; - HArr_p r = m_harrv(sz); - for (u64 i = 0; i < sz; i++) r.a[i] = m_c32(s[i]); - return r.b; -} __ssize_t getline (char **__restrict __lineptr, size_t *restrict n, FILE *restrict stream); @@ -104,6 +92,14 @@ int main() { ); B comp = m_funBlock(comp_b, 0); ptr_dec(comp_b); + #ifdef FORMATTER + Block* fmt_b = compile( + #include "formatter" + ); + B fmtM = m_funBlock(fmt_b, 0); ptr_dec(fmt_b); + B fmt = TI(fmtM).m1_d(fmtM, m_caB(4, (B[]){inci(bi_type), inci(bi_decp), inci(bi_fmtF), inci(bi_fmtN)})); + #endif + // uncomment to self-compile and use that for the REPL; expects a copy of mlochbaum/BQN/src/c.bqn to be at the execution directory // char* c_src = 0; @@ -137,7 +133,13 @@ int main() { B cbc = c2(comp, inci(rtObj), obj); free(ln); Block* cbc_b = ca3(cbc); + #ifdef FORMATTER + B res = c1(fmt, m_funBlock(cbc_b, 0)); + printRaw(res); dec(res); + printf("\n"); + #else pr("", m_funBlock(cbc_b, 0)); + #endif } dec(rtRes); diff --git a/src/sfns.c b/src/sfns.c index e758943d..d5ca8207 100644 --- a/src/sfns.c +++ b/src/sfns.c @@ -89,14 +89,28 @@ B lt_c2(B t, B w, B x) { dec(x); return w; } B rt_c1(B t, B x) { return x; } B rt_c2(B t, B w, B x) { dec(w); return x; } +B fmtN_c1(B t, B x) { + const u64 BL = 100; + char buf[BL]; + if (isF64(x)) snprintf(buf, BL, "%g", x.f); + else snprintf(buf, BL, "(fmtN: not given a number?)"); + return m_str8(strlen(buf), buf); +} +B fmtF_c1(B t, B x) { + if (!isVal(x)) return m_str32(U"(fmtF: not given a function)"); + u8 fl = v(x)->flags; + if (fl==0 || fl>=62) return m_str32(U"(fmtF: not given a runtime primitive)"); + return m_c32(U"+-×÷⋆√⌊⌈|¬∧∨<>≠=≤≥≡≢⊣⊢⥊∾≍↑↓↕«»⌽⍉/⍋⍒⊏⊑⊐⊒∊⍷⊔!˙˜˘¨⌜⁼´˝`∘○⊸⟜⌾⊘◶⎉⚇⍟"[fl-1]); +} + #define ba(NAME) bi_##NAME = mm_alloc(sizeof(Fun), t_fun_def, ftag(FUN_TAG)); c(Fun,bi_##NAME)->c2 = NAME##_c2; c(Fun,bi_##NAME)->c1 = NAME##_c1 ; c(Fun,bi_##NAME)->extra=pf_##NAME; #define bd(NAME) bi_##NAME = mm_alloc(sizeof(Fun), t_fun_def, ftag(FUN_TAG)); c(Fun,bi_##NAME)->c2 = NAME##_c2; c(Fun,bi_##NAME)->c1 = c1_invalid; c(Fun,bi_##NAME)->extra=pf_##NAME; #define bm(NAME) bi_##NAME = mm_alloc(sizeof(Fun), t_fun_def, ftag(FUN_TAG)); c(Fun,bi_##NAME)->c2 = c2_invalid;c(Fun,bi_##NAME)->c1 = NAME##_c1 ; c(Fun,bi_##NAME)->extra=pf_##NAME; void print_fun_def(B x) { printf("%s", format_pf(c(Fun,x)->extra)); } -B bi_shape, bi_pick, bi_ud, bi_pair, bi_fne, bi_lt, bi_rt; -void sfns_init() { ba(shape) ba(pick) bm(ud) ba(pair) bm(fne) ba(lt) ba(rt) +B bi_shape, bi_pick, bi_ud, bi_pair, bi_fne, bi_lt, bi_rt, bi_fmtF, bi_fmtN; +void sfns_init() { ba(shape) ba(pick) bm(ud) ba(pair) bm(fne) ba(lt) ba(rt) bm(fmtF) bm(fmtN) ti[t_fun_def].print = print_fun_def; } diff --git a/src/utf.c b/src/utf.c index 8f35da61..c52e810f 100644 --- a/src/utf.c +++ b/src/utf.c @@ -32,3 +32,10 @@ void printUTF8(u32 c) { else if (c<=0xFFFF) printf("%c%c%c" , 0xE0| c>>12, 0x80| (c>>6 &0x3F), 0x80| (c &0x3F) ); else printf("%c%c%c%c", 0xF0| c>>18, 0x80| (c>>12 &0x3F), 0x80| (c>>6 &0x3F), 0x80| (c&0x3F)); } + +u64 snprintUTF8(char* p, u64 l, u32 c) { + if (c<128) return snprintf(p, l, "%c", c); + else if (c<=0x07FF) return snprintf(p, l, "%c%c" , 0xC0| c>>6 , 0x80| (c &0x3F) ); + else if (c<=0xFFFF) return snprintf(p, l, "%c%c%c" , 0xE0| c>>12, 0x80| (c>>6 &0x3F), 0x80| (c &0x3F) ); + else return snprintf(p, l, "%c%c%c%c", 0xF0| c>>18, 0x80| (c>>12 &0x3F), 0x80| (c>>6 &0x3F), 0x80| (c&0x3F)); +} diff --git a/src/vm.c b/src/vm.c index de2f2d28..ca87fdb7 100644 --- a/src/vm.c +++ b/src/vm.c @@ -341,7 +341,12 @@ B evalBC(Body* b, Scope* sc) { break; } // not implemented: VARO VARM CHKV VFYM SETH FLDO FLDM NSPM RETD SYSV - default: printf("todo %d\n", bc[-1]); bc++; break; + default: + #ifdef DEBUG + printf("todo %d\n", bc[-1]); bc++; break; + #else + UD; + #endif case RETN: goto end; } #ifdef DEBUG_VM