diff --git a/src/core/stuff.c b/src/core/stuff.c index 2b23558a..834cd8a3 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -49,7 +49,9 @@ B def_m1_uc1(B t, B o, B f, B x) { B t2 = m1_d(inc(t),inc(f) ); B def_m1_ucw(B t, B o, B f, B w, B x) { B t2 = m1_d(inc(t),inc(f) ); B r = rtUnder_cw(o, t2, w, x); dec(t2); return r; } B def_m2_uc1(B t, B o, B f, B g, B x) { B t2 = m2_d(inc(t),inc(f),inc(g)); B r = rtUnder_c1(o, t2, x); dec(t2); return r; } B def_m2_ucw(B t, B o, B f, B g, B w, B x) { B t2 = m2_d(inc(t),inc(f),inc(g)); B r = rtUnder_cw(o, t2, w, x); dec(t2); return r; } -B def_decompose(B x) { return m_v2(m_i32(isCallable(x)? 0 : -1),x); } +B def_decompose(B x) { + return m_v2(m_i32(isCallable(x)? (isImpureBuiltin(x)? 1 : 0) : -1),x); +} B bi_emptyHVec, bi_emptyIVec, bi_emptyCVec, bi_emptySVec; @@ -426,7 +428,6 @@ char* format_type(u8 u) { bool isPureFn(B x) { // doesn't consume if (isCallable(x)) { if (v(x)->flags) return true; - if (v(x)->extra >= pf_type) return false; B2B dcf = TI(x,decompose); B xd = dcf(inc(x)); B* xdp = harr_ptr(xd); diff --git a/src/utils/builtins.h b/src/utils/builtins.h index 0448a312..8197443e 100644 --- a/src/utils/builtins.h +++ b/src/utils/builtins.h @@ -15,6 +15,7 @@ #define FOR_PM1(A,M,D) \ /*md1.c*/ A(tbl,"⌜") A(each,"¨") A(fold,"´") A(scan,"`") A(const,"˙") A(swap,"˜") A(cell,"˘") \ +/* everything before the definition of •_timed is defined to be pure, and everything after is not */ \ /*md1.c*/ A(timed,"•_timed") #define FOR_PM2(A,M,D) \ @@ -36,6 +37,16 @@ enum PrimMd2 { pm2_none, FOR_PM2(F,F,F) #undef F }; +static const i32 firstImpurePFN = pf_type; +static const i32 firstImpurePM1 = pm1_timed; +static const i32 firstImpurePM2 = I32_MAX; + +static inline bool isImpureBuiltin(B x) { + if (isFun(x)) return !v(x)->extra || v(x)->extra>=firstImpurePFN; + if (isMd1(x)) return !v(x)->extra || v(x)->extra>=firstImpurePM1; + if (isMd2(x)) return !v(x)->extra || v(x)->extra>=firstImpurePM2; + return false; +} #define F(N,X) extern B bi_##N;