diff --git a/src/README.md b/src/README.md index 100054e9..f24860b2 100644 --- a/src/README.md +++ b/src/README.md @@ -5,7 +5,8 @@ Functions starting with `m_` allocate a new object. Functions starting with `q_` are queries/predicates, and return a boolean. Functions ending with `R` are either supposed to be called rarely, or the caller expects that a part of it happens rarely. -Functions ending with `N` are not inlined. +Functions ending with `N` are non-inlined versions of another one. +Functions ending with `F` are rarely invoked fallback parts of a function. Functions ending with `P` take a pointer argument. Functions ending with `U` return (or take) a non-owned object (`U` = "unincremented"). Functions ending with `_c1` are monadic implementations, `_c2` are dyadic (see [builtin implementations](#builtin-implementations)) @@ -35,6 +36,7 @@ src/ gen/ generated files jit/ simple JIT compiler for x86-64 core/ things included everywhere + h.h core CBQN definitions builtins.h definitions of all built-in functions (excluding things defined by means of nfns.c) core.h file imported everywhere that defines the base BQN model nfns.c native functions for things that need to keep some state (e.g. •FLines needs to also hold the path its relative to) @@ -45,6 +47,17 @@ src/ ) ``` +### Random example functions + +* `c1`, `c2` in `h.h` - correspondingly monadically or dyadically invoke a function +* `evalBC` in `vm.c` - VM bytecode interpreter +* `slash_c2` in `builtins/sfns.c` - implementation of `𝕨/𝕩` +* `GC2i` & `GC2f` invocations in `builtins/arithd.c` - dyadic pervasive builtins +* See `load.c` `fruntime` items for more builtins (remove leading `bi_` & append `_c1`/`_c2` to get the implementation function) +* `load_init` in `load.c` - loads the BQN runtime & compiler +* `bqn_comp` in `load.c` - execute BQN code from a string +* `BN(allocL)` in `opt/mm_buddyTemplate.h` - fast path of buddy memory allocator; invoked from `opt/mm_buddy.h` + ## Base `B` represents any BQN object. It's a 64-bit NaN-boxed value; some of the NaN-boxed values, determined by the top 16 bits, are heap-allocated (i.e. low 48 bits are a `Value*`), some aren't: diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 452c99e0..6366ff6e 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -1135,7 +1135,7 @@ B transp_c1(B t, B x) { usz ia = a(x)->ia; usz* xsh = a(x)->sh; usz h = xsh[0]; - usz w = xsh[1] * shProd(a(x)->sh, 2, xr); + usz w = xsh[1] * shProd(xsh, 2, xr); Arr* r; usz xi = 0; diff --git a/src/core/fillarr.c b/src/core/fillarr.c index 5753d96b..d65b56c3 100644 --- a/src/core/fillarr.c +++ b/src/core/fillarr.c @@ -83,7 +83,7 @@ void validateFill(B x) { } } -NOINLINE bool fillEqualR(B w, B x) { // doesn't consume; both args must be arrays +NOINLINE bool fillEqualF(B w, B x) { // doesn't consume; both args must be arrays if (!eqShape(w, x)) return false; usz ia = a(w)->ia; if (ia==0) return true; diff --git a/src/core/fillarr.h b/src/core/fillarr.h index 2827b752..29394da6 100644 --- a/src/core/fillarr.h +++ b/src/core/fillarr.h @@ -18,11 +18,11 @@ static B qWithFill(B x, B fill) { // consumes both return withFill(x, fill); } -NOINLINE bool fillEqualR(B w, B x); +NOINLINE bool fillEqualF(B w, B x); static bool fillEqual(B w, B x) { if (w.u==x.u) return true; if (isAtm(w)|isAtm(x)) return false; - return fillEqualR(w, x); + return fillEqualF(w, x); } diff --git a/src/core/stuff.c b/src/core/stuff.c index 033187a3..76e8cc31 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -27,16 +27,16 @@ NORETURN NOINLINE void err(char* s) { exit(1); } -NOINLINE B c1N(B f, B x) { dec(x); +NOINLINE B c1F(B f, B x) { dec(x); if (isMd(f)) thrM("Calling a modifier"); return inc(VALIDATE(f)); } -NOINLINE B c2N(B f, B w, B x) { dec(w); dec(x); +NOINLINE B c2F(B f, B w, B x) { dec(w); dec(x); if (isMd(f)) thrM("Calling a modifier"); return inc(VALIDATE(f)); } -NOINLINE void value_freeN(Value* x) { value_free(x); } -NOINLINE void decA_N(B x) { dec(x); } +NOINLINE void value_freeF(Value* x) { value_free(x); } +NOINLINE void decA_F(B x) { dec(x); } void noop_visit(Value* x) { } NOINLINE B c1_bad(B f, B x) { thrM("This function can't be called monadically"); } NOINLINE B c2_bad(B f, B w, B x) { thrM("This function can't be called dyadically"); } @@ -357,7 +357,7 @@ NOINLINE void thrF(char* p, ...) { #define CMP(W,X) ({ AUTO wt = (W); AUTO xt = (X); (wt>xt?1:0)-(wttype!=v(x)->type) return false; B2B dcf = TI(w,decompose); if (dcf == def_decompose) return false; diff --git a/src/core/stuff.h b/src/core/stuff.h index adbbb96f..f019f224 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -192,20 +192,20 @@ B def_decompose(B x); void noop_visit(Value* x); #define CMP(W,X) ({ AUTO wt = (W); AUTO xt = (X); (wt>xt?1:0)-(wtx, 0 if w≡x; 0==compare(NaN,NaN) if (isNum(w) & isNum(x)) return CMP(o2fu(w), o2fu(x)); if (isC32(w) & isC32(x)) return CMP(o2cu(w), o2cu(x)); - return compareR(w, x); + return compareF(w, x); } #undef CMP -NOINLINE bool atomEqualR(B w, B x); +NOINLINE bool atomEqualF(B w, B x); static bool atomEqual(B w, B x) { // doesn't consume (not that that matters really currently) if(isF64(w)&isF64(x)) return w.f==x.f; if (w.u==x.u) return true; if (!isVal(w) | !isVal(x)) return false; - return atomEqualR(w, x); + return atomEqualF(w, x); } diff --git a/src/h.h b/src/h.h index a2c3d9e0..61d9b416 100644 --- a/src/h.h +++ b/src/h.h @@ -542,22 +542,22 @@ static bool reusable(B x) { return v(x)->refc==1; } #define REUSE(X) ({ B x_ = (X); v(x_)->flags = 0; x_; }) #define DEF_FREE(TY) static inline void TY##_freeO(Value* x); static void TY##_freeF(Value* x) { TY##_freeO(x); mm_free(x); } static inline void TY##_freeO(Value* x) FORCE_INLINE void value_free(Value* x) { TIv(x,freeF)(x); } -void value_freeN(Value* x); +void value_freeF(Value* x); static void dec(B x) { if (!isVal(VALIDATE(x))) return; Value* vx = v(x); if(!--vx->refc) value_free(vx); } static inline void ptr_dec(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_free(x); } -static inline void ptr_decR(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_freeN(x); } +static inline void ptr_decR(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_freeF(x); } #define tptr_dec(X, F) ({ Value* x_ = (Value*)(X); if (!--VALIDATEP(x_)->refc) F(x_); }) static void decR(B x) { if (!isVal(VALIDATE(x))) return; Value* vx = v(x); - if(!--vx->refc) value_freeN(vx); + if(!--vx->refc) value_freeF(vx); } -void decA_N(B x); -static void decA(B x) { if (RARE(isVal(x))) decA_N(x); } // decrement what's likely an atom +void decA_F(B x); +static void decA(B x) { if (RARE(isVal(x))) decA_F(x); } // decrement what's likely an atom static inline B inc(B x) { if (isVal(VALIDATE(x))) v(x)->refc++; return x; @@ -588,15 +588,15 @@ typedef struct Fun { } Fun; -B c1N(B f, B x); -B c2N(B f, B w, B x); +B c1F(B f, B x); +B c2F(B f, B w, B x); static B c1(B f, B x) { // BQN-call f monadically; consumes x if (isFun(f)) return VALIDATE(c(Fun,f)->c1(f, x)); - return c1N(f, x); + return c1F(f, x); } static B c2(B f, B w, B x) { // BQN-call f dyadically; consumes w,x if (isFun(f)) return VALIDATE(c(Fun,f)->c2(f, w, x)); - return c2N(f, w, x); + return c2F(f, w, x); } static void errMd(B x) { if(RARE(isMd(x))) thrM("Calling a modifier"); } // like c1/c2, but with less overhead on non-functions diff --git a/src/utils/mut.c b/src/utils/mut.c index a108f709..42377b5b 100644 --- a/src/utils/mut.c +++ b/src/utils/mut.c @@ -34,7 +34,7 @@ NOINLINE void mut_to(Mut* m, u8 n) { } } -NOINLINE B vec_add_new(B w, B x) { +NOINLINE B vec_addF(B w, B x) { usz wia = a(w)->ia; MAKE_MUT(r, wia+1); mut_init(r, el_or(TI(w,elType), selfElType(x))); MUTG_INIT(r); diff --git a/src/utils/mut.h b/src/utils/mut.h index 0dcf5ada..47841eec 100644 --- a/src/utils/mut.h +++ b/src/utils/mut.h @@ -231,9 +231,9 @@ static inline bool inplace_add(B w, B x) { // consumes x if returns true; fails } return false; } -B vec_add_new(B w, B x); +B vec_addF(B w, B x); +B vec_addN(B w, B x); // vec_add but not inlined static B vec_add(B w, B x) { // consumes both; fills may be wrong if (inplace_add(w, x)) return w; - return vec_add_new(w, x); + return vec_addF(w, x); } -B vec_addN(B w, B x); // vec_add but not inlined diff --git a/src/vm.c b/src/vm.c index ecaaebe9..251adcce 100644 --- a/src/vm.c +++ b/src/vm.c @@ -474,7 +474,7 @@ NOINLINE Block* compile(B bcq, B objs, B allBlocks, B allBodies, B indices, B to -NOINLINE void v_setR(Scope* pscs[], B s, B x, bool upd) { +NOINLINE void v_setF(Scope* pscs[], B s, B x, bool upd) { if (isArr(s)) { VTY(s, t_harr); B* sp = harr_ptr(s); usz ia = a(s)->ia; @@ -510,7 +510,7 @@ NOINLINE void v_setR(Scope* pscs[], B s, B x, bool upd) { sc->ext->vars[(u32)s.u] = inc(x); } } -NOINLINE bool v_sethR(Scope* pscs[], B s, B x) { +NOINLINE bool v_sethF(Scope* pscs[], B s, B x) { if (v(s)->type==t_vfyObj) return equal(c(VfyObj,s)->obj,x); VTY(s, t_harr); B* sp = harr_ptr(s); @@ -539,7 +539,7 @@ NOINLINE bool v_sethR(Scope* pscs[], B s, B x) { -NOINLINE B v_getR(Scope* pscs[], B s) { +NOINLINE B v_getF(Scope* pscs[], B s) { if (isExt(s)) { Scope* sc = pscs[(u16)(s.u>>32)]; B r = sc->ext->vars[(u32)s.u]; diff --git a/src/vm.h b/src/vm.h index 363473a8..b09a4de3 100644 --- a/src/vm.h +++ b/src/vm.h @@ -286,7 +286,7 @@ typedef struct VfyObj { } VfyObj; -NOINLINE B v_getR(Scope* pscs[], B s); // doesn't consume +NOINLINE B v_getF(Scope* pscs[], B s); // doesn't consume FORCE_INLINE B v_getI(Scope* sc, u32 p, bool chk) { B r = sc->vars[p]; if (chk && r.u==bi_noVar.u) thrM("↩: Reading variable that hasn't been set"); @@ -294,12 +294,12 @@ FORCE_INLINE B v_getI(Scope* sc, u32 p, bool chk) { return r; } FORCE_INLINE B v_get(Scope* pscs[], B s, bool chk) { // get value representing s, replacing with bi_optOut; doesn't consume; if chk is false, content variables _may_ not be checked to be set - if (RARE(!isVar(s))) return v_getR(pscs, s); + if (RARE(!isVar(s))) return v_getF(pscs, s); return v_getI(pscs[(u16)(s.u>>32)], (u32)s.u, chk); } -NOINLINE void v_setR(Scope* pscs[], B s, B x, bool upd); // doesn't consume -NOINLINE bool v_sethR(Scope* pscs[], B s, B x); // doesn't consume +NOINLINE void v_setF(Scope* pscs[], B s, B x, bool upd); // doesn't consume +NOINLINE bool v_sethF(Scope* pscs[], B s, B x); // doesn't consume FORCE_INLINE void v_setI(Scope* sc, u32 p, B x, bool upd, bool chk) { // consumes x if (upd) { B prev = sc->vars[p]; @@ -311,7 +311,7 @@ FORCE_INLINE void v_setI(Scope* sc, u32 p, B x, bool upd, bool chk) { // consume } } FORCE_INLINE void v_set(Scope* pscs[], B s, B x, bool upd, bool chk) { // doesn't consume; if chk is false, content variables _may_ not be checked to be set - if (RARE(!isVar(s))) v_setR(pscs, s, x, upd); + if (RARE(!isVar(s))) v_setF(pscs, s, x, upd); else v_setI(pscs[(u16)(s.u>>32)], (u32)s.u, inc(x), upd, chk); } @@ -321,5 +321,5 @@ FORCE_INLINE bool v_seth(Scope* pscs[], B s, B x) { // doesn't consume; s cannot return true; } if (s.u == bi_N.u) return true; - return v_sethR(pscs, s, x); + return v_sethF(pscs, s, x); }