diff --git a/makefile b/makefile index a00694d9..6ba5f33e 100644 --- a/makefile +++ b/makefile @@ -31,7 +31,7 @@ rtverifyn-singeli: wasi-o3: @${MAKE} singeli=0 t=wasi_o3 f="-DWASM -DCATCH_ERRORS=0 -D_WASI_EMULATED_MMAN --target=wasm32-wasi" LDFLAGS="-lwasi-emulated-mman --target=wasm32-wasi" LD_LIBS= PIE= c emcc-o3: - @${MAKE} singeli=0 t=emcc_o3 f='-DWASM -O3' CC=emcc c + @${MAKE} singeli=0 t=emcc_o3 f='-DWASM -DEMCC -O3' LDFLAGS='-s EXPORTED_FUNCTIONS=_main,_cbqn_runLine -s EXPORTED_RUNTIME_METHODS=ccall,cwrap' CC=emcc c # compiler setup diff --git a/src/main.c b/src/main.c index 606596c5..5f1d9488 100644 --- a/src/main.c +++ b/src/main.c @@ -39,6 +39,193 @@ static bool isCmd(char* s, char** e, const char* cmd) { return true; } +void cbqn_runLine0(char* ln, i64 read) { + if (ln[0]==10) return; + if (ln[read-1]==10) ln[--read] = 0; + + B code; + int output; // 0-no; 1-formatter; 2-internal + i32 time = 0; + if (ln[0] == ')') { + char* cmdS = ln+1; + char* cmdE; + if (isCmd(cmdS, &cmdE, "ex ")) { + B path = fromUTF8l(cmdE); + code = path_chars(path); + output = 0; + } else if (isCmd(cmdS, &cmdE, "t ") || isCmd(cmdS, &cmdE, "time ")) { + code = fromUTF8l(cmdE); + time = -1; + output = 0; + } else if (isCmd(cmdS, &cmdE, "t:") || isCmd(cmdS, &cmdE, "time:")) { + char* repE = cmdE; + i64 am = 0; + while (*repE>='0' & *repE<='9') { + am = am*10 + (*repE - '0'); + repE++; + } + if (repE==cmdE) { printf("time command not given repetition count\n"); return; } + if (am==0) { printf("repetition count was zero\n"); return; } + code = fromUTF8l(repE); + time = am; + output = 0; + } else if (isCmd(cmdS, &cmdE, "mem ")) { + bool sizes = 0; + bool types = 0; + bool freed = 0; + char c; + while ((c=*(cmdE++)) != 0) { + if (c=='t') types=1; + if (c=='s') sizes=1; + if (c=='f') freed=1; + } + heap_printInfo(sizes, types, freed); + return; + } else if (isCmd(cmdS, &cmdE, "erase ")) { + char* name = cmdE; + i64 len = strlen(name); + ScopeExt* e = gsc->ext; + if (e!=NULL) { + i32 am = e->varAm; + for (i32 i = 0; i < am; i++) { + B c = e->vars[i+am]; + if (a(c)->ia != len) continue; + SGetU(c) + bool ok = true; + for (i32 j = 0; j < len; j++) ok&= o2cu(GetU(c, j))==name[j]; + if (ok) { + B val = e->vars[i]; + e->vars[i] = bi_noVar; + dec(val); + #if ENABLE_GC + if (!gc_depth) gc_forceGC(); + #endif + return; + } + } + } + printf("No such variable found\n"); + return; + } else if (isCmd(cmdS, &cmdE, "vars")) { + B r = listVars(gsc); + if (q_N(r)) { + printf("Couldn't list variables\n"); + } else { + usz ia = a(r)->ia; + B* rp = harr_ptr(r); + for (usz i = 0; i < ia; i++) { + if (i!=0) printf(", "); + printRaw(rp[i]); + } + putchar('\n'); + } + return; + } else if (isCmd(cmdS, &cmdE, "gc ")) { + #if ENABLE_GC + if (0==*cmdE) { + if (gc_depth!=0) { + printf("GC is disabled, but forcibly GCing anyway\n"); + gc_enable(); + gc_forceGC(); + gc_disable(); + } else { + gc_forceGC(); + } + } else if (strcmp(cmdE,"on")==0) { + if (gc_depth==0) printf("GC already on\n"); + else if (gc_depth>1) printf("GC cannot be enabled\n"); + else { + gc_enable(); + printf("GC enabled\n"); + } + } else if (strcmp(cmdE,"off")==0) { + if (gc_depth>0) printf("GC already off\n"); + else { + gc_disable(); + printf("GC disabled\n"); + } + } else printf("Unknown GC command\n"); + #else + printf("Macro ENABLE_GC was false at compile-time, cannot GC\n"); + #endif + return; + } else if (isCmd(cmdS, &cmdE, "internalPrint ")) { + code = fromUTF8l(cmdE); + output = 2; + } else { + printf("Unknown REPL command\n"); + return; + } + } else { + code = fromUTF8l(ln); + output = 1; + } + Block* block = bqn_compSc(code, inc(replPath), emptySVec(), gsc, true); + + ptr_dec(gsc->body); + gsc->body = ptr_inc(block->bodies[0]); + + B res; + if (time) { + f64 t; + if (time==-1) { + u64 sns = nsTime(); + res = execBlockInline(block, gsc); + u64 ens = nsTime(); + t = ens-sns; + } else { + u64 sns = nsTime(); + for (i64 i = 0; i < time; i++) dec(execBlockInline(block, gsc)); + u64 ens = nsTime(); + t = (ens-sns)*1.0 / time; + res = m_c32(0); + } + if (t<1e3) printf("%.5gns\n", t); + else if (t<1e6) printf("%.4gus\n", t/1e3); + else if (t<1e9) printf("%.4gms\n", t/1e6); + else printf("%.5gs\n", t/1e9); + } else { + res = execBlockInline(block, gsc); + } + ptr_dec(block); + + if (output) { + if (output!=2 && FORMATTER) { + B resFmt = bqn_fmt(res); + printRaw(resFmt); dec(resFmt); + putchar('\n'); + } else { + print(res); putchar('\n'); fflush(stdout); + dec(res); + } + } else dec(res); + + #ifdef HEAP_VERIFY + heapVerify(); + #endif + gc_maybeGC(); +} + +void cbqn_runLine(char* ln, i64 read) { + if(CATCH) { + fprintf(stderr, "Error: "); printErrMsg(thrownMsg); fputc('\n', stderr); + vm_pst(envCurr+1, envStart+envPrevHeight); + freeThrown(); + #ifdef HEAP_VERIFY + heapVerify(); + #endif + gc_maybeGC(); + return; + } + cbqn_runLine0(ln, read); + popCatch(); +} + +#if EMCC +int main() { + repl_init(); +} +#else int main(int argc, char* argv[]) { bool startREPL = argc==1; bool silentREPL = false; @@ -151,187 +338,15 @@ int main(int argc, char* argv[]) { } if (startREPL) { repl_init(); - while (CATCH) { - fprintf(stderr, "Error: "); printErrMsg(thrownMsg); fputc('\n', stderr); - vm_pst(envCurr+1, envStart+envPrevHeight); - freeThrown(); - #ifdef HEAP_VERIFY - heapVerify(); - #endif - gc_maybeGC(); - } - while (true) { // exit by evaluating an empty expression + while (true) { + if (!silentREPL) printf(" "); char* ln = NULL; size_t gl = 0; - if (!silentREPL) printf(" "); i64 read = getline(&ln, &gl, stdin); if (read<=0 || ln[0]==0) { if(!silentREPL) putchar('\n'); break; } - if (ln[0]==10) { cont: free(ln); continue; } - if (ln[read-1]==10) ln[--read] = 0; - B code; - int output; // 0-no; 1-formatter; 2-internal - i32 time = 0; - if (ln[0] == ')') { - char* cmdS = ln+1; - char* cmdE; - if (isCmd(cmdS, &cmdE, "ex ")) { - B path = fromUTF8l(cmdE); - code = path_chars(path); - output = 0; - } else if (isCmd(cmdS, &cmdE, "t ") || isCmd(cmdS, &cmdE, "time ")) { - code = fromUTF8l(cmdE); - time = -1; - output = 0; - } else if (isCmd(cmdS, &cmdE, "t:") || isCmd(cmdS, &cmdE, "time:")) { - char* repE = cmdE; - i64 am = 0; - while (*repE>='0' & *repE<='9') { - am = am*10 + (*repE - '0'); - repE++; - } - if (repE==cmdE) { printf("time command not given repetition count\n"); goto cont; } - if (am==0) { printf("repetition count was zero\n"); goto cont; } - code = fromUTF8l(repE); - time = am; - output = 0; - } else if (isCmd(cmdS, &cmdE, "mem ")) { - bool sizes = 0; - bool types = 0; - bool freed = 0; - char c; - while ((c=*(cmdE++)) != 0) { - if (c=='t') types=1; - if (c=='s') sizes=1; - if (c=='f') freed=1; - } - heap_printInfo(sizes, types, freed); - goto cont; - } else if (isCmd(cmdS, &cmdE, "erase ")) { - char* name = cmdE; - i64 len = strlen(name); - ScopeExt* e = gsc->ext; - if (e!=NULL) { - i32 am = e->varAm; - for (i32 i = 0; i < am; i++) { - B c = e->vars[i+am]; - if (a(c)->ia != len) continue; - SGetU(c) - bool ok = true; - for (i32 j = 0; j < len; j++) ok&= o2cu(GetU(c, j))==name[j]; - if (ok) { - B val = e->vars[i]; - e->vars[i] = bi_noVar; - dec(val); - #if ENABLE_GC - if (!gc_depth) gc_forceGC(); - #endif - goto cont; - } - } - } - printf("No such variable found\n"); - goto cont; - } else if (isCmd(cmdS, &cmdE, "vars")) { - B r = listVars(gsc); - if (q_N(r)) { - printf("Couldn't list variables\n"); - } else { - usz ia = a(r)->ia; - B* rp = harr_ptr(r); - for (usz i = 0; i < ia; i++) { - if (i!=0) printf(", "); - printRaw(rp[i]); - } - putchar('\n'); - } - goto cont; - } else if (isCmd(cmdS, &cmdE, "gc ")) { - #if ENABLE_GC - if (0==*cmdE) { - if (gc_depth!=0) { - printf("GC is disabled, but forcibly GCing anyway\n"); - gc_enable(); - gc_forceGC(); - gc_disable(); - } else { - gc_forceGC(); - } - } else if (strcmp(cmdE,"on")==0) { - if (gc_depth==0) printf("GC already on\n"); - else if (gc_depth>1) printf("GC cannot be enabled\n"); - else { - gc_enable(); - printf("GC enabled\n"); - } - } else if (strcmp(cmdE,"off")==0) { - if (gc_depth>0) printf("GC already off\n"); - else { - gc_disable(); - printf("GC disabled\n"); - } - } else printf("Unknown GC command\n"); - #else - printf("Macro ENABLE_GC was false at compile-time, cannot GC\n"); - #endif - goto cont; - } else if (isCmd(cmdS, &cmdE, "internalPrint ")) { - code = fromUTF8l(cmdE); - output = 2; - } else { - printf("Unknown REPL command\n"); - goto cont; - } - } else { - code = fromUTF8l(ln); - output = 1; - } - Block* block = bqn_compSc(code, inc(replPath), emptySVec(), gsc, true); - - ptr_dec(gsc->body); - gsc->body = ptr_inc(block->bodies[0]); - - B res; - if (time) { - f64 t; - if (time==-1) { - u64 sns = nsTime(); - res = execBlockInline(block, gsc); - u64 ens = nsTime(); - t = ens-sns; - } else { - u64 sns = nsTime(); - for (i64 i = 0; i < time; i++) dec(execBlockInline(block, gsc)); - u64 ens = nsTime(); - t = (ens-sns)*1.0 / time; - res = m_c32(0); - } - if (t<1e3) printf("%.5gns\n", t); - else if (t<1e6) printf("%.4gus\n", t/1e3); - else if (t<1e9) printf("%.4gms\n", t/1e6); - else printf("%.5gs\n", t/1e9); - } else { - res = execBlockInline(block, gsc); - } - ptr_dec(block); - - if (output) { - if (output!=2 && FORMATTER) { - B resFmt = bqn_fmt(res); - printRaw(resFmt); dec(resFmt); - putchar('\n'); - } else { - print(res); putchar('\n'); fflush(stdout); - dec(res); - } - } else dec(res); - - #ifdef HEAP_VERIFY - heapVerify(); - #endif - gc_maybeGC(); - goto cont; + cbqn_runLine(ln, read); + free(ln); } - popCatch(); } #ifdef HEAP_VERIFY heapVerify(); @@ -339,3 +354,4 @@ int main(int argc, char* argv[]) { bqn_exit(0); #undef INIT } +#endif \ No newline at end of file