diff --git a/src/opt/comp.c b/src/opt/comp.c index d3ea0235..ebd9e1dc 100644 --- a/src/opt/comp.c +++ b/src/opt/comp.c @@ -1,6 +1,11 @@ #include "../nfns.h" #include "../vm.h" #include "../utils/mut.h" +// minimal compiler, capable of running mlochbaum/BQN/src/bootstrap/boot2.bqn +// supports •-values, 1-modifiers, value and function class variables +// input must be either an immediate expression, or a block potentially containing 𝕨 or 𝕩 +// goal is to either error, or compile correctly + B native_comp; @@ -69,10 +74,10 @@ NOINLINE B nc_tokenize(B prims, B sysvs, u32* chars, usz len, bool* hasBlock) { 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--; + else if (!nc_num(chars[i])) thrM("Native compiler: Standalone negative sign"); f64 num = 0; while (nc_num(chars[i])) num = num*10 + (chars[i++]-'0'); if (neg) num = -num; @@ -115,7 +120,7 @@ NOINLINE B nc_tokenize(B prims, B sysvs, u32* chars, usz len, bool* hasBlock) { j++; } // syntax - u32* basicChars = U"()⟨⟩←↩"; + u32* basicChars = U"()⟨⟩←↩{}"; while (*basicChars) { if (c==*basicChars) { val = m_c32(c); goto add; } basicChars++; @@ -185,7 +190,8 @@ B nc_generate(B p1) { // consumes 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; + u8 tyE = nc_ty(GetU(p2,p2ia-1)); + bool explicit = tyE==3; while(i>0) { B en1 = GetU(p2, i-1); @@ -193,9 +199,11 @@ B nc_generate(B p1) { // consumes // printf("e @ %d: ", i); printI(e); putchar('\n'); if (en1t==4 || en1t==5) { // assignment + if (!explicit && i!=1) thrM("Native compiler: Assignment in the middle of tacit code"); B bc = nc_emptyI32Vec(); nc_ijoin(&bc, IGetU(e, 1)); nc_ijoin(&bc, IGetU(en1, 1)); + if (tyE != o2iG(IGetU(en1, 2))) thrM("Native compiler: Wrong assignment class"); nc_iadd(&bc, en1t==4? SETN : SETU); decG(e); e = m_hVec2(m_f64(explicit? 3 : 0), bc); @@ -287,7 +295,11 @@ B nc_parseStatements(B tokens, usz i0, usz* i1, u32 close, B* objs, Vars vars) { 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 (ctc==U'{' || ctc==U'}') { + thrM("Native compiler: Nested blocks aren't supported"); + } else if (ctc==U'←' || ctc==U'↩') { + thrM("Native compiler: Invalid assignment"); + } else thrF("Native compiler: Unexpected character token \\u%xi / %i", ctc, ctc); } else if (isArr(ct)) { if (RNK(ct)==0) { // literal B val = IGetU(ct, 0); @@ -296,15 +308,16 @@ B nc_parseStatements(B tokens, usz i0, usz* i1, u32 close, B* objs, Vars vars) { nc_add(&parts, m_hVec2(m_f64(type), nc_ivec2(PUSH, i))); } else { // name u8 ty = nc_ty(ct); + u8 rty = ty; assert(ty<=3); if (ipop; free_b2i(vars0); @@ -357,7 +376,8 @@ B nc_parseBlock(B tokens, usz i0, bool isBlock, B* objs, u32* varCount) { // ret *varCount = IA(vars0); decG(vars0); #endif - if (i1 != IA(tokens)) thrM("Native compiler: Failed to parse"); + i1 = nc_skipSeparators(tokens, i1); + if (i1 != IA(tokens)) thrM("Native compiler: Code present after block end"); B r = IGet(r0, 1); decG(r0); return r; @@ -367,7 +387,7 @@ B nativeComp_c2(B t, B w, B x) { SGetU(w) B prims = GetU(w,0); B sysvs = GetU(w,1); - bool isBlock = false; + bool fnBlock = false; // tokenize usz xia = IA(x); @@ -375,27 +395,31 @@ B nativeComp_c2(B t, B w, B x) { 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); + B tokens = nc_tokenize(prims, sysvs, xBuf, xia, &fnBlock); decG(xBufO); // // parse B objs = emptyHVec(); i32* bc0; - B bytecode = m_i32arrv(&bc0, isBlock? 3 : 0); - if (isBlock) { + B bytecode = m_i32arrv(&bc0, fnBlock? 3 : 0); + usz i0 = nc_skipSeparators(tokens, 0); + bool anyBlock = i0