From c2013e3b5d67ffebf98e4befc3f501aaec0dfc8c Mon Sep 17 00:00:00 2001 From: dzaima Date: Sat, 15 May 2021 17:51:17 +0300 Subject: [PATCH] =?UTF-8?q?=E2=80=A2args,=20=E2=80=A2FLines,=20command-lin?= =?UTF-8?q?e=20options,=20=E2=80=A2Repr,=20fix=20unit=E2=88=BEunit=20fill?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cc.bqn | 17 ++++++----- src/fillarr.c | 18 ++++++----- src/fns.c | 9 +----- src/h.h | 12 ++++---- src/load.c | 22 ++++++++----- src/main.c | 77 +++++++++++++++++++++++++++++++++++++++++++--- src/md1.c | 36 +++++++++++++++++++--- src/sfns.c | 17 +++++++++-- src/stuff.c | 1 + src/sysfn.c | 21 ++++++++++--- src/vm.c | 85 +++++++++++++++++++++++++++------------------------ 11 files changed, 221 insertions(+), 94 deletions(-) diff --git a/cc.bqn b/cc.bqn index bcfdc6e7..78ade8ca 100755 --- a/cc.bqn +++ b/cc.bqn @@ -7,8 +7,8 @@ return ← 1≡⊑args args↓˜↩ return path←(⊑args)∾"/src/" args↓˜↩1 -L ← {"m_caB(" ∾(⍕≠𝕩)∾",(B[]){" ∾(1↓∾","⊸∾¨𝕩)∾"})"} -LI ← {"m_cai32("∾(⍕≠𝕩)∾",(i32[]){"∾(1↓∾","⊸∾¨𝕩)∾"})"} +L ← {"m_caB(" ∾(•Repr≠𝕩)∾",(B[]){" ∾(1↓∾","⊸∾¨𝕩)∾"})"} +LI ← {"m_cai32("∾(•Repr≠𝕩)∾",(i32[]){"∾(1↓∾","⊸∾¨𝕩)∾"})"} # Escape the special characters that appear in BQN sources. Esc←{ in ← (@+0‿9‿10‿13)∾"'""" # Null, Tab, LF, CR, and quotes @@ -19,9 +19,9 @@ Esc←{ } Str ← "m_str32(U"""∾Esc∾""")"˙ # A BQN string Char ← {"m_c32(U'"∾(Esc⥊𝕩)∾"')"} # A BQN character -Num ← {s←"-"/˜𝕩<0 ⋄ ∞⊸=∘|◶⟨"m_f64("∾")"∾˜s∾⍕∘| ⋄ "m_f64("∾s∾"1.0/0.0)"⟩𝕩} # Format number +Num ← {s←"-"/˜𝕩<0 ⋄ ∞⊸=∘|◶⟨"m_f64("∾")"∾˜s∾•Repr∘| ⋄ "m_f64("∾s∾"1.0/0.0)"⟩𝕩} # Format number -F ← ⍕ # Format number +F ← •Repr # Format number Import ← {𝕨•Import path∾𝕩} FChars ← {𝕨•FChars path∾𝕩} @@ -30,12 +30,13 @@ FLines ← {𝕨•FLines path∾𝕩} glyphs ← Import "glyphs.bqn" _getComp ← { (3+useInd) ↑ (𝕗 Import "c.bqn"){𝔽} } useInd ← "-i"≡⊑args ⋄ args↓˜↩useInd -Comp ← ((<"inc(runtime["∾⍕∾"])"˙)¨↕62) glyphs _getComp ⊢ -J ← ∾∾⟜\n¨ +Comp ← ((<"inc(runtime["∾•Repr∾"])"˙)¨↕62) glyphs _getComp ⊢ +J ← ∾∾⟜(@+10)¨ Fconst ← ≡◶⟨@⊸≤◶Num‿Char, Str, ⊑⟩ Fout ← {((≠𝕩)↑⟨LI F¨,L Fconst¨,L (LI ·F¨ 4↑⊢)¨,L (L F¨)¨⟩) {𝕎𝕩}¨ 𝕩} Frun ← 1⊸Fout -Long ← {¯2↓∾𝕩∾¨<","∾\n} +Long ← {¯2↓∾𝕩∾¨<","∾@+10} +LFC ← Long∘Fout∘Comp RT ← { src‿need‿inputs←𝕩Import"pr.bqn" @@ -43,7 +44,7 @@ RT ← { Long Fout pr need _getComp src } CArg ← {J (¯5⊸↓∾𝕩˙)⌾⊑ FLines "c.bqn"} -LFC ← Long∘Fout∘Comp +SVG ← {∾⟨"Modify←GetHighlights←⊢⋄"⟩∾ FChars∘∾⟜".bqn"¨ "../svg"‿𝕩} •Out⍟(¬return) (⊑"r"‿"r0"‿"r1"‿"c"‿"cc"‿"f"‿"e"‿"p"⊐⊏)◶⟨ RT∘2, RT∘0, RT∘1 diff --git a/src/fillarr.c b/src/fillarr.c index 80db5d7d..d26348d5 100644 --- a/src/fillarr.c +++ b/src/fillarr.c @@ -6,11 +6,7 @@ typedef struct FillArr { B a[]; } FillArr; -B getFillQ(B x) { // doesn't consume; can return bi_noFill - bool defZero = true; - #ifdef CATCH_ERRORS - defZero = false; - #endif +B getFillR(B x) { // doesn't consume; can return bi_noFill if (isArr(x)) { u8 t = v(x)->type; if (t==t_fillarr ) { B r = inc(c(FillArr,x )->fill); return r; } @@ -18,12 +14,18 @@ B getFillQ(B x) { // doesn't consume; can return bi_noFill if (t==t_c32arr || t==t_c32slice) return m_c32(' '); if (t==t_i32arr || t==t_i32slice) return m_f64(0 ); if (t==t_f64arr || t==t_f64slice) return m_f64(0 ); - return defZero? m_f64(0) : bi_noFill; + return bi_noFill; } if (isF64(x)|isI32(x)) return m_i32(0); if (isC32(x)) return m_c32(' '); - - return defZero? m_f64(0) : bi_noFill; + return bi_noFill; +} +B getFillQ(B x) { // doesn't consume; can return bi_noFill if CATCH_ERRORS + B r = getFillR(x); + #ifdef CATCH_ERRORS + return r; + #endif + return noFill(r)? m_f64(0) : r; } B getFillE(B x) { // errors if there's no fill B xf = getFillQ(x); diff --git a/src/fns.c b/src/fns.c index 05163d79..3442ce4e 100644 --- a/src/fns.c +++ b/src/fns.c @@ -81,13 +81,6 @@ B ltack_c2(B t, B w, B x) { dec(x); return w; } B rtack_c1(B t, B x) { return x; } B rtack_c2(B t, B w, B x) { dec(w); return x; } -B fmtN_c1(B t, B x) { - #define 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; @@ -180,7 +173,7 @@ B fne_c2(B t, B w, B x) { #define BI_FNS1(F) F(BI_A,BI_M,BI_D) -#define F(A,M,D) A(ud) A(fne) A(feq) A(ltack) A(rtack) M(fmtF) M(fmtN) +#define F(A,M,D) A(ud) A(fne) A(feq) A(ltack) A(rtack) M(fmtF) BI_FNS0(F); static inline void fns_init() { BI_FNS1(F) ti[t_funBI].print = print_funBI; diff --git a/src/h.h b/src/h.h index 6d37f4f2..ac34833c 100644 --- a/src/h.h +++ b/src/h.h @@ -123,11 +123,11 @@ char* format_type(u8 u) { #define FOR_PF(F) F(none, "(unknown fn)") \ /*arith.c*/ F(add,"+") F(sub,"-") F(mul,"×") F(div,"÷") F(pow,"⋆") F(floor,"⌊") F(ceil,"⌈") F(stile,"|") F(eq,"=") \ /*arith.c*/ F(ne,"≠") F(le,"≤") F(ge,"≥") F(lt,"<") F(gt,">") F(and,"∧") F(or,"∨") F(not,"¬") F(log,"⋆⁼") \ - /*fns.c*/ F(ud,"↕") F(fne,"≢") F(feq,"≡") F(ltack,"⊣") F(rtack,"⊢") F(fmtF,"•FmtF") F(fmtN,"•FmtN") \ + /*fns.c*/ F(ud,"↕") F(fne,"≢") F(feq,"≡") F(ltack,"⊣") F(rtack,"⊢") F(fmtF,"•FmtF") \ /*sfns.c*/ F(shape,"⥊") F(pick,"⊑") F(pair,"{𝕨‿𝕩}") F(select,"⊏") F(slash,"/") F(join,"∾") F(couple,"≍") F(shiftb,"»") F(shifta,"«") F(take,"↑") F(drop,"↓") F(group,"⊔") \ /*derv.c*/ F(fork,"(fork)") F(atop,"(atop)") F(md1d,"(derived 1-modifier)") F(md2d,"(derived 2-modifier)") \ /*sort.c*/ F(gradeUp,"⍋") \ - /*sysfn.c*/ F(type,"•Type") F(decp,"•Decompose") F(primInd,"•PrimInd") F(glyph,"•Glyph") F(fill,"•FillFn") \ + /*sysfn.c*/ F(type,"•Type") F(decp,"•Decompose") F(primInd,"•PrimInd") F(glyph,"•Glyph") F(repr,"•Repr") F(fill,"•FillFn") \ /*sysfn.c*/ F(grLen,"•GroupLen") F(grOrd,"•groupOrd") F(asrt,"!") F(sys,"•getsys") F(bqn,"•BQN") F(cmp,"•Cmp") F(internal,"•Internal") F(show,"•Show") F(out,"•Out") \ enum PrimFns { @@ -145,13 +145,13 @@ char* format_pf(u8 u) { enum PrimMd1 { pm1_none, pm1_tbl, pm1_each, pm1_fold, pm1_scan, pm1_const, pm1_swap, pm1_timed, // md1.c - pm1_fchars, pm1_fbytes, pm1_import, // md1.c + pm1_fchars, pm1_fbytes, pm1_flines, pm1_import, // md1.c }; char* format_pm1(u8 u) { switch(u) { default: case pf_none: return"(unknown 1-modifier)"; case pm1_tbl:return"⌜"; case pm1_each:return"¨"; case pm1_fold:return"´"; case pm1_scan:return"`"; case pm1_const:return"˙"; case pm1_swap:return"˜"; case pm1_timed:return"•_timed"; - case pm1_fchars:return"•FChars"; case pm1_fbytes:return"•FBytes"; case pm1_import:return"•Import"; + case pm1_fchars:return"•FChars"; case pm1_fbytes:return"•FBytes"; case pm1_flines:return"•FLines"; case pm1_import:return"•Import"; } } enum PrimMd2 { @@ -258,8 +258,8 @@ B m_unit (B x); // consumes B m_hunit(B x); // consumes B m_str32(u32* s); // meant to be used as m_str32(U"{𝕨‿𝕩}"), so doesn't free for you -B bqn_exec(B str, B path); // consumes both -B bqn_execFile(B path); // consumes +B bqn_exec(B str, B path, B args); // consumes both +B bqn_execFile(B path, B args); // consumes NOINLINE NORETURN void thr(B b); NOINLINE NORETURN void thrM(char* s); diff --git a/src/load.c b/src/load.c index 0d032dff..03529f2f 100644 --- a/src/load.c +++ b/src/load.c @@ -23,17 +23,22 @@ B bqn_fmt(B x) { // consumes } #endif -void load_gcFn() { mm_visit(comp_currPath); } -Block* bqn_comp(B str, B path) { // consumes both +void load_gcFn() { + mm_visit(comp_currPath); + mm_visit(comp_currArgs); +} + +Block* bqn_comp(B str, B path, B args) { // consumes all comp_currPath = path; + comp_currArgs = args; Block* r = load_compObj(c2(load_comp, inc(load_compArg), inc(str)), str); - dec(path); - comp_currPath = bi_N; + dec(path); dec(args); + comp_currArgs = comp_currPath = bi_N; return r; } -B bqn_exec(B str, B path) { // consumes both - Block* block = bqn_comp(str, path); +B bqn_exec(B str, B path, B args) { // consumes all + Block* block = bqn_comp(str, path, args); B res = m_funBlock(block, 0); ptr_dec(block); return res; @@ -45,6 +50,7 @@ void bqn_setComp(B comp) { // consumes; doesn't unload old comp, but whatever static inline void load_init() { comp_currPath = bi_N; + comp_currArgs = bi_N; gc_addFn(load_gcFn); B fruntime[] = { /* +-×÷⋆√⌊⌈|¬ */ bi_add , bi_sub , bi_mul , bi_div , bi_pow , bi_N , bi_floor, bi_ceil, bi_stile , bi_not, @@ -161,6 +167,6 @@ static inline void load_init() { #endif // NO_COMP } -B bqn_execFile(B path) { // consumes - return bqn_exec(file_chars(inc(path)), path); +B bqn_execFile(B path, B args) { // consumes both + return bqn_exec(file_chars(inc(path)), path, args); } diff --git a/src/main.c b/src/main.c index 78107691..25cc7f56 100644 --- a/src/main.c +++ b/src/main.c @@ -81,8 +81,77 @@ int main(int argc, char* argv[]) { exit(1); } #endif - - if (argc==1) { + bool startREPL = argc==1; + if (!startREPL) { + i32 i = 1; + while (i!=argc) { + char* carg = argv[i]; + if (carg[0]!='-') break; + i++; + if (carg[1]=='-') { + if (!strcmp(carg, "--help")) { + printf( + "Usage: %s [options] [file.bqn [arguments]]\n" + "Options:\n" + "-f file: execute the contents of the file with all further arguments as •args\n" + "-e code: execute the argument as BQN\n" + "-p code: execute the argument as BQN and print its result pretty-printed\n" + "-o code: execute the argument as BQN and print its raw result\n" + "-r : start the REPL after all further arguments\n" + , argv[0]); + exit(0); + } else { + printf("%s: Unknown option: %s\n", argv[0], carg); + exit(1); + } + } else { + carg++; + char c; + while ((c=*carg++) != '\0') { + switch(c) { default: printf("Unknown option: -%c\n", c); + #define REQARG(X) if(*carg) { printf("%s: -%s must end the option\n", argv[0], #X); exit(1); } if (i==argc) { printf("%s: -%s requires an argument\n", argv[0], #X); exit(1); } + case 'f': REQARG(f); goto execFile; + case 'e': { REQARG(e); + dec(bqn_exec(fromUTF8l(argv[i++]), m_str32(U"-e"), inc(bi_emptyHVec))); + break; + } + case 'p': { REQARG(p); + B r = bqn_exec(fromUTF8l(argv[i++]), m_str32(U"-e"), inc(bi_emptyHVec)); + print(r); dec(r); + printf("\n"); + break; + } + case 'o': { REQARG(o); + B r = bqn_exec(fromUTF8l(argv[i++]), m_str32(U"-e"), inc(bi_emptyHVec)); + printRaw(r); dec(r); + printf("\n"); + break; + } + case 'r': { + startREPL = true; + break; + } + } + } + } + } + execFile: + if (i!=argc) { + B src = fromUTF8l(argv[i++]); + B args; + if (i==argc) { + args = inc(bi_emptyHVec); + } else { + HArr_p ap = m_harrUv(argc-i); // eh whatever, erroring will exit anyways + for (usz j = 0; j < argc-i; j++) { + ap.a[j] = fromUTF8l(argv[i+j]); + } + args = ap.b; + } + dec(bqn_execFile(src, args)); + } + } + if (startREPL) { while (CATCH) { printf("Error: "); print(catchMessage); putchar('\n'); vm_pst(envCurr, envStart+envPrevHeight); @@ -94,7 +163,7 @@ int main(int argc, char* argv[]) { size_t gl = 0; getline(&ln, &gl, stdin); if (ln[0]==0 || ln[0]==10) break; - Block* block = bqn_comp(fromUTF8(ln, strlen(ln)), inc(replPath)); + Block* block = bqn_comp(fromUTF8(ln, strlen(ln)), inc(replPath), inc(bi_emptyHVec)); free(ln); #ifdef TIME @@ -124,8 +193,6 @@ int main(int argc, char* argv[]) { #endif } popCatch(); - } else { - bqn_execFile(fromUTF8l(argv[1])); } rtPerf_print(); CTR_FOR(CTR_PRINT) diff --git a/src/md1.c b/src/md1.c index 4f8f6677..222f8c37 100644 --- a/src/md1.c +++ b/src/md1.c @@ -215,14 +215,42 @@ B fchars_c1(B d, B x) { B f = c(Md1D,d)->f; return file_chars(path_resolve(f, x)); } B fbytes_c1(B d, B x) { B f = c(Md1D,d)->f; - TmpFile* tf = file_bytes(path_resolve(f, x)); usz ia = tf->ia; u8* p = (u8*)tf->a; + TmpFile* tf = file_bytes(path_resolve(f, x)); + usz ia = tf->ia; u8* p = (u8*)tf->a; u32* rp; B r = m_c32arrv(&rp, ia); for (i64 i = 0; i < ia; i++) rp[i] = p[i]; ptr_dec(tf); return r; } +B flines_c1(B d, B x) { B f = c(Md1D,d)->f; + TmpFile* tf = file_bytes(path_resolve(f, x)); + usz ia = tf->ia; u8* p = (u8*)tf->a; + usz lineCount = 0; + for (usz i = 0; i < ia; i++) { + if (p[i]=='\n') lineCount++; + else if (p[i]=='\r') { + lineCount++; + if(i+1f; - return bqn_execFile(path_resolve(f, x)); + return bqn_execFile(path_resolve(f, x), inc(bi_emptyHVec)); +} +B import_c2(B d, B w, B x) { B f = c(Md1D,d)->f; + return bqn_execFile(path_resolve(f, x), w); } #define ba(NAME) bi_##NAME = mm_alloc(sizeof(Md1), t_md1BI, ftag(MD1_TAG)); c(Md1,bi_##NAME)->c2 = NAME##_c2; c(Md1,bi_##NAME)->c1 = NAME##_c1 ; c(Md1,bi_##NAME)->extra=pm1_##NAME; gc_add(bi_##NAME); @@ -231,8 +259,8 @@ B import_c1(B d, B x) { B f = c(Md1D,d)->f; void print_md1BI(B x) { printf("%s", format_pm1(c(Md1,x)->extra)); } -B bi_tbl, bi_each, bi_fold, bi_scan, bi_const, bi_swap, bi_timed, bi_fchars, bi_fbytes, bi_import; -static inline void md1_init() { ba(tbl) ba(each) ba(fold) ba(scan) ba(const) ba(swap) ba(timed) bm(fchars) bm(fbytes) bm(import) +B bi_tbl, bi_each, bi_fold, bi_scan, bi_const, bi_swap, bi_timed, bi_fchars, bi_fbytes, bi_flines, bi_import; +static inline void md1_init() { ba(tbl) ba(each) ba(fold) ba(scan) ba(const) ba(swap) ba(timed) bm(fchars) bm(fbytes) bm(flines) ba(import) ti[t_md1BI].print = print_md1BI; } diff --git a/src/sfns.c b/src/sfns.c index 9fdbdde0..37b33ce3 100644 --- a/src/sfns.c +++ b/src/sfns.c @@ -430,8 +430,19 @@ B join_c1(B t, B x) { if (rnk(x)==1) { usz xia = a(x)->ia; if (xia==0) { - B xf = getFillE(x); dec(x); - if (isAtm(xf)) thrM("∾: Empty vector 𝕩 cannot have an atom fill element"); + B xf = getFillE(x); + if (isAtm(xf)) { + decR(xf); + if (!PROPER_FILLS) { + B xfq = getFillR(x); + bool no = noFill(xfq); + decR(xfq); + if (no) return x; + } + dec(x); + thrM("∾: Empty vector 𝕩 cannot have an atom fill element"); + } + dec(x); ur ir = rnk(xf); if (ir==0) thrM("∾: Empty vector 𝕩 cannot have a unit fill element"); B xff = getFillQ(xf); @@ -493,7 +504,7 @@ B join_c2(B t, B w, B x) { HArr_p r = m_harrUv(2); r.a[0] = TI(w).get(w,0); dec(w); r.a[1] = TI(x).get(x,0); dec(x); - return r.b; + return withFill(r.b, f); } if (c-wr > 1 || c-xr > 1) thrM("∾: Argument ranks must differ by 1 or less"); MAKE_MUT(r, wia+xia); diff --git a/src/stuff.c b/src/stuff.c index fed8a34a..f3819289 100644 --- a/src/stuff.c +++ b/src/stuff.c @@ -365,6 +365,7 @@ void printAllocStats() { } _Thread_local B comp_currPath; +_Thread_local B comp_currArgs; #define FOR_INIT(F) F(hdr) F(harr) F(fillarr) F(i32arr) F(c32arr) F(f64arr) F(fns) F(sfns) F(arith) F(grade) F(md1) F(md2) F(sysfn) F(derv) F(comp) F(rtPerf) F(ns) F(load) #define F(X) static inline void X##_init(); FOR_INIT(F) diff --git a/src/sysfn.c b/src/sysfn.c index 90af11c4..9fa180c2 100644 --- a/src/sysfn.c +++ b/src/sysfn.c @@ -32,6 +32,14 @@ B glyph_c1(B t, B x) { return x; } +B repr_c1(B t, B x) { + #define 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 fill_c1(B t, B x) { B r = getFillE(x); dec(x); @@ -137,7 +145,7 @@ B bqn_c1(B t, B x) { BS2B xgetU = TI(x).getU; for (usz i = 0; i < ia; i++) if (!isC32(xgetU(x,i))) thrM("•BQN: Argument must be a character vector"); } - return bqn_exec(x, bi_N); + return bqn_exec(x, bi_N, bi_N); } B cmp_c2(B t, B w, B x) { @@ -147,7 +155,7 @@ B cmp_c2(B t, B w, B x) { } -#define F(A,M,D) M(type) M(decp) M(primInd) M(glyph) A(fill) A(grLen) D(grOrd) A(asrt) M(out) M(show) M(sys) M(bqn) D(cmp) D(internal) +#define F(A,M,D) M(type) M(decp) M(primInd) M(glyph) M(repr) A(fill) A(grLen) D(grOrd) A(asrt) M(out) M(show) M(sys) M(bqn) D(cmp) D(internal) BI_FNS0(F); static inline void sysfn_init() { BI_FNS1(F) } #undef F @@ -156,7 +164,7 @@ static B makeRel(B md) { // doesn't consume return m1_d(inc(md), path_dir(inc(comp_currPath))); } -B bi_timed, bi_fchars, bi_fbytes, bi_import; +B bi_timed, bi_fchars, bi_fbytes, bi_flines, bi_import; B sys_c1(B t, B x) { assert(isArr(x)); usz i = 0; @@ -173,10 +181,15 @@ B sys_c1(B t, B x) { else if (eqStr(c, U"bqn")) r.a[i] = inc(bi_bqn); else if (eqStr(c, U"cmp")) r.a[i] = inc(bi_cmp); else if (eqStr(c, U"timed")) r.a[i] = inc(bi_timed); + else if (eqStr(c, U"repr")) r.a[i] = inc(bi_repr); else if (eqStr(c, U"fchars")) r.a[i] = makeRel(bi_fchars); else if (eqStr(c, U"fbytes")) r.a[i] = makeRel(bi_fbytes); + else if (eqStr(c, U"flines")) r.a[i] = makeRel(bi_flines); else if (eqStr(c, U"import")) r.a[i] = makeRel(bi_import); - else { dec(x); thrM("Unknown system function"); } + else if (eqStr(c, U"args")) { + if(isNothing(comp_currArgs)) thrM("No arguments present for •args"); + r.a[i] = inc(comp_currArgs); + } else { dec(x); thrM("Unknown system function"); } } return harr_fcd(r, x); } diff --git a/src/vm.c b/src/vm.c index 1840b5a6..616d9688 100644 --- a/src/vm.c +++ b/src/vm.c @@ -685,46 +685,6 @@ void popCatch() { #endif } -NOINLINE NORETURN void thr(B msg) { - if (cf>cfStart) { - catchMessage = msg; - cf--; - - B* gStackNew = gStackStart + cf->gsDepth; - assert(gStackNew<=gStack); - while (gStack!=gStackNew) dec(*--gStack); - envPrevHeight = envCurr-envStart; - Env* envNew = envStart + cf->envDepth; - assert(envNew<=envCurr); - while (envCurr!=envNew) { - envCurr--; - #if VM_POS - envCurr->bcV = *envCurr->bcP - i32arr_ptr(envCurr->sc->body->comp->bc) - 1; - #else - envCurr->bcV = envCurr->bcL - i32arr_ptr(envCurr->sc->body->comp->bc); - #endif - } - - if (cfStart+cf->cfDepth > cf) err("bad catch cfDepth"); - cf = cfStart+cf->cfDepth; - longjmp(cf->jmp, 1); - } - assert(cf==cfStart); - printf("Error: "); - print(msg); - puts(""); - #ifdef DEBUG - __builtin_trap(); - #else - exit(1); - #endif -} - -NOINLINE NORETURN void thrM(char* s) { - thr(fromUTF8(s, strlen(s))); -} -NOINLINE NORETURN void thrOOM() { thrM("Out of memory"); } - NOINLINE void vm_pst(Env* s, Env* e) { assert(s<=e); @@ -763,3 +723,48 @@ NOINLINE void vm_pst(Env* s, Env* e) { i--; } } + +static void unwindEnv(Env* envNew) { + assert(envNew<=envCurr); + while (envCurr!=envNew) { + envCurr--; + #if VM_POS + envCurr->bcV = *envCurr->bcP - i32arr_ptr(envCurr->sc->body->comp->bc) - 1; + #else + envCurr->bcV = envCurr->bcL - i32arr_ptr(envCurr->sc->body->comp->bc); + #endif + } +} + +NOINLINE NORETURN void thr(B msg) { + if (cf>cfStart) { + catchMessage = msg; + cf--; + + B* gStackNew = gStackStart + cf->gsDepth; + assert(gStackNew<=gStack); + while (gStack!=gStackNew) dec(*--gStack); + envPrevHeight = envCurr-envStart; + unwindEnv(envStart + cf->envDepth); + + + if (cfStart+cf->cfDepth > cf) err("bad catch cfDepth"); + cf = cfStart+cf->cfDepth; + longjmp(cf->jmp, 1); + } + assert(cf==cfStart); + printf("Error: "); print(msg); putchar('\n'); + Env* envPrev = envCurr; + unwindEnv(envStart); + vm_pst(envCurr, envPrev); + #ifdef DEBUG + __builtin_trap(); + #else + exit(1); + #endif +} + +NOINLINE NORETURN void thrM(char* s) { + thr(fromUTF8(s, strlen(s))); +} +NOINLINE NORETURN void thrOOM() { thrM("Out of memory"); }