native minimal compiler

This commit is contained in:
dzaima 2023-01-26 00:45:39 +02:00
parent e231d36471
commit 9abe7506ab
7 changed files with 498 additions and 40 deletions

View File

@ -492,7 +492,7 @@ AddRule ← { 𝕊 cache‿cacheKey‿dst‿GetCMD‿disp‿deps:
cacheKey cacheKey cacheKey cacheKey
found0 0 found0 0
SetFound {found0𝕩} 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 @ found1 @
SetVal {found1 𝕩DepHash@} SetVal {found1 𝕩DepHash@}
disp disp disp disp

View File

@ -279,7 +279,18 @@ B eequal_c2(B t, B w, B x) {
#ifdef TEST_BITCPY #ifdef TEST_BITCPY
#include "../utils/mut.h" #include "../utils/mut.h"
#endif #endif
#if NATIVE_COMPILER
extern B native_comp;
void switchComp(void);
#endif
B internalTemp_c1(B t, B x) { 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 #ifdef TEST_BITCPY
SGetU(x) 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))); 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" #include "../utils/calls.h"
#endif #endif
B internalTemp_c2(B t, B w, B x) { B internalTemp_c2(B t, B w, B x) {
#if NATIVE_COMPILER
return c2(native_comp, w, x);
#endif
#ifdef TEST_MUT #ifdef TEST_MUT
SGetU(x) SGetU(x)
FILL_TO(tyarr_ptr(w), o2s(GetU(x,0)), o2s(GetU(x,1)), GetU(x,2), o2s(GetU(x,3))); FILL_TO(tyarr_ptr(w), o2s(GetU(x,0)), o2s(GetU(x,1)), GetU(x,2), o2s(GetU(x,3)));
dec(w); dec(w);
#endif #endif
return x; return x;
} }

View File

@ -118,7 +118,10 @@ Block* load_compObj(B x, B src, B path, Scope* sc) { // consumes x,src
return r; return r;
} }
#if !(ONLY_NATIVE_COMP && !FORMATTER && NO_RT && NO_EXPLAIN)
#include PRECOMPILED_FILE(src) #include PRECOMPILED_FILE(src)
#endif
#if RT_SRC #if RT_SRC
Block* load_compImport(char* name, B bc, B objs, B blocks, B bodies, B inds, B src) { // consumes all 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); 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_glyphs;
B load_explain; 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 #if FORMATTER
B load_fmt, load_repr; B load_fmt, load_repr;
B bqn_fmt(B x) { // consumes B bqn_fmt(B x) { // consumes
@ -414,15 +426,15 @@ void load_init() { // very last init function
HArr_p runtimeH = m_harrUc(rtObjRaw); HArr_p runtimeH = m_harrUc(rtObjRaw);
SGet(rtObjRaw) SGet(rtObjRaw)
rt_undo = Get(rtObjRaw, n_undo ); gc_add(rt_undo); rt_undo = Get(rtObjRaw, n_undo );
rt_select = Get(rtObjRaw, n_select ); gc_add(rt_select); rt_select = Get(rtObjRaw, n_select );
rt_slash = Get(rtObjRaw, n_slash ); gc_add(rt_slash); rt_slash = Get(rtObjRaw, n_slash );
rt_group = Get(rtObjRaw, n_group ); gc_add(rt_group); rt_group = Get(rtObjRaw, n_group );
rt_under = Get(rtObjRaw, n_under ); gc_add(rt_under); rt_under = Get(rtObjRaw, n_under );
rt_find = Get(rtObjRaw, n_find ); gc_add(rt_find); rt_find = Get(rtObjRaw, n_find );
rt_transp = Get(rtObjRaw, n_transp ); gc_add(rt_transp); rt_transp = Get(rtObjRaw, n_transp );
rt_depth = Get(rtObjRaw, n_depth ); gc_add(rt_depth); rt_depth = Get(rtObjRaw, n_depth );
rt_insert = Get(rtObjRaw, n_insert ); gc_add(rt_insert); rt_insert = Get(rtObjRaw, n_insert );
for (usz i = 0; i < rtLen; i++) { for (usz i = 0; i < rtLen; i++) {
#ifdef RT_WRAP #ifdef RT_WRAP
@ -461,14 +473,22 @@ void load_init() { // very last init function
if (isVal(r)) v(r)->flags|= i+1; if (isVal(r)) v(r)->flags|= i+1;
} }
load_rtObj = frtObj; load_rtObj = frtObj;
load_compArg = m_hVec2(load_rtObj, incG(bi_sys)); gc_add(frtObj); load_compArg = m_hVec2(load_rtObj, incG(bi_sys));
rt_select=rt_slash=rt_group=rt_find=rt_transp=rt_invFnReg=rt_invFnSwap = bi_invalidFn; rt_select=rt_slash=rt_group=rt_find=rt_transp=rt_invFnReg=rt_invFnSwap = incByG(bi_invalidFn, 7);
rt_undo=rt_insert = bi_invalidMd1; rt_undo=rt_insert = incByG(bi_invalidMd1, 2);
rt_under=rt_depth = bi_invalidMd2; rt_under=rt_depth = incByG(bi_invalidMd2, 2);
rt_invFnRegFn=rt_invFnSwapFn = invalidFn_c1; rt_invFnRegFn=rt_invFnSwapFn = invalidFn_c1;
#endif #endif
gc_add(load_compArg); 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(); print_allocStats();
exit(0); exit(0);
#else // use compiler #else // use compiler
B prevAsrt = runtime[n_asrt]; load_glyphs = m_hVec3(m_c32vec_0(U"+-×÷⋆√⌊⌈|¬∧∨<>≠=≤≥≡≢⊣⊢⥊∾≍⋈↑↓↕«»⌽⍉/⍋⍒⊏⊑⊐⊒∊⍷⊔!"), m_c32vec_0(U"˙˜˘¨⌜⁼´˝`"), m_c32vec_0(U"∘○⊸⟜⌾⊘◶⎉⚇⍟⎊")); gc_add(load_glyphs);
runtime[n_asrt] = bi_casrt; // horrible but GC is off so it's fiiiiiine
Block* comp_b = load_compImport("(compiler)", #if !ONLY_NATIVE_COMP
#include PRECOMPILED_FILE(compiles) B prevAsrt = runtime[n_asrt];
); runtime[n_asrt] = bi_casrt; // horrible but GC is off so it's fiiiiiine
runtime[n_asrt] = prevAsrt; Block* comp_b = load_compImport("(compiler)",
load_glyphs = m_hVec3(m_c32vec_0(U"+-×÷⋆√⌊⌈|¬∧∨<>≠=≤≥≡≢⊣⊢⥊∾≍⋈↑↓↕«»⌽⍉/⍋⍒⊏⊑⊐⊒∊⍷⊔!"), m_c32vec_0(U"˙˜˘¨⌜⁼´˝`"), m_c32vec_0(U"∘○⊸⟜⌾⊘◶⎉⚇⍟⎊")); #include PRECOMPILED_FILE(compiles)
load_compgen = evalFunBlock(comp_b, 0); ptr_dec(comp_b); );
load_comp = c1(load_compgen, inc(load_glyphs)); runtime[n_asrt] = prevAsrt;
gc_add(load_compgen); gc_add(load_comp); gc_add(load_glyphs); 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 #if FORMATTER
Block* fmt_b = load_compImport("(formatter)", Block* fmt_b = load_compImport("(formatter)",
#include PRECOMPILED_FILE(formatter) #include PRECOMPILED_FILE(formatter)
); );
B fmtM = evalFunBlock(fmt_b, 0); ptr_dec(fmt_b); 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)})); B fmtR = c1(fmtM, m_caB(4, (B[]){incG(bi_type), incG(bi_decp), incG(bi_glyph), incG(bi_repr)}));
decG(fmtM); decG(fmtM);
SGet(fmtR) SGet(fmtR)
load_fmt = Get(fmtR, 0); gc_add(load_fmt); load_fmt = Get(fmtR, 0); gc_add(load_fmt);
load_repr = Get(fmtR, 1); gc_add(load_repr); load_repr = Get(fmtR, 1); gc_add(load_repr);
decG(fmtR); decG(fmtR);
#endif #endif
gc_enable(); gc_enable();
@ -754,6 +780,12 @@ void typesFinished_init() {
for (u64 i = 0; i < t_COUNT; i++) { for (u64 i = 0; i < t_COUNT; i++) {
if (TIi(i,freeT) == def_fallbackTriv) TIi(i,freeT) = TIi(i,freeF); 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; bool cbqn_initialized;

View File

@ -489,6 +489,10 @@ void profiler_free(void);
void profiler_displayResults(void); void profiler_displayResults(void);
void clearImportCache(void); void clearImportCache(void);
#if NATIVE_COMPILER && !ONLY_NATIVE_COMP
void switchComp(void);
#endif
static B escape_parser; static B escape_parser;
static B simple_unescape(B x) { static B simple_unescape(B x) {
if (RARE(escape_parser.u==0)) { if (RARE(escape_parser.u==0)) {
@ -654,6 +658,11 @@ void cbqn_runLine0(char* ln, i64 read) {
} else if (isCmd(cmdS, &cmdE, "internalPrint ")) { } else if (isCmd(cmdS, &cmdE, "internalPrint ")) {
code = utf8Decode0(cmdE); code = utf8Decode0(cmdE);
output = 2; 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 ")) { } else if (isCmd(cmdS, &cmdE, "e ") || isCmd(cmdS, &cmdE, "explain ")) {
B expl = bqn_explain(utf8Decode0(cmdE), replPath); B expl = bqn_explain(utf8Decode0(cmdE), replPath);
HArr* expla = toHArr(expl); HArr* expla = toHArr(expl);

View File

@ -140,7 +140,14 @@ Body* m_nnsDescF(i32 n, char** names) {
B m_nnsF(Body* desc, i32 n, B* vals) { B m_nnsF(Body* desc, i32 n, B* vals) {
assert(n == desc->varAm); 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)); return m_ns(sc, ptr_inc(desc->nsDesc));
} }

392
src/opt/comp.c Normal file
View 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);
}

View File

@ -82,6 +82,9 @@ void print_gStack() {
} }
B listVars(Scope* sc) { B listVars(Scope* sc) {
#if ONLY_NATIVE_COMP
return emptyHVec();
#endif
Body* b = sc->body; Body* b = sc->body;
if (b==NULL) return bi_N; 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) { while (*c!=RETN & *c!=RETD) {
if (*c==PRED) { remapArgs = true; break; } if (*c==PRED) { remapArgs = true; break; }
c = nextBC(c); c = nextBC(c);
if (c-bc-1 >= bcIA) thrM("VM compiler: No RETN/RETD found before end of bytecode");
} }
if (remapArgs) { if (remapArgs) {
if (sc && depth==0) thrM("Predicates cannot be used directly in a REPL"); 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) { while (*c!=RETN & *c!=RETD) {
if (*c==VARO | *c==VARM | *c==VARU) if (c[1]==0 && c[2]<argAm) argUsed[c[2]] = true; if (*c==VARO | *c==VARM | *c==VARU) if (c[1]==0 && c[2]<argAm) argUsed[c[2]] = true;
c = nextBC(c); 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]) { for (i32 i = 0; i < 6; i++) if (argUsed[i]) {
TSADDA(newBC, ((u32[]){ VARO,0,i, VARM,0,vam+i, SETN, POPS }), 8); 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; c = bc+idx;
while (true) { while (true) {
u32* n = nextBC(c); u32* n = nextBC(c);
if (n-bc-1 >= bcIA) thrM("VM compiler: No RETN/RETD found before end of bytecode");
bool ret = false; bool ret = false;
#define A64(X) { u64 a64=(X); TSADD(newBC, (u32)a64); TSADD(newBC, a64>>32); } #define A64(X) { u64 a64=(X); TSADD(newBC, (u32)a64); TSADD(newBC, a64>>32); }
switch (*c) { switch (*c) {