make •Import follow ReBQN

This commit is contained in:
dzaima 2023-12-11 13:58:28 +02:00
parent 56a6a08b97
commit 653583eb1d
6 changed files with 63 additions and 67 deletions

View File

@ -301,24 +301,6 @@ B find_c2(B t, B w, B x) {
decG(x); decG(w); return r; 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; static H_b2i* globalNames;
B globalNameList; B globalNameList;
i32 str2gid(B s) { i32 str2gid(B s) {
@ -373,7 +355,6 @@ B tack_uc1(B t, B o, B x) {
void fun_gcFn(void) { void fun_gcFn(void) {
if (prevImports!=NULL) mm_visitP(prevImports);
if (globalNames!=NULL) mm_visitP(globalNames); if (globalNames!=NULL) mm_visitP(globalNames);
} }
static void print_funBI(FILE* f, B x) { fprintf(f, "%s", pfn_repr(c(Fun,x)->extra)); } static void print_funBI(FILE* f, B x) { fprintf(f, "%s", pfn_repr(c(Fun,x)->extra)); }

View File

@ -825,54 +825,42 @@ static NFnDesc* importDesc;
B import_c2(B d, B w, B x) { 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) { B import_c1(B d, B x) {
if (importKeyList.u==0) { B* o = harr_ptr(nfn_objU(d));
importKeyList = emptyHVec(); B path = path_abs(path_rel(o[0], x, "•Import"));
importValList = emptyHVec(); B re = o[1];
} B map = IGetU(re, re_map);
B path = path_abs(path_rel(nfn_objU(d), x, "•Import"));
i32 prevIdx = getPrevImport(path); B tag_none = tag(100000000, C32_TAG);
if (prevIdx>=0) { 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)); // print_fmt("cached: %R @ %i/%i\n", path, prevIdx, IA(importKeyList));
dec(path); decG(path);
return IGet(importValList, prevIdx); 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) { if (CATCH) {
setPrevImport(path, -1); decG(c1(ns_getC(map, "delete"), incG(path)));
rethrow(); rethrow();
} }
i32 prevLen = IA(importValList); B r = bqn_execFileRe(incG(path), emptySVec(), re);
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);
popCatch(); popCatch();
decG(c2(nsSet, path, inc(r))); // path finally consumed
return r; 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; 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_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"); } 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; if (fileInit) return;
fileInit = true; 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"); 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 3: cr = getBitNS(); break; // •bit
case 4: cr = comps_getPrimitives(); break; // •primitives case 4: cr = comps_getPrimitives(); break; // •primitives
case 5: cr = getInternalNS(); break; // •internal case 5: cr = getInternalNS(); break; // •internal
case 6: initFileNS(); cr = m_nfn(fCharsDesc, inc(REQ_PATH)); break; // •FChars case 6: initSysDesc(); cr = m_nfn(fCharsDesc, inc(REQ_PATH)); break; // •FChars
case 7: initFileNS(); cr = m_nfn(fBytesDesc, inc(REQ_PATH)); break; // •FBytes case 7: initSysDesc(); cr = m_nfn(fBytesDesc, inc(REQ_PATH)); break; // •FBytes
case 8: initFileNS(); cr = m_nfn(fLinesDesc, inc(REQ_PATH)); break; // •FLines case 8: initSysDesc(); cr = m_nfn(fLinesDesc, inc(REQ_PATH)); break; // •FLines
case 9: initFileNS(); cr = m_nfn(importDesc, inc(REQ_PATH)); break; // •Import case 9: initSysDesc(); cr = m_nfn(importDesc, m_hvec2(inc(REQ_PATH), incG(COMPS_CREF(re)))); break; // •Import
case 10: initFileNS(); cr = m_nfn(ffiloadDesc, inc(REQ_PATH)); break; // •FFI 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 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 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 13: { cr = inc(CACHE_OBJ(wdpath, path_abs(inc(cdPath)))); break; } // •wdpath
case 14: { // •file case 14: { // •file
#define F(X) m_nfn(X##Desc, inc(path)) #define F(X) m_nfn(X##Desc, inc(path))
cr = incG(CACHE_OBJ(fileNS, ({ cr = incG(CACHE_OBJ(fileNS, ({
initFileNS(); initSysDesc();
REQ_PATH; 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)); 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 #endif
cdPath = m_c8vec(".", 1); gc_add(cdPath); cdPath = m_c8vec(".", 1); gc_add(cdPath);
gc_add_ref(&importKeyList);
gc_add_ref(&importValList);
gc_add_ref(&thrownMsg); gc_add_ref(&thrownMsg);
bqnDesc = registerNFn(m_c32vec_0(U"•BQN"), bqn_c1, bqn_c2); bqnDesc = registerNFn(m_c32vec_0(U"•BQN"), bqn_c1, bqn_c2);

View File

@ -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_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_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) { static NOINLINE B evalFunBlockConsume(Block* block) {
B r = evalFunBlock(block, NULL); B r = evalFunBlock(block, NULL);
ptr_dec(block); 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; prh.a[np[t]++] = v;
} }
new_re[re_map] = m_importMap();
new_re[re_rt] = prh.b; new_re[re_rt] = prh.b;
new_re[re_glyphs] = inc(rb); new_re[re_glyphs] = inc(rb);
new_re[re_comp] = c1(load_compgen, 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); B invalidFn_c1(B t, B x);
void comps_gcFn(void) { void comps_gcFn(void) {
@ -572,6 +584,7 @@ void load_init() { // very last init function
ps.a[re_comp] = load_comp; ps.a[re_comp] = load_comp;
ps.a[re_compOpts] = load_compOpts; ps.a[re_compOpts] = load_compOpts;
ps.a[re_rt] = incG(load_rt); ps.a[re_rt] = incG(load_rt);
ps.a[re_map] = m_importMap();
ps.a[re_glyphs] = load_glyphs; ps.a[re_glyphs] = load_glyphs;
ps.a[re_sysNames] = incG(def_sysNames); ps.a[re_sysNames] = incG(def_sysNames);
ps.a[re_sysVals] = incG(def_sysVals); 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); } 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 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); return bqn_exec(path_chars(path), state);
} }

View File

@ -11,6 +11,7 @@ enum {
}; };
enum { enum {
re_comp, re_compOpts, re_rt, re_glyphs, re_sysNames, re_sysVals, // compiling info 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_mode, re_scope, // only for repl_exec
re_max re_max
}; };
@ -25,6 +26,7 @@ typedef struct Block Block;
typedef struct Scope Scope; typedef struct Scope Scope;
B bqn_explain(B str); // consumes str B bqn_explain(B str); // consumes str
B bqn_execFile(B path, B args); // consumes both 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_comp (B str, B state); // consumes both
Block* bqn_compSc (B str, B state, Scope* sc, bool repl); // consumes str,state 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 Block* bqn_compScc(B str, B state, B re, Scope* sc, bool loose, bool noNS); // consumes str,state

View File

@ -3,11 +3,18 @@
File {path0 •file.At 𝕩} File {path0 •file.At 𝕩}
CleanPath ! {r•file.RealPath path0 i/r 𝕩? (i)("..."(r)+)𝕩; 𝕩}•CurrentError@ CleanPath ! {r•file.RealPath path0 i/r 𝕩? (i)("..."(r)+)𝕩; 𝕩}•CurrentError@
) )
( (
%USE file %USE file
i1 •Import File "show.bqn" ! "show.bqn" 1i1 f File "show.bqn"
i2 •Import File "show.bqn" ! "show.bqn" 1i2 r1 •Import f ! +"show.bqn" 1r1
! i1 i2 r2 •Import f ! +"show.bqn" 1r2
! r1 r2
re •ReBQN{primitives'+'-}
import2 RE "•Import"
r3 Import2 f ! -"show.bqn" 1r3
r4 Import2 f ! -"show.bqn" 1r4
! r1r3 ¨r1r2r3r4
) )
!"•Import: cyclic import of "".../cyclic.bqn""" % %USE file •ImportCleanPath File "cyclic.bqn" !"•Import: cyclic import of "".../cyclic.bqn""" % %USE file •ImportCleanPath File "cyclic.bqn"

View File

@ -1 +1 @@
{}, "show.bqn", •args {}, +, "show.bqn", •args