From 653583eb1d9699476ff67875d3e4cd220bee00c4 Mon Sep 17 00:00:00 2001 From: dzaima Date: Mon, 11 Dec 2023 13:58:28 +0200 Subject: [PATCH] =?UTF-8?q?make=20=E2=80=A2Import=20follow=20ReBQN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/fns.c | 19 ----------- src/builtins/sysfn.c | 72 +++++++++++++++++------------------------- src/load.c | 22 ++++++++++++- src/load.h | 2 ++ test/cases/imports.bqn | 13 ++++++-- test/imports/show.bqn | 2 +- 6 files changed, 63 insertions(+), 67 deletions(-) diff --git a/src/builtins/fns.c b/src/builtins/fns.c index 19155289..e4fe9d2b 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -301,24 +301,6 @@ B find_c2(B t, B w, B x) { decG(x); decG(w); return r; } -static H_b2i* prevImports; -i32 getPrevImport(B path) { // -1 for unset, -2 for unfinished - if (prevImports==NULL) prevImports = m_b2i(16); - - bool had; i32 prev = mk_b2i(&prevImports, path, &had); - if (had && prevImports->a[prev].val!=-1) return prevImports->a[prev].val; - prevImports->a[prev].val = -2; - return -1; -} -void setPrevImport(B path, i32 pos) { - bool had; i32 prev = mk_b2i(&prevImports, path, &had); - prevImports->a[prev].val = pos; -} -void clearImportCacheMap(void) { - if (prevImports!=NULL) free_b2i(prevImports); - prevImports = NULL; -} - static H_b2i* globalNames; B globalNameList; i32 str2gid(B s) { @@ -373,7 +355,6 @@ B tack_uc1(B t, B o, B x) { void fun_gcFn(void) { - if (prevImports!=NULL) mm_visitP(prevImports); if (globalNames!=NULL) mm_visitP(globalNames); } static void print_funBI(FILE* f, B x) { fprintf(f, "%s", pfn_repr(c(Fun,x)->extra)); } diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index c43e3702..7e05de93 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -825,54 +825,42 @@ static NFnDesc* importDesc; B import_c2(B d, B w, B x) { - return bqn_execFile(path_rel(nfn_objU(d), x, "•Import"), w); + B* o = harr_ptr(nfn_objU(d)); + B path = path_abs(path_rel(o[0], x, "•Import")); + B re = o[1]; + return bqn_execFileRe(path, w, re); } -// defined in fns.c -i32 getPrevImport(B path); -void setPrevImport(B path, i32 pos); -void clearImportCacheMap(void); - -static B importKeyList; // exists for GC roots as the hashmap doesn't -static B importValList; B import_c1(B d, B x) { - if (importKeyList.u==0) { - importKeyList = emptyHVec(); - importValList = emptyHVec(); - } - B path = path_abs(path_rel(nfn_objU(d), x, "•Import")); + B* o = harr_ptr(nfn_objU(d)); + B path = path_abs(path_rel(o[0], x, "•Import")); + B re = o[1]; + B map = IGetU(re, re_map); - i32 prevIdx = getPrevImport(path); - if (prevIdx>=0) { + B tag_none = tag(100000000, C32_TAG); + B tag_running = tag(100000001, C32_TAG); + B prevVal = c2(ns_getC(map, "get"), tag_none, incG(path)); + if (prevVal.u == tag_running.u) thrF("•Import: cyclic import of \"%R\"", path); + if (prevVal.u != tag_none.u) { // print_fmt("cached: %R @ %i/%i\n", path, prevIdx, IA(importKeyList)); - dec(path); - return IGet(importValList, prevIdx); + decG(path); + return prevVal; } - if (prevIdx==-2) thrF("•Import: cyclic import of \"%R\"", path); + + B nsSet = ns_getC(map, "set"); + decG(c2(nsSet, incG(path), tag_running)); if (CATCH) { - setPrevImport(path, -1); + decG(c1(ns_getC(map, "delete"), incG(path))); rethrow(); } - i32 prevLen = IA(importValList); - importKeyList = vec_addN(importKeyList, path); - importValList = vec_addN(importValList, bi_N); - - B r = bqn_execFile(incG(path), emptySVec()); - - harr_ptr(importValList)[prevLen] = inc(r); - setPrevImport(path, prevLen); + B r = bqn_execFileRe(incG(path), emptySVec(), re); popCatch(); + decG(c2(nsSet, path, inc(r))); // path finally consumed + return r; } -void clearImportCache(void) { - if (importKeyList.u!=0) { - dec(importKeyList); importKeyList = m_f64(0); - dec(importValList); importValList = m_f64(0); - } - clearImportCacheMap(); -} static NFnDesc* fTypeDesc; @@ -1716,7 +1704,7 @@ B invalidMd1_c2(Md1D* d, B w, B x) { thrM("Using an invalid 1-modifier"); } B invalidMd2_c1(Md2D* d, B x) { thrM("Using an invalid 2-modifier"); } B invalidMd2_c2(Md2D* d, B w, B x) { thrM("Using an invalid 2-modifier"); } -static void initFileNS() { +static NOINLINE void initSysDesc() { if (fileInit) return; fileInit = true; file_nsGen = m_nnsDesc("path","at","list","bytes","chars","lines","type","created","accessed","modified","size","exists","name","parent","mapbytes","createdir","realpath","rename","remove"); @@ -1839,18 +1827,18 @@ B sys_c1(B t, B x) { case 3: cr = getBitNS(); break; // •bit case 4: cr = comps_getPrimitives(); break; // •primitives case 5: cr = getInternalNS(); break; // •internal - case 6: initFileNS(); cr = m_nfn(fCharsDesc, inc(REQ_PATH)); break; // •FChars - case 7: initFileNS(); cr = m_nfn(fBytesDesc, inc(REQ_PATH)); break; // •FBytes - case 8: initFileNS(); cr = m_nfn(fLinesDesc, inc(REQ_PATH)); break; // •FLines - case 9: initFileNS(); cr = m_nfn(importDesc, inc(REQ_PATH)); break; // •Import - case 10: initFileNS(); cr = m_nfn(ffiloadDesc, inc(REQ_PATH)); break; // •FFI + case 6: initSysDesc(); cr = m_nfn(fCharsDesc, inc(REQ_PATH)); break; // •FChars + case 7: initSysDesc(); cr = m_nfn(fBytesDesc, inc(REQ_PATH)); break; // •FBytes + case 8: initSysDesc(); cr = m_nfn(fLinesDesc, inc(REQ_PATH)); break; // •FLines + case 9: initSysDesc(); cr = m_nfn(importDesc, m_hvec2(inc(REQ_PATH), incG(COMPS_CREF(re)))); break; // •Import + case 10: initSysDesc(); cr = m_nfn(ffiloadDesc, inc(REQ_PATH)); break; // •FFI case 11: if (q_N(name)) thrM("No name present for •name"); cr = inc(name); break; // •name case 12: if (q_N(path0)) thrM("No path present for •path"); cr = inc(REQ_PATH); break; // •path case 13: { cr = inc(CACHE_OBJ(wdpath, path_abs(inc(cdPath)))); break; } // •wdpath case 14: { // •file #define F(X) m_nfn(X##Desc, inc(path)) cr = incG(CACHE_OBJ(fileNS, ({ - initFileNS(); + initSysDesc(); REQ_PATH; m_nns(file_nsGen, q_N(path)? m_c32(0) : inc(path), F(fileAt), F(fList), F(fBytes), F(fChars), F(fLines), F(fType), F(fCreated), F(fAccessed), F(fModified), F(fSize), F(fExists), inc(bi_fName), inc(bi_fParent), F(fMapBytes), F(createdir), F(realpath), F(rename), F(remove)); }))); @@ -1936,8 +1924,6 @@ void sysfn_init(void) { #endif cdPath = m_c8vec(".", 1); gc_add(cdPath); - gc_add_ref(&importKeyList); - gc_add_ref(&importValList); gc_add_ref(&thrownMsg); bqnDesc = registerNFn(m_c32vec_0(U"•BQN"), bqn_c1, bqn_c2); diff --git a/src/load.c b/src/load.c index 6675a357..a974f75c 100644 --- a/src/load.c +++ b/src/load.c @@ -113,6 +113,10 @@ static NOINLINE B m_lvi32_2(i32 a, i32 b ) { i32* rp; B r = m_i32ar static NOINLINE B m_lvi32_3(i32 a, i32 b, i32 c ) { i32* rp; B r = m_i32arrv(&rp,3); rp[0]=a; rp[1]=b; rp[2]=c; return r; } static NOINLINE B m_lvi32_4(i32 a, i32 b, i32 c, i32 d) { i32* rp; B r = m_i32arrv(&rp,4); rp[0]=a; rp[1]=b; rp[2]=c; rp[3]=d; return r; } +static NOINLINE B m_importMap(void) { + return c2(bi_hashMap, emptyHVec(), emptyHVec()); +} + static NOINLINE B evalFunBlockConsume(Block* block) { B r = evalFunBlock(block, NULL); ptr_dec(block); @@ -288,6 +292,7 @@ void init_comp(B* new_re, B* prev_re, B prim, B sys) { prh.a[np[t]++] = v; } + new_re[re_map] = m_importMap(); new_re[re_rt] = prh.b; new_re[re_glyphs] = inc(rb); new_re[re_comp] = c1(load_compgen, rb); @@ -397,6 +402,13 @@ B repl_exec(B str, B state, B re) { } } +void clearImportCache(void) { + B* where = harr_ptr(def_re)+re_map; + B prev = *where; + *where = m_importMap(); + decG(prev); +} + B invalidFn_c1(B t, B x); void comps_gcFn(void) { @@ -572,6 +584,7 @@ void load_init() { // very last init function ps.a[re_comp] = load_comp; ps.a[re_compOpts] = load_compOpts; ps.a[re_rt] = incG(load_rt); + ps.a[re_map] = m_importMap(); ps.a[re_glyphs] = load_glyphs; ps.a[re_sysNames] = incG(def_sysNames); ps.a[re_sysVals] = incG(def_sysVals); @@ -593,8 +606,15 @@ void load_init() { // very last init function } NOINLINE B m_state(B path, B name, B args) { return m_lvB_3(path, name, args); } +static NOINLINE B fileState(B path, B args) { // consumes args + return m_state(path_parent(inc(path)), path_name(inc(path)), args); +} +B bqn_execFileRe(B path, B args, B re) { + B state = fileState(path, args); + return evalFunBlockConsume(bqn_compc(path_chars(path), state, re)); +} B bqn_execFile(B path, B args) { // consumes both - B state = m_state(path_parent(inc(path)), path_name(inc(path)), args); + B state = fileState(path, args); return bqn_exec(path_chars(path), state); } diff --git a/src/load.h b/src/load.h index f9f058af..ebcc3478 100644 --- a/src/load.h +++ b/src/load.h @@ -11,6 +11,7 @@ enum { }; enum { re_comp, re_compOpts, re_rt, re_glyphs, re_sysNames, re_sysVals, // compiling info + re_map, // •HashMap of cached import results re_mode, re_scope, // only for repl_exec re_max }; @@ -25,6 +26,7 @@ typedef struct Block Block; typedef struct Scope Scope; B bqn_explain(B str); // consumes str B bqn_execFile(B path, B args); // consumes both +B bqn_execFileRe(B path, B args, B re); // consumes path,args Block* bqn_comp (B str, B state); // consumes both Block* bqn_compSc (B str, B state, Scope* sc, bool repl); // consumes str,state Block* bqn_compScc(B str, B state, B re, Scope* sc, bool loose, bool noNS); // consumes str,state diff --git a/test/cases/imports.bqn b/test/cases/imports.bqn index fea77a85..5697fed9 100644 --- a/test/cases/imports.bqn +++ b/test/cases/imports.bqn @@ -3,11 +3,18 @@ File ← {path0 •file.At 𝕩} CleanPath ← ! {r←•file.RealPath path0 ⋄ ≠i←/r ⍷ 𝕩? (⋈⁼i)(↑∾"..."∾(≠r)⊸+⊸↓)𝕩; 𝕩}∘•CurrentError∘@ ) + ( %USE file - i1 ← •Import File "show.bqn" ⋄ ! "show.bqn"‿⟨⟩ ≡ 1↓i1 - i2 ← •Import File "show.bqn" ⋄ ! "show.bqn"‿⟨⟩ ≡ 1↓i2 - ! i1 ≡ i2 + f ← File "show.bqn" + r1 ← •Import f ⋄ ! +‿"show.bqn"‿⟨⟩ ≡ 1↓r1 + r2 ← •Import f ⋄ ! +‿"show.bqn"‿⟨⟩ ≡ 1↓r2 + ! r1 ≡○⊑ r2 + re ← •ReBQN{primitives⇐⟨'+'‿-⟩} + import2 ← RE "•Import" + r3 ← Import2 f ⋄ ! -‿"show.bqn"‿⟨⟩ ≡ 1↓r3 + r4 ← Import2 f ⋄ ! -‿"show.bqn"‿⟨⟩ ≡ 1↓r4 + ! r1‿r3 ≡ ⍷⊑¨r1‿r2‿r3‿r4 ) !"•Import: cyclic import of "".../cyclic.bqn""" % %USE file ⋄ •Import⎊CleanPath File "cyclic.bqn" diff --git a/test/imports/show.bqn b/test/imports/show.bqn index aa1c5e74..a214856d 100644 --- a/test/imports/show.bqn +++ b/test/imports/show.bqn @@ -1 +1 @@ -⟨{⇐}, "show.bqn", •args⟩ +⟨{⇐}, +, "show.bqn", •args⟩