native minimal compiler
This commit is contained in:
parent
e231d36471
commit
9abe7506ab
@ -492,7 +492,7 @@ AddRule ← { 𝕊 cache‿cacheKey‿dst‿GetCMD‿disp‿deps:
|
||||
cacheKey ⇐ cacheKey
|
||||
found0 ⇐ 0
|
||||
SetFound ↩ {found0↩𝕩}
|
||||
DepHash ⇐ {𝕊: Hash {𝕩.found1≡@? 𝕩.found0; 𝕩.found1}¨ ruleDeps}
|
||||
DepHash ⇐ {𝕊: Hash {𝕩.found1≡@? 𝕩.found0; 𝕩.found1}¨ ruleDeps} # todo instead of conditionally choosing found1 or found2, decide statically; and properly cache
|
||||
found1 ⇐ @
|
||||
SetVal ⇐ {found1 ↩ 𝕩⋈DepHash@}
|
||||
disp ⇐ disp
|
||||
|
||||
@ -279,7 +279,18 @@ B eequal_c2(B t, B w, B x) {
|
||||
#ifdef TEST_BITCPY
|
||||
#include "../utils/mut.h"
|
||||
#endif
|
||||
#if NATIVE_COMPILER
|
||||
extern B native_comp;
|
||||
void switchComp(void);
|
||||
#endif
|
||||
B internalTemp_c1(B t, B x) {
|
||||
|
||||
#if NATIVE_COMPILER
|
||||
switchComp();
|
||||
B r = bqn_exec(x, bi_N, bi_N);
|
||||
switchComp();
|
||||
return r;
|
||||
#endif
|
||||
#ifdef TEST_BITCPY
|
||||
SGetU(x)
|
||||
bit_cpy(bitarr_ptr(GetU(x,0)), o2s(GetU(x,1)), bitarr_ptr(GetU(x,2)), o2s(GetU(x,3)), o2s(GetU(x,4)));
|
||||
@ -291,10 +302,13 @@ B internalTemp_c1(B t, B x) {
|
||||
#include "../utils/calls.h"
|
||||
#endif
|
||||
B internalTemp_c2(B t, B w, B x) {
|
||||
#if NATIVE_COMPILER
|
||||
return c2(native_comp, w, x);
|
||||
#endif
|
||||
#ifdef TEST_MUT
|
||||
SGetU(x)
|
||||
FILL_TO(tyarr_ptr(w), o2s(GetU(x,0)), o2s(GetU(x,1)), GetU(x,2), o2s(GetU(x,3)));
|
||||
dec(w);
|
||||
SGetU(x)
|
||||
FILL_TO(tyarr_ptr(w), o2s(GetU(x,0)), o2s(GetU(x,1)), GetU(x,2), o2s(GetU(x,3)));
|
||||
dec(w);
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
|
||||
100
src/load.c
100
src/load.c
@ -118,7 +118,10 @@ Block* load_compObj(B x, B src, B path, Scope* sc) { // consumes x,src
|
||||
return r;
|
||||
}
|
||||
|
||||
#if !(ONLY_NATIVE_COMP && !FORMATTER && NO_RT && NO_EXPLAIN)
|
||||
#include PRECOMPILED_FILE(src)
|
||||
#endif
|
||||
|
||||
#if RT_SRC
|
||||
Block* load_compImport(char* name, B bc, B objs, B blocks, B bodies, B inds, B src) { // consumes all
|
||||
return compile(bc, objs, blocks, bodies, inds, bi_N, src, m_c8vec_0(name), NULL);
|
||||
@ -136,6 +139,15 @@ B load_compArg;
|
||||
B load_glyphs;
|
||||
B load_explain;
|
||||
|
||||
|
||||
#if NATIVE_COMPILER
|
||||
#include "opt/comp.c"
|
||||
B load_rtComp;
|
||||
void switchComp() {
|
||||
load_comp = load_comp.u==load_rtComp.u? native_comp : load_rtComp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FORMATTER
|
||||
B load_fmt, load_repr;
|
||||
B bqn_fmt(B x) { // consumes
|
||||
@ -414,15 +426,15 @@ void load_init() { // very last init function
|
||||
HArr_p runtimeH = m_harrUc(rtObjRaw);
|
||||
SGet(rtObjRaw)
|
||||
|
||||
rt_undo = Get(rtObjRaw, n_undo ); gc_add(rt_undo);
|
||||
rt_select = Get(rtObjRaw, n_select ); gc_add(rt_select);
|
||||
rt_slash = Get(rtObjRaw, n_slash ); gc_add(rt_slash);
|
||||
rt_group = Get(rtObjRaw, n_group ); gc_add(rt_group);
|
||||
rt_under = Get(rtObjRaw, n_under ); gc_add(rt_under);
|
||||
rt_find = Get(rtObjRaw, n_find ); gc_add(rt_find);
|
||||
rt_transp = Get(rtObjRaw, n_transp ); gc_add(rt_transp);
|
||||
rt_depth = Get(rtObjRaw, n_depth ); gc_add(rt_depth);
|
||||
rt_insert = Get(rtObjRaw, n_insert ); gc_add(rt_insert);
|
||||
rt_undo = Get(rtObjRaw, n_undo );
|
||||
rt_select = Get(rtObjRaw, n_select );
|
||||
rt_slash = Get(rtObjRaw, n_slash );
|
||||
rt_group = Get(rtObjRaw, n_group );
|
||||
rt_under = Get(rtObjRaw, n_under );
|
||||
rt_find = Get(rtObjRaw, n_find );
|
||||
rt_transp = Get(rtObjRaw, n_transp );
|
||||
rt_depth = Get(rtObjRaw, n_depth );
|
||||
rt_insert = Get(rtObjRaw, n_insert );
|
||||
|
||||
for (usz i = 0; i < rtLen; i++) {
|
||||
#ifdef RT_WRAP
|
||||
@ -461,14 +473,22 @@ void load_init() { // very last init function
|
||||
if (isVal(r)) v(r)->flags|= i+1;
|
||||
}
|
||||
load_rtObj = frtObj;
|
||||
load_compArg = m_hVec2(load_rtObj, incG(bi_sys)); gc_add(frtObj);
|
||||
rt_select=rt_slash=rt_group=rt_find=rt_transp=rt_invFnReg=rt_invFnSwap = bi_invalidFn;
|
||||
rt_undo=rt_insert = bi_invalidMd1;
|
||||
rt_under=rt_depth = bi_invalidMd2;
|
||||
load_compArg = m_hVec2(load_rtObj, incG(bi_sys));
|
||||
rt_select=rt_slash=rt_group=rt_find=rt_transp=rt_invFnReg=rt_invFnSwap = incByG(bi_invalidFn, 7);
|
||||
rt_undo=rt_insert = incByG(bi_invalidMd1, 2);
|
||||
rt_under=rt_depth = incByG(bi_invalidMd2, 2);
|
||||
rt_invFnRegFn=rt_invFnSwapFn = invalidFn_c1;
|
||||
#endif
|
||||
gc_add(load_compArg);
|
||||
|
||||
gc_add(rt_undo);
|
||||
gc_add(rt_select);
|
||||
gc_add(rt_slash);
|
||||
gc_add(rt_group);
|
||||
gc_add(rt_under);
|
||||
gc_add(rt_find);
|
||||
gc_add(rt_transp);
|
||||
gc_add(rt_depth);
|
||||
gc_add(rt_insert);
|
||||
|
||||
|
||||
|
||||
@ -489,29 +509,35 @@ void load_init() { // very last init function
|
||||
print_allocStats();
|
||||
exit(0);
|
||||
#else // use compiler
|
||||
B prevAsrt = runtime[n_asrt];
|
||||
runtime[n_asrt] = bi_casrt; // horrible but GC is off so it's fiiiiiine
|
||||
Block* comp_b = load_compImport("(compiler)",
|
||||
#include PRECOMPILED_FILE(compiles)
|
||||
);
|
||||
runtime[n_asrt] = prevAsrt;
|
||||
load_glyphs = m_hVec3(m_c32vec_0(U"+-×÷⋆√⌊⌈|¬∧∨<>≠=≤≥≡≢⊣⊢⥊∾≍⋈↑↓↕«»⌽⍉/⍋⍒⊏⊑⊐⊒∊⍷⊔!"), m_c32vec_0(U"˙˜˘¨⌜⁼´˝`"), m_c32vec_0(U"∘○⊸⟜⌾⊘◶⎉⚇⍟⎊"));
|
||||
load_compgen = evalFunBlock(comp_b, 0); ptr_dec(comp_b);
|
||||
load_comp = c1(load_compgen, inc(load_glyphs));
|
||||
gc_add(load_compgen); gc_add(load_comp); gc_add(load_glyphs);
|
||||
load_glyphs = m_hVec3(m_c32vec_0(U"+-×÷⋆√⌊⌈|¬∧∨<>≠=≤≥≡≢⊣⊢⥊∾≍⋈↑↓↕«»⌽⍉/⍋⍒⊏⊑⊐⊒∊⍷⊔!"), m_c32vec_0(U"˙˜˘¨⌜⁼´˝`"), m_c32vec_0(U"∘○⊸⟜⌾⊘◶⎉⚇⍟⎊")); gc_add(load_glyphs);
|
||||
|
||||
#if !ONLY_NATIVE_COMP
|
||||
B prevAsrt = runtime[n_asrt];
|
||||
runtime[n_asrt] = bi_casrt; // horrible but GC is off so it's fiiiiiine
|
||||
Block* comp_b = load_compImport("(compiler)",
|
||||
#include PRECOMPILED_FILE(compiles)
|
||||
);
|
||||
runtime[n_asrt] = prevAsrt;
|
||||
load_compgen = evalFunBlock(comp_b, 0); ptr_dec(comp_b);
|
||||
load_comp = c1(load_compgen, inc(load_glyphs));
|
||||
#if NATIVE_COMPILER
|
||||
load_rtComp = load_comp;
|
||||
#endif
|
||||
gc_add(load_compgen); gc_add(load_comp);
|
||||
#endif
|
||||
|
||||
|
||||
#if FORMATTER
|
||||
Block* fmt_b = load_compImport("(formatter)",
|
||||
#include PRECOMPILED_FILE(formatter)
|
||||
);
|
||||
B fmtM = evalFunBlock(fmt_b, 0); ptr_dec(fmt_b);
|
||||
B fmtR = c1(fmtM, m_caB(4, (B[]){incG(bi_type), incG(bi_decp), incG(bi_glyph), incG(bi_repr)}));
|
||||
decG(fmtM);
|
||||
SGet(fmtR)
|
||||
load_fmt = Get(fmtR, 0); gc_add(load_fmt);
|
||||
load_repr = Get(fmtR, 1); gc_add(load_repr);
|
||||
decG(fmtR);
|
||||
Block* fmt_b = load_compImport("(formatter)",
|
||||
#include PRECOMPILED_FILE(formatter)
|
||||
);
|
||||
B fmtM = evalFunBlock(fmt_b, 0); ptr_dec(fmt_b);
|
||||
B fmtR = c1(fmtM, m_caB(4, (B[]){incG(bi_type), incG(bi_decp), incG(bi_glyph), incG(bi_repr)}));
|
||||
decG(fmtM);
|
||||
SGet(fmtR)
|
||||
load_fmt = Get(fmtR, 0); gc_add(load_fmt);
|
||||
load_repr = Get(fmtR, 1); gc_add(load_repr);
|
||||
decG(fmtR);
|
||||
#endif
|
||||
|
||||
gc_enable();
|
||||
@ -754,6 +780,12 @@ void typesFinished_init() {
|
||||
for (u64 i = 0; i < t_COUNT; i++) {
|
||||
if (TIi(i,freeT) == def_fallbackTriv) TIi(i,freeT) = TIi(i,freeF);
|
||||
}
|
||||
#if NATIVE_COMPILER
|
||||
nativeCompiler_init();
|
||||
#if ONLY_NATIVE_COMP
|
||||
load_comp = native_comp;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool cbqn_initialized;
|
||||
|
||||
@ -489,6 +489,10 @@ void profiler_free(void);
|
||||
void profiler_displayResults(void);
|
||||
void clearImportCache(void);
|
||||
|
||||
#if NATIVE_COMPILER && !ONLY_NATIVE_COMP
|
||||
void switchComp(void);
|
||||
#endif
|
||||
|
||||
static B escape_parser;
|
||||
static B simple_unescape(B x) {
|
||||
if (RARE(escape_parser.u==0)) {
|
||||
@ -654,6 +658,11 @@ void cbqn_runLine0(char* ln, i64 read) {
|
||||
} else if (isCmd(cmdS, &cmdE, "internalPrint ")) {
|
||||
code = utf8Decode0(cmdE);
|
||||
output = 2;
|
||||
#if NATIVE_COMPILER && !ONLY_NATIVE_COMP
|
||||
} else if (isCmd(cmdS, &cmdE, "switchCompiler")) {
|
||||
switchComp();
|
||||
return;
|
||||
#endif
|
||||
} else if (isCmd(cmdS, &cmdE, "e ") || isCmd(cmdS, &cmdE, "explain ")) {
|
||||
B expl = bqn_explain(utf8Decode0(cmdE), replPath);
|
||||
HArr* expla = toHArr(expl);
|
||||
|
||||
9
src/ns.c
9
src/ns.c
@ -140,7 +140,14 @@ Body* m_nnsDescF(i32 n, char** names) {
|
||||
|
||||
B m_nnsF(Body* desc, i32 n, B* vals) {
|
||||
assert(n == desc->varAm);
|
||||
Scope* sc = m_scope(desc, NULL, n, n, vals);
|
||||
i32 varAm = n;
|
||||
#if ONLY_NATIVE_COMP
|
||||
varAm+= 100;
|
||||
#endif
|
||||
Scope* sc = m_scope(desc, NULL, varAm, n, vals);
|
||||
#if ONLY_NATIVE_COMP
|
||||
for (usz i = 0; i < 100; i++) sc->vars[i+n] = bi_N;
|
||||
#endif
|
||||
return m_ns(sc, ptr_inc(desc->nsDesc));
|
||||
}
|
||||
|
||||
|
||||
392
src/opt/comp.c
Normal file
392
src/opt/comp.c
Normal file
@ -0,0 +1,392 @@
|
||||
#include "../nfns.h"
|
||||
#include "../vm.h"
|
||||
#include "../utils/mut.h"
|
||||
|
||||
B native_comp;
|
||||
|
||||
|
||||
|
||||
NOINLINE B nc_emptyI32Vec() {
|
||||
i32* rp;
|
||||
return m_i32arrv(&rp, 0);
|
||||
}
|
||||
B nc_ivec1(i32 a ) { i32* rp; B r = m_i32arrv(&rp, 1); rp[0]=a; return r; }
|
||||
B nc_ivec2(i32 a, i32 b ) { i32* rp; B r = m_i32arrv(&rp, 2); rp[0]=a; rp[1]=b; return r; }
|
||||
B nc_ivec3(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; }
|
||||
NOINLINE void nc_iadd(B* w, i32 x) { // consumes x
|
||||
*w = vec_add(*w, m_f64(x));
|
||||
}
|
||||
NOINLINE void nc_ijoin(B* w, B x) { // doesn't consume x
|
||||
SGetU(x)
|
||||
usz ia = IA(x);
|
||||
for (usz i = 0; i < ia; i++) nc_iadd(w, o2i(GetU(x, i)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define nc_equal equal
|
||||
NOINLINE void nc_add(B* w, B x) { // consumes x
|
||||
*w = vec_add(*w, x);
|
||||
}
|
||||
NOINLINE B nc_pop(B* wp) {
|
||||
B w = *wp;
|
||||
assert(isArr(w) && v(w)->refc==1 && IA(w)>0);
|
||||
B r = IGetU(w, a(w)->ia-1);
|
||||
a(w)->ia--;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NOINLINE B nc_literal(B val) {
|
||||
HArr_p r = m_harr0p(1);
|
||||
r.a[0] = val;
|
||||
arr_shAtm((Arr*)r.c);
|
||||
return r.b;
|
||||
}
|
||||
static bool nc_up(u32 c) { return (c>='A' & c<='Z'); }
|
||||
static bool nc_al(u32 c) { return (c>='a' & c<='z') | nc_up(c); }
|
||||
static bool nc_num(u32 c) { return (c>='0' & c<='9'); }
|
||||
B sys_c1(B, B);
|
||||
NOINLINE B nc_tokenize(B prims, B sysvs, u32* chars, usz len, bool* hasBlock) {
|
||||
B r = emptyHVec();
|
||||
usz i = 0;
|
||||
usz pi = USZ_MAX;
|
||||
while (i < len) {
|
||||
u32 c = chars[i++];
|
||||
if (i==pi) thrF("Native compiler: Tokenizer stuck on \\u%xi / %i", c, c);
|
||||
B val;
|
||||
if (c==U'∞') val = nc_literal(m_f64(1.0/0));
|
||||
else if (c==U'π') val = nc_literal(m_f64(3.141592653589793));
|
||||
else if (c=='@') val = nc_literal(m_c32(0));
|
||||
else if (c==' ') continue;
|
||||
else if (c=='{' | c=='}') continue; // ignoring braces for now
|
||||
else if (nc_num(c) | (c==U'¯')) {
|
||||
bool neg = c==U'¯';
|
||||
if (!neg) i--;
|
||||
f64 num = 0;
|
||||
while (nc_num(chars[i])) num = num*10 + (chars[i++]-'0');
|
||||
if (neg) num = -num;
|
||||
val = nc_literal(m_f64(num));
|
||||
} else if (c=='"') {
|
||||
usz i0 = i;
|
||||
while ('"'!=chars[i]) { i++; if (i>=len) thrM("Native compiler: Unclosed string literal"); }
|
||||
usz ia = i-i0;
|
||||
u32* vp; val = nc_literal(m_c32arrv(&vp, ia));
|
||||
memcpy(vp, chars+i0, ia*sizeof(u32));
|
||||
i++;
|
||||
} else if (c=='#') { // comments
|
||||
while (i<len && chars[i]!='\n') i++;
|
||||
val = m_c32(','); i++;
|
||||
} else if (c==U'𝕨' || c==U'𝕩') { // special names
|
||||
*hasBlock = true;
|
||||
val = m_hVec2(m_f64(3), m_c32vec((u32[1]){c}, 1));
|
||||
} else if (nc_al(c) || c==U'•') { // names
|
||||
bool sys = c==U'•';
|
||||
usz i0 = sys? i : i-1;
|
||||
while (nc_al(chars[i]) | nc_num(chars[i])) i++;
|
||||
usz ia = i-i0;
|
||||
u32* np; B name = m_c32arrv(&np, ia);
|
||||
for (usz j = 0; j < ia; j++) np[j] = chars[i0+j] + (nc_up(chars[i0+j])? 32 : 0);
|
||||
if (sys) {
|
||||
B sysRes = sys_c1(m_f64(0), m_hVec1(name));
|
||||
val = nc_literal(IGet(sysRes, 0)); // won't have the class the user entered but ¯\_(ツ)_/¯
|
||||
decG(sysRes);
|
||||
} else {
|
||||
val = m_hVec2(m_f64(nc_up(c)? 0 : 3), name);
|
||||
}
|
||||
} else if (c==U'⋄' | c==',' | c=='\n') { // separators
|
||||
val = m_c32(',');
|
||||
} else {
|
||||
// primitives
|
||||
u32* primRepr = U"+-×÷⋆√⌊⌈|¬∧∨<>≠=≤≥≡≢⊣⊢⥊∾≍⋈↑↓↕«»⌽⍉/⍋⍒⊏⊑⊐⊒∊⍷⊔!˙˜˘¨⌜⁼´˝`∘○⊸⟜⌾⊘◶⎉⚇⍟⎊";
|
||||
usz j = 0;
|
||||
while(primRepr[j]) {
|
||||
if (primRepr[j]==c) { val = nc_literal(IGet(prims, j)); goto add; }
|
||||
j++;
|
||||
}
|
||||
// syntax
|
||||
u32* basicChars = U"()⟨⟩←↩";
|
||||
while (*basicChars) {
|
||||
if (c==*basicChars) { val = m_c32(c); goto add; }
|
||||
basicChars++;
|
||||
}
|
||||
thrF("Native compiler: Can't tokenize \\u%xi / %i", c, c);
|
||||
}
|
||||
add:
|
||||
nc_add(&r, val);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
usz addObj(B* objs, B val) { // consumes val
|
||||
nc_add(objs, val);
|
||||
return IA(*objs)-1;
|
||||
}
|
||||
|
||||
i32 nc_ty(B x) {
|
||||
assert(o2iG(IGetU(x, 0))<10);
|
||||
return o2iG(IGetU(x, 0)); }
|
||||
|
||||
B nc_generate(B p1) { // consumes
|
||||
// printf("p1: "); printI(p1); putchar('\n');
|
||||
|
||||
usz p1ia = IA(p1);
|
||||
B listFinal;
|
||||
if (p1ia == 1) { // simple case of 1 element
|
||||
listFinal = p1;
|
||||
toFinal:;
|
||||
B elFinal = IGet(listFinal, 0);
|
||||
if(nc_ty(elFinal)>3) thrM("Native compiler: Unexpected assignment");
|
||||
decG(listFinal);
|
||||
return elFinal;
|
||||
}
|
||||
|
||||
// merge 1-modifiers
|
||||
SGetU(p1)
|
||||
B p2 = emptyHVec();
|
||||
{
|
||||
usz i = 0;
|
||||
while (i < p1ia) {
|
||||
B e = incG(GetU(p1, i));
|
||||
u8 e0t = nc_ty(e);
|
||||
usz j = i+1;
|
||||
if (e0t==4 || e0t==5) goto add;
|
||||
if (!(e0t==0 || e0t==3)) thrM("Native compiler: Unexpected type in expression");
|
||||
while (j<p1ia) {
|
||||
B e1 = GetU(p1, j);
|
||||
if (nc_ty(IGetU(p1,j))!=1) break;
|
||||
B bc = nc_emptyI32Vec();
|
||||
nc_ijoin(&bc, IGetU(e1, 1));
|
||||
nc_ijoin(&bc, IGetU(e, 1));
|
||||
nc_iadd(&bc, MD1C);
|
||||
decG(e);
|
||||
e = m_hVec2(m_f64(0), bc);
|
||||
j++;
|
||||
}
|
||||
|
||||
add: nc_add(&p2, e);
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
decG(p1);
|
||||
// printf("p2: "); printI(p2); putchar('\n');
|
||||
|
||||
// parse as either tacit or explicit
|
||||
SGetU(p2)
|
||||
usz p2ia = IA(p2);
|
||||
if (p2ia==1) { listFinal=p2; goto toFinal; }
|
||||
B e = incG(GetU(p2, p2ia-1));
|
||||
usz i = p2ia-1; // pointer to last used thing
|
||||
bool explicit = nc_ty(GetU(p2,p2ia-1)) == 3;
|
||||
|
||||
while(i>0) {
|
||||
B en1 = GetU(p2, i-1);
|
||||
u8 en1t = nc_ty(en1);
|
||||
// printf("e @ %d: ", i); printI(e); putchar('\n');
|
||||
|
||||
if (en1t==4 || en1t==5) { // assignment
|
||||
B bc = nc_emptyI32Vec();
|
||||
nc_ijoin(&bc, IGetU(e, 1));
|
||||
nc_ijoin(&bc, IGetU(en1, 1));
|
||||
nc_iadd(&bc, en1t==4? SETN : SETU);
|
||||
decG(e);
|
||||
e = m_hVec2(m_f64(explicit? 3 : 0), bc);
|
||||
i-= 1;
|
||||
continue;
|
||||
}
|
||||
if (en1t!=0) thrM("Native compiler: Expected but didn't get function");
|
||||
|
||||
if (i>=2) { // dyadic call, fork
|
||||
B en2 = GetU(p2, i-2);
|
||||
if (nc_ty(en2)==3 || (!explicit && nc_ty(en2)==0)) {
|
||||
B bc = nc_emptyI32Vec();
|
||||
nc_ijoin(&bc, IGetU(e, 1));
|
||||
nc_ijoin(&bc, IGetU(en1, 1));
|
||||
nc_ijoin(&bc, IGetU(en2, 1));
|
||||
nc_iadd(&bc, explicit? FN2O : TR3O);
|
||||
decG(e);
|
||||
e = m_hVec2(m_f64(explicit? 3 : 0), bc);
|
||||
i-= 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// monadic call, atop
|
||||
B bc = nc_emptyI32Vec();
|
||||
nc_ijoin(&bc, IGetU(e, 1));
|
||||
nc_ijoin(&bc, IGetU(en1, 1));
|
||||
nc_iadd(&bc, explicit? FN1O : TR2D);
|
||||
decG(e);
|
||||
e = m_hVec2(m_f64(explicit? 3 : 0), bc);
|
||||
i-= 1;
|
||||
}
|
||||
// printf("e: "); printI(e); putchar('\n');
|
||||
decG(p2);
|
||||
return e;
|
||||
}
|
||||
|
||||
u32 nc_var(B* vars, B name) { // doesn't consume
|
||||
B o = *vars;
|
||||
usz ia = IA(o);
|
||||
SGetU(o)
|
||||
for (usz i = 0; i < ia; i++) if (nc_equal(GetU(o, i), name)) return i;
|
||||
nc_add(vars, incG(name));
|
||||
return ia;
|
||||
}
|
||||
|
||||
B nc_parseStatements(B tokens, usz i0, usz* i1, u32 close, B* objs, B* vars) {
|
||||
SGetU(tokens)
|
||||
usz tia = IA(tokens);
|
||||
usz i = i0;
|
||||
|
||||
B statements = emptyHVec();
|
||||
B parts = emptyHVec(); // list of lists; first element indicates class: 0:fn; 1:md1; 2:md2; 3:arr; 4:v←; 5:v↩
|
||||
|
||||
while (true) {
|
||||
B ct;
|
||||
if (i==tia) ct = m_c32(0);
|
||||
else ct = GetU(tokens, i++);
|
||||
// printf("next token: "); printI(ct); putchar('\n');
|
||||
|
||||
if (isC32(ct)) {
|
||||
u32 ctc = o2cG(ct);
|
||||
if (ctc=='\0' || ctc==close || ctc==',') {
|
||||
if (IA(parts)>0) {
|
||||
nc_add(&statements, nc_generate(parts));
|
||||
parts = emptyHVec();
|
||||
}
|
||||
if (ctc==close) {
|
||||
decG(parts);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctc=='\0') thrM("Native compiler: Unclosed");
|
||||
if (close==U')') thrM("Native compiler: Multiple statements in parens");
|
||||
} else if (ctc=='(' || ctc==U'⟨') {
|
||||
usz iM;
|
||||
B res = nc_parseStatements(tokens, i, &iM, ctc=='('? ')' : U'⟩', objs, vars);
|
||||
i = iM;
|
||||
nc_add(&parts, res);
|
||||
} else thrF("Native compiler: Unexpected character token: %B", ct);
|
||||
} else if (isArr(ct)) {
|
||||
if (RNK(ct)==0) { // literal
|
||||
B val = IGetU(ct, 0);
|
||||
usz i = addObj(objs, inc(val));
|
||||
i32 type = isFun(val)? 0 : isMd1(val)? 1 : isMd2(val)? 2 : 3;
|
||||
nc_add(&parts, m_hVec2(m_f64(type), nc_ivec2(PUSH, i)));
|
||||
} else { // name
|
||||
u8 ty = nc_ty(ct);
|
||||
assert(ty<=3);
|
||||
if (i<tia) {
|
||||
B ct2 = GetU(tokens, i);
|
||||
if (isC32(ct2) && (o2cG(ct2)==U'←' || o2cG(ct2)==U'↩')) {
|
||||
ty = o2cG(ct2)==U'←'? 4 : 5;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
nc_add(&parts, m_hVec2(m_f64(ty), nc_ivec3(ty<=3? VARO : VARM, 0, nc_var(vars, IGetU(ct, 1)))));
|
||||
}
|
||||
} else thrF("Native compiler: Unexpected token %B", ct);
|
||||
}
|
||||
*i1 = i;
|
||||
|
||||
// merge statements
|
||||
SGetU(statements)
|
||||
B final = nc_emptyI32Vec();
|
||||
usz segAm = IA(statements);
|
||||
for (usz i = 0; i < segAm; i++) {
|
||||
B segment = GetU(statements, i);
|
||||
if (i && close!=U'⟩') nc_iadd(&final, POPS);
|
||||
nc_ijoin(&final, IGetU(segment, 1));
|
||||
}
|
||||
|
||||
u8 type0 = segAm==1? nc_ty(GetU(statements,0)) : 99;
|
||||
decG(statements);
|
||||
|
||||
u8 type;
|
||||
if (close=='\0' || close=='}') {
|
||||
nc_iadd(&final, RETN);
|
||||
type = 0;
|
||||
} else if (close==U'⟩') {
|
||||
nc_iadd(&final, LSTO);
|
||||
nc_iadd(&final, segAm);
|
||||
type = 3;
|
||||
} else if (close==')') {
|
||||
type = type0;
|
||||
} else thrM("bad closing");
|
||||
return m_hVec2(m_f64(type), final);
|
||||
}
|
||||
B nc_parseBlock(B tokens, usz i0, bool isBlock, B* objs, u32* varCount) { // returns bytecode
|
||||
usz i1;
|
||||
B vars = emptyHVec();
|
||||
if (isBlock) {
|
||||
nc_add(&vars, m_c32vec(U"𝕤", 1));
|
||||
nc_add(&vars, m_c32vec(U"𝕩", 1));
|
||||
nc_add(&vars, m_c32vec(U"𝕨", 1));
|
||||
}
|
||||
B r0 = nc_parseStatements(tokens, 0, &i1, '\0', objs, &vars);
|
||||
*varCount = IA(vars);
|
||||
decG(vars);
|
||||
if (i1 != IA(tokens)) thrM("Native compiler: Failed to parse");
|
||||
B r = IGet(r0, 1);
|
||||
decG(r0);
|
||||
return r;
|
||||
}
|
||||
|
||||
B nativeComp_c2(B t, B w, B x) {
|
||||
SGetU(w)
|
||||
B prims = GetU(w,0);
|
||||
B sysvs = GetU(w,1);
|
||||
bool isBlock = false;
|
||||
|
||||
// tokenize
|
||||
usz xia = IA(x);
|
||||
u32* xBuf; B xBufO = m_c32arrv(&xBuf, xia+1);
|
||||
SGetU(x)
|
||||
for (usz i = 0; i < xia; i++) xBuf[i] = o2c(GetU(x, i));
|
||||
xBuf[xia] = 0;
|
||||
B tokenized = nc_tokenize(prims, sysvs, xBuf, xia, &isBlock);
|
||||
decG(xBufO);
|
||||
|
||||
// // parse
|
||||
B objs = emptyHVec();
|
||||
i32* bc0;
|
||||
B bytecode = m_i32arrv(&bc0, isBlock? 3 : 0);
|
||||
if (isBlock) {
|
||||
bc0[0] = DFND;
|
||||
bc0[1] = 1;
|
||||
bc0[2] = RETN;
|
||||
}
|
||||
u32 varCount;
|
||||
B bc1 = nc_parseBlock(tokenized, 0, isBlock, &objs, &varCount);
|
||||
nc_ijoin(&bytecode, bc1);
|
||||
decG(bc1);
|
||||
decG(tokenized);
|
||||
|
||||
// build result
|
||||
B res;
|
||||
if (isBlock) {
|
||||
res = m_hVec4(
|
||||
bytecode,
|
||||
objs,
|
||||
m_hVec2(nc_ivec3(0, 1, 0), nc_ivec3(0, 0, 1)),
|
||||
m_hVec2(nc_ivec2(0, 0), nc_ivec2(3, varCount))
|
||||
);
|
||||
} else {
|
||||
res = m_hVec4(
|
||||
bytecode,
|
||||
objs,
|
||||
m_hVec1(nc_ivec3(0, 1, 0)),
|
||||
m_hVec1(nc_ivec2(0, varCount))
|
||||
);
|
||||
}
|
||||
|
||||
decG(w); decG(x);
|
||||
return res;
|
||||
}
|
||||
|
||||
void nativeCompiler_init() {
|
||||
native_comp = m_nfn(registerNFn(m_c8vec("(native compiler)", 17), c1_bad, nativeComp_c2), bi_N);
|
||||
gc_add(native_comp);
|
||||
}
|
||||
6
src/vm.c
6
src/vm.c
@ -82,6 +82,9 @@ void print_gStack() {
|
||||
}
|
||||
|
||||
B listVars(Scope* sc) {
|
||||
#if ONLY_NATIVE_COMP
|
||||
return emptyHVec();
|
||||
#endif
|
||||
Body* b = sc->body;
|
||||
if (b==NULL) return bi_N;
|
||||
|
||||
@ -259,6 +262,7 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl
|
||||
while (*c!=RETN & *c!=RETD) {
|
||||
if (*c==PRED) { remapArgs = true; break; }
|
||||
c = nextBC(c);
|
||||
if (c-bc-1 >= bcIA) thrM("VM compiler: No RETN/RETD found before end of bytecode");
|
||||
}
|
||||
if (remapArgs) {
|
||||
if (sc && depth==0) thrM("Predicates cannot be used directly in a REPL");
|
||||
@ -267,6 +271,7 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl
|
||||
while (*c!=RETN & *c!=RETD) {
|
||||
if (*c==VARO | *c==VARM | *c==VARU) if (c[1]==0 && c[2]<argAm) argUsed[c[2]] = true;
|
||||
c = nextBC(c);
|
||||
if (c-bc-1 >= bcIA) thrM("VM compiler: No RETN/RETD found before end of bytecode");
|
||||
}
|
||||
for (i32 i = 0; i < 6; i++) if (argUsed[i]) {
|
||||
TSADDA(newBC, ((u32[]){ VARO,0,i, VARM,0,vam+i, SETN, POPS }), 8);
|
||||
@ -277,7 +282,6 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl
|
||||
c = bc+idx;
|
||||
while (true) {
|
||||
u32* n = nextBC(c);
|
||||
if (n-bc-1 >= bcIA) thrM("VM compiler: No RETN/RETD found before end of bytecode");
|
||||
bool ret = false;
|
||||
#define A64(X) { u64 a64=(X); TSADD(newBC, (u32)a64); TSADD(newBC, a64>>32); }
|
||||
switch (*c) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user