split up CATCH_ERRORS into functional and semantic options
allows running a non-heapverify build that functions exactly as a heapverify one, while allowing ⎊ to function
This commit is contained in:
parent
fd317ddce3
commit
54cec2fdf5
@ -323,14 +323,14 @@ po ← { # parsed options
|
|||||||
args∾↩ (singeli ∧ arch≡"aarch64") / ⟨"-DSINGELI_NEON"⟩
|
args∾↩ (singeli ∧ arch≡"aarch64") / ⟨"-DSINGELI_NEON"⟩
|
||||||
args∾↩ (singeli ∧ ⊑arch<⊸∊"x86-64"‿"aarch64") / ⟨"-DSINGELI_SIMD"⟩
|
args∾↩ (singeli ∧ ⊑arch<⊸∊"x86-64"‿"aarch64") / ⟨"-DSINGELI_SIMD"⟩
|
||||||
args∾↩ ( wasm) / ⟨"-DWASM"⟩
|
args∾↩ ( wasm) / ⟨"-DWASM"⟩
|
||||||
args∾↩ ( wasi) / ⟨"-DWASI", "-DNO_MMAP", "-DCATCH_ERRORS=0", "-D_WASI_EMULATED_MMAN", "--target=wasm32-wasi"⟩
|
args∾↩ ( wasi) / ⟨"-DWASI", "-DNO_MMAP", "-DUSE_SETJMP=0", "-D_WASI_EMULATED_MMAN", "--target=wasm32-wasi"⟩
|
||||||
args∾↩ ( emcc) / ⟨"-DEMCC", "-O3"⟩
|
args∾↩ ( emcc) / ⟨"-DEMCC", "-O3"⟩
|
||||||
args∾↩ ( replxx) / ⟨"-DUSE_REPLXX", "-DREPLXX_STATIC=1", "-I"∾replxxDir∾"/include"⟩ # TODO maybe move to main.c only, and have it be in its own separate cache dir, so that adding replxx doesn't recompile everything?
|
args∾↩ ( replxx) / ⟨"-DUSE_REPLXX", "-DREPLXX_STATIC=1", "-I"∾replxxDir∾"/include"⟩ # TODO maybe move to main.c only, and have it be in its own separate cache dir, so that adding replxx doesn't recompile everything?
|
||||||
args∾↩ ( debug DOpt "g") / ⟨"-g"⟩
|
args∾↩ ( debug DOpt "g") / ⟨"-g"⟩
|
||||||
args∾↩ ( o3) / ⟨"-O3"⟩
|
args∾↩ ( o3) / ⟨"-O3"⟩
|
||||||
args∾↩ ( debug) / ⟨"-DDEBUG"⟩
|
args∾↩ ( debug) / ⟨"-DDEBUG"⟩
|
||||||
args∾↩ ( rtverify) / ⟨"-DRT_VERIFY"⟩
|
args∾↩ ( rtverify) / ⟨"-DRT_VERIFY"⟩
|
||||||
args∾↩ ( heapverify) / ⟨"-DHEAP_VERIFY", "-DCATCH_ERRORS=0"⟩
|
args∾↩ ( heapverify) / ⟨"-DHEAP_VERIFY", "-DUSE_SETJMP=0"⟩
|
||||||
args∾↩ ( exportSymbols) / ⟨"-DCBQN_EXPORT"⟩
|
args∾↩ ( exportSymbols) / ⟨"-DCBQN_EXPORT"⟩
|
||||||
args∾↩ ( ¬pie) / ⟨"-fno-pie"⟩
|
args∾↩ ( ¬pie) / ⟨"-fno-pie"⟩
|
||||||
args∾↩ (pie ∧ ¬sharedLib) / ⟨"-fPIE"⟩
|
args∾↩ (pie ∧ ¬sharedLib) / ⟨"-fPIE"⟩
|
||||||
|
|||||||
@ -401,7 +401,7 @@ Most toggles require a value of `1` to be enabled.
|
|||||||
|
|
||||||
```c
|
```c
|
||||||
// (effective) usual default value is listed; (u) marks being not defined
|
// (effective) usual default value is listed; (u) marks being not defined
|
||||||
// default may change under some conditions (DEBUG, CATCH_ERRORS, heapverify, among maybe other things)
|
// defaults may change under some conditions (DEBUG, USE_SETJMP, heapverify, among maybe other things)
|
||||||
// some things fully configured by the build system may not be listed
|
// some things fully configured by the build system may not be listed
|
||||||
|
|
||||||
// general config:
|
// general config:
|
||||||
@ -420,7 +420,6 @@ Most toggles require a value of `1` to be enabled.
|
|||||||
#define ALL_R0 0 // use all of r0.bqn for runtime_0
|
#define ALL_R0 0 // use all of r0.bqn for runtime_0
|
||||||
#define ALL_R1 0 // use all of r1.bqn for runtime
|
#define ALL_R1 0 // use all of r1.bqn for runtime
|
||||||
#define NO_RT 0 // whether to completely disable self-hosted runtime loading
|
#define NO_RT 0 // whether to completely disable self-hosted runtime loading
|
||||||
#define CATCH_ERRORS 1 // allow catching errors; means refcounts might stay too high if forgotten over a throw-catch; disabled for heapverify
|
|
||||||
#define FAKE_RUNTIME 0 // disable the self-hosted runtime
|
#define FAKE_RUNTIME 0 // disable the self-hosted runtime
|
||||||
#define FORMATTER 1 // use self-hosted formatter for output
|
#define FORMATTER 1 // use self-hosted formatter for output
|
||||||
#define NO_EXPLAIN 0 // disable )explain
|
#define NO_EXPLAIN 0 // disable )explain
|
||||||
@ -429,6 +428,9 @@ Most toggles require a value of `1` to be enabled.
|
|||||||
#define SFNS_FILLS 1 // compute fills for structural functions (∾, ≍, etc)
|
#define SFNS_FILLS 1 // compute fills for structural functions (∾, ≍, etc)
|
||||||
#define CHECK_VALID 1 // check for valid arguments in places where that would be detrimental to performance
|
#define CHECK_VALID 1 // check for valid arguments in places where that would be detrimental to performance
|
||||||
// e.g. left argument sortedness of ⍋/⍒, incompatible changes in ⌾, etc
|
// e.g. left argument sortedness of ⍋/⍒, incompatible changes in ⌾, etc
|
||||||
|
#define USE_SETJMP 1 // whether setjmp is available & should be used for error catching (makes refcounts leakable)
|
||||||
|
#define SEMANTIC_CATCH USE_SETJMP // whether catching should be assumed to be usable for operations which need to semantically change depending on that
|
||||||
|
#define SEMANTIC_CATCH_BI SEMANTIC_CATCH // whether ⎊ will catch stuff
|
||||||
|
|
||||||
#define RYU_OPTIMIZE_SIZE 0 // reduce size of Ryu tables at the cost of some performance for number •Repr
|
#define RYU_OPTIMIZE_SIZE 0 // reduce size of Ryu tables at the cost of some performance for number •Repr
|
||||||
#define FFI_CHECKS 1 // check for valid arguments passed to FFI-d functions
|
#define FFI_CHECKS 1 // check for valid arguments passed to FFI-d functions
|
||||||
|
|||||||
@ -83,12 +83,12 @@ B scan_arith(B f, B w, B x, usz* xsh) { // Used by scan.c
|
|||||||
|
|
||||||
|
|
||||||
#if TEST_CELL_FILLS
|
#if TEST_CELL_FILLS
|
||||||
i32 fullCellFills = 2*CATCH_ERRORS;
|
i32 fullCellFills = 2*SEMANTIC_CATCH;
|
||||||
i32 cellFillErrored = 0;
|
i32 cellFillErrored = 0;
|
||||||
#define DO_CELL_CATCH (fullCellFills==2)
|
#define DO_CELL_CATCH (fullCellFills==2)
|
||||||
#define SET_FILL_ERRORED cellFillErrored = 1
|
#define SET_FILL_ERRORED cellFillErrored = 1
|
||||||
#else
|
#else
|
||||||
#define DO_CELL_CATCH CATCH_ERRORS
|
#define DO_CELL_CATCH SEMANTIC_CATCH
|
||||||
#define SET_FILL_ERRORED
|
#define SET_FILL_ERRORED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -8,9 +8,7 @@
|
|||||||
B val_c1(Md2D* d, B x) { return c1(d->f, x); }
|
B val_c1(Md2D* d, B x) { return c1(d->f, x); }
|
||||||
B val_c2(Md2D* d, B w, B x) { return c2(d->g, w,x); }
|
B val_c2(Md2D* d, B w, B x) { return c2(d->g, w,x); }
|
||||||
|
|
||||||
#if CATCH_ERRORS && !BI_CATCH_DISABLED
|
#if SEMANTIC_CATCH
|
||||||
extern GLOBAL B lastErrMsg; // sysfn.c
|
|
||||||
|
|
||||||
B fillBy_c1(Md2D* d, B x) {
|
B fillBy_c1(Md2D* d, B x) {
|
||||||
B xf=getFillQ(x);
|
B xf=getFillQ(x);
|
||||||
B r = c1(d->f, x);
|
B r = c1(d->f, x);
|
||||||
@ -30,7 +28,13 @@ B fillBy_c2(Md2D* d, B w, B x) {
|
|||||||
popCatch();
|
popCatch();
|
||||||
return withFill(r, fill);
|
return withFill(r, fill);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
B fillBy_c1(Md2D* d, B x) { return c1(d->f, x); }
|
||||||
|
B fillBy_c2(Md2D* d, B w, B x) { return c2(d->f, w,x); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SEMANTIC_CATCH_BI)? SEMANTIC_CATCH_BI : SEMANTIC_CATCH
|
||||||
|
extern GLOBAL B lastErrMsg; // sysfn.c
|
||||||
typedef struct ReObj {
|
typedef struct ReObj {
|
||||||
struct CustomObj;
|
struct CustomObj;
|
||||||
B msg;
|
B msg;
|
||||||
@ -48,8 +52,6 @@ void pushRe(void) {
|
|||||||
B catch_c1(Md2D* d, B x) { if(CATCH) { pushRe(); B r = c1(d->g, x); dec(gsPop()); return r; } B r = c1(d->f, inc(x)); popCatch(); dec(x); return r; }
|
B catch_c1(Md2D* d, B x) { if(CATCH) { pushRe(); B r = c1(d->g, x); dec(gsPop()); return r; } B r = c1(d->f, inc(x)); popCatch(); dec(x); return r; }
|
||||||
B catch_c2(Md2D* d, B w, B x) { if(CATCH) { pushRe(); B r = c2(d->g, w,x); dec(gsPop()); return r; } B r = c2(d->f, inc(w),inc(x)); popCatch(); dec(w); dec(x); return r; }
|
B catch_c2(Md2D* d, B w, B x) { if(CATCH) { pushRe(); B r = c2(d->g, w,x); dec(gsPop()); return r; } B r = c2(d->f, inc(w),inc(x)); popCatch(); dec(w); dec(x); return r; }
|
||||||
#else
|
#else
|
||||||
B fillBy_c1(Md2D* d, B x) { return c1(d->f, x); }
|
|
||||||
B fillBy_c2(Md2D* d, B w, B x) { return c2(d->f, w,x); }
|
|
||||||
B catch_c1(Md2D* d, B x) { return c1(d->f, x); }
|
B catch_c1(Md2D* d, B x) { return c1(d->f, x); }
|
||||||
B catch_c2(Md2D* d, B w, B x) { return c2(d->f, w,x); }
|
B catch_c2(Md2D* d, B w, B x) { return c2(d->f, w,x); }
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -701,7 +701,7 @@ B repl_c1(B t, B x) {
|
|||||||
return repl_c2(t, emptyHVec(), x);
|
return repl_c2(t, emptyHVec(), x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
GLOBAL B lastErrMsg;
|
GLOBAL B lastErrMsg;
|
||||||
B currentError_c1(B t, B x) {
|
B currentError_c1(B t, B x) {
|
||||||
if (isNsp(x)) thrM("•CurrentError: Namespace 𝕩 is reserved");
|
if (isNsp(x)) thrM("•CurrentError: Namespace 𝕩 is reserved");
|
||||||
@ -1992,7 +1992,7 @@ void sysfn_init(void) {
|
|||||||
#undef F
|
#undef F
|
||||||
NOGC_E;
|
NOGC_E;
|
||||||
|
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
lastErrMsg = bi_N;
|
lastErrMsg = bi_N;
|
||||||
gc_add_ref(&lastErrMsg);
|
gc_add_ref(&lastErrMsg);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -59,9 +59,9 @@ static B getFillR(B x) { // doesn't consume; can return bi_noFill
|
|||||||
if (isC32(x)) return m_c32(' ');
|
if (isC32(x)) return m_c32(' ');
|
||||||
return bi_noFill;
|
return bi_noFill;
|
||||||
}
|
}
|
||||||
static B getFillQ(B x) { // doesn't consume; returns 0 if !CATCH_ERRORS
|
static B getFillQ(B x) { // doesn't consume; returns 0 if !SEMANTIC_CATCH
|
||||||
B r = getFillR(x);
|
B r = getFillR(x);
|
||||||
#if CATCH_ERRORS
|
#if SEMANTIC_CATCH
|
||||||
return r;
|
return r;
|
||||||
#endif
|
#endif
|
||||||
return noFill(r)? m_f64(0) : r;
|
return noFill(r)? m_f64(0) : r;
|
||||||
|
|||||||
15
src/h.h
15
src/h.h
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef CATCH_ERRORS
|
#ifndef USE_SETJMP
|
||||||
#define CATCH_ERRORS 1
|
#define USE_SETJMP 1
|
||||||
#endif
|
#endif
|
||||||
#ifndef ENABLE_GC
|
#ifndef ENABLE_GC
|
||||||
#define ENABLE_GC 1
|
#define ENABLE_GC 1
|
||||||
@ -43,14 +43,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RT_LEN 64
|
#define RT_LEN 64
|
||||||
|
|
||||||
#if CATCH_ERRORS
|
#ifndef SEMANTIC_CATCH
|
||||||
#define PROPER_FILLS (EACH_FILLS&SFNS_FILLS)
|
#define SEMANTIC_CATCH USE_SETJMP
|
||||||
|
#endif
|
||||||
|
#if SEMANTIC_CATCH
|
||||||
|
#define PROPER_FILLS (EACH_FILLS & SFNS_FILLS)
|
||||||
#else
|
#else
|
||||||
#undef EACH_FILLS
|
#undef EACH_FILLS
|
||||||
#define EACH_FILLS 0
|
#define EACH_FILLS 0
|
||||||
@ -393,7 +396,7 @@ NOINLINE NORETURN void rethrow(void);
|
|||||||
NOINLINE NORETURN void thrM(char* s);
|
NOINLINE NORETURN void thrM(char* s);
|
||||||
NOINLINE NORETURN void thrF(char* s, ...);
|
NOINLINE NORETURN void thrF(char* s, ...);
|
||||||
NOINLINE NORETURN void thrOOM(void);
|
NOINLINE NORETURN void thrOOM(void);
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
jmp_buf* prepareCatch(void);
|
jmp_buf* prepareCatch(void);
|
||||||
#define CATCH setjmp(*prepareCatch()) // use as `if (CATCH) { /*handle error*/ freeThrown(); return; } /*potentially erroring thing*/ popCatch(); /*no errors yay*/`
|
#define CATCH setjmp(*prepareCatch()) // use as `if (CATCH) { /*handle error*/ freeThrown(); return; } /*potentially erroring thing*/ popCatch(); /*no errors yay*/`
|
||||||
void popCatch(void); // note: popCatch() must always be called if no error is thrown, so no returns before it!
|
void popCatch(void); // note: popCatch() must always be called if no error is thrown, so no returns before it!
|
||||||
|
|||||||
@ -659,7 +659,7 @@ B bqn_explain(B str) {
|
|||||||
|
|
||||||
|
|
||||||
static void freed_visit(Value* x) {
|
static void freed_visit(Value* x) {
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
fatal("visiting t_freed\n");
|
fatal("visiting t_freed\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,7 +54,7 @@ void gc_visitRoots() {
|
|||||||
|
|
||||||
static void gc_tryFree(Value* v) {
|
static void gc_tryFree(Value* v) {
|
||||||
u8 t = v->type;
|
u8 t = v->type;
|
||||||
#if DEBUG && !CATCH_ERRORS
|
#if DEBUG && !USE_SETJMP
|
||||||
if (t==t_freed) fatal("GC found t_freed\n");
|
if (t==t_freed) fatal("GC found t_freed\n");
|
||||||
#endif
|
#endif
|
||||||
if (t!=t_empty && !(v->mmInfo&0x80)) {
|
if (t!=t_empty && !(v->mmInfo&0x80)) {
|
||||||
@ -62,7 +62,7 @@ static void gc_tryFree(Value* v) {
|
|||||||
#if DONT_FREE
|
#if DONT_FREE
|
||||||
v->flags = t;
|
v->flags = t;
|
||||||
#else
|
#else
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
if (t==t_freed) { mm_free(v); return; }
|
if (t==t_freed) { mm_free(v); return; }
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -121,7 +121,7 @@ B eachm_fn(B fo, B x, FC1 f) {
|
|||||||
return any_squeeze(HARR_FCD(r, x));
|
return any_squeeze(HARR_FCD(r, x));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CATCH_ERRORS
|
#if SEMANTIC_CATCH
|
||||||
B arith_recd(FC2 f, B w, B x) {
|
B arith_recd(FC2 f, B w, B x) {
|
||||||
B fx = getFillR(x);
|
B fx = getFillR(x);
|
||||||
if (noFill(fx)) return eachd_fn(bi_N, w, x, f);
|
if (noFill(fx)) return eachd_fn(bi_N, w, x, f);
|
||||||
|
|||||||
@ -4,7 +4,7 @@ B eachd_fn(B fo, B w, B x, FC2 f); // consumes w,x; assumes at least one is arra
|
|||||||
B eachm_fn(B fo, B x, FC1 f); // consumes x; x must be array
|
B eachm_fn(B fo, B x, FC1 f); // consumes x; x must be array
|
||||||
|
|
||||||
|
|
||||||
#if CATCH_ERRORS
|
#if SEMANTIC_CATCH
|
||||||
NOINLINE B arith_recd(FC2 f, B w, B x);
|
NOINLINE B arith_recd(FC2 f, B w, B x);
|
||||||
#else
|
#else
|
||||||
static inline B arith_recd(FC2 f, B w, B x) { return eachd_fn(bi_N, w, x, f); }
|
static inline B arith_recd(FC2 f, B w, B x) { return eachd_fn(bi_N, w, x, f); }
|
||||||
|
|||||||
@ -128,7 +128,7 @@ void fprintsB(FILE* f, B x) {
|
|||||||
for (usz i = 0; i < ia; i++) {
|
for (usz i = 0; i < ia; i++) {
|
||||||
B c = GetU(x, i);
|
B c = GetU(x, i);
|
||||||
if (isC32(c)) fprintCodepoint(f, o2cG(c));
|
if (isC32(c)) fprintCodepoint(f, o2cG(c));
|
||||||
#if !CATCH_ERRORS
|
#if !SEMANTIC_CATCH
|
||||||
else if (c.u==0 || noFill(c)) fprintf(f, " ");
|
else if (c.u==0 || noFill(c)) fprintf(f, " ");
|
||||||
#endif
|
#endif
|
||||||
else thrM("Trying to output non-character");
|
else thrM("Trying to output non-character");
|
||||||
|
|||||||
8
src/vm.c
8
src/vm.c
@ -1299,7 +1299,7 @@ void comp_init(void) {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct CatchFrame {
|
typedef struct CatchFrame {
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
jmp_buf jmp;
|
jmp_buf jmp;
|
||||||
#endif
|
#endif
|
||||||
u64 gsDepth;
|
u64 gsDepth;
|
||||||
@ -1310,7 +1310,7 @@ GLOBAL CatchFrame* cf; // points to after end
|
|||||||
GLOBAL CatchFrame* cfStart;
|
GLOBAL CatchFrame* cfStart;
|
||||||
GLOBAL CatchFrame* cfEnd;
|
GLOBAL CatchFrame* cfEnd;
|
||||||
|
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
jmp_buf* prepareCatch() {
|
jmp_buf* prepareCatch() {
|
||||||
if (cf==cfEnd) {
|
if (cf==cfEnd) {
|
||||||
u64 n = cfEnd-cfStart;
|
u64 n = cfEnd-cfStart;
|
||||||
@ -1689,7 +1689,7 @@ NOINLINE NORETURN void throwImpl(bool rethrow) {
|
|||||||
// while (c>gStackStart) { printI(*--c); putchar('\n'); } printf("gStack printed\n");
|
// while (c>gStackStart) { printI(*--c); putchar('\n'); } printf("gStack printed\n");
|
||||||
NOGC_CHECK("throwing during noAlloc");
|
NOGC_CHECK("throwing during noAlloc");
|
||||||
if (!rethrow) envPrevHeight = envCurr-envStart + 1;
|
if (!rethrow) envPrevHeight = envCurr-envStart + 1;
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
if (cf>cfStart) { // something wants to catch errors
|
if (cf>cfStart) { // something wants to catch errors
|
||||||
cf--;
|
cf--;
|
||||||
|
|
||||||
@ -1715,7 +1715,7 @@ NOINLINE NORETURN void throwImpl(bool rethrow) {
|
|||||||
#else
|
#else
|
||||||
exit(1);
|
exit(1);
|
||||||
#endif
|
#endif
|
||||||
#if CATCH_ERRORS
|
#if USE_SETJMP
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ if [ "$#" -ne 1 ]; then
|
|||||||
echo "Usage: $0 path/to/mlochbaum/BQN"
|
echo "Usage: $0 path/to/mlochbaum/BQN"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
make f='-DDEBUG -DHEAP_VERIFY -DJIT_START=0' single-c
|
make f='-DDEBUG -DHEAP_VERIFY -DUSE_SETJMP=0 -DJIT_START=0' single-c
|
||||||
echo 'alljit+heapverify:' && ./BQN -M 1000 "$1/test/this.bqn" -noerr bytecode header identity literal namespace prim simple syntax token under undo unhead || exit
|
echo 'alljit+heapverify:' && ./BQN -M 1000 "$1/test/this.bqn" -noerr bytecode header identity literal namespace prim simple syntax token under undo unhead || exit
|
||||||
echo 'native vfy:';make heapverifyn && ./BQN -M 1000 "$1/test/this.bqn" -noerr bytecode header identity literal namespace prim simple syntax token under undo unhead || exit
|
echo 'native vfy:';make heapverifyn && ./BQN -M 1000 "$1/test/this.bqn" -noerr bytecode header identity literal namespace prim simple syntax token under undo unhead || exit
|
||||||
echo 'native:';make o3n && ./BQN -M 1000 "$1/test/this.bqn" || exit
|
echo 'native:';make o3n && ./BQN -M 1000 "$1/test/this.bqn" || exit
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user