diff --git a/minproto.leg b/minproto.leg index 20867bd..2b4713f 100644 --- a/minproto.leg +++ b/minproto.leg @@ -1,6 +1,6 @@ # minproto.leg -- minimal prototype langauge for semantic experiments # -# last edited: 2024-06-20 02:30:46 by piumarta on m1mbp +# last edited: 2024-06-20 03:14:11 by piumarta on m1mbp %{ ; @@ -4852,7 +4852,8 @@ vmInsn *vmCompile(oop grammar, oop symbol) oop *prog = _get(program, Object,indexed); int plen = _get(program, Object,isize); if (plen % 5 != 0) valueError("__match__", "program length is not a multiple of five", program); - vmInsn *code = calloc(plen / 5, sizeof(*code)); + int clen = plen / 5; + vmInsn *code = calloc(clen, sizeof(*code)); vmCachePut(grammar, symbol, code); oop env = nil; int ppc = 0; @@ -4863,11 +4864,14 @@ vmInsn *vmCompile(oop grammar, oop symbol) int arglen = integerValue(prog[ppc++], "__match__"); int ok = integerValue(prog[ppc++], "__match__"); int ko = integerValue(prog[ppc++], "__match__"); + if (ok < 0 || ok >= clen) valueError("__match__", "OK destination out of range", program); + if (ko < 0 || ko >= clen) valueError("__match__", "KO destination out of range", program); code[cpc] = (vmInsn){ .arg.obj = arg, .op = op, .arglen = arglen, .ok = ok, .ko = ko }; switch (op) { case CLASS: case STRING: { - code[cpc].arg.str = stringValue(code[cpc].arg.obj, "__match__"); + code[cpc].arglen = stringLength(code[cpc].arg.obj, "__match__"); + code[cpc].arg.str = stringValue (code[cpc].arg.obj, "__match__"); break; } case RULE: { @@ -4875,15 +4879,15 @@ vmInsn *vmCompile(oop grammar, oop symbol) break; } case CALL: { - valueError("__match__", "program contains CALL opcode", program); + valueError("__match__", "program contains explicit CALL opcode", program); break; } case ACTION: { - if (!isClosure(code[cpc].arg.obj)) valueError("__match__", "ACTION argument is not a function", program); + if (!isClosure(code[cpc].arg.obj)) valueError("__match__", "ACTION argument must be a closure", program); break; } case SET: { - if (!is(Symbol, code[cpc].arg.obj)) valueError("__match__", "SET argument is not a symbol", program); + if (!is(Symbol, code[cpc].arg.obj)) valueError("__match__", "SET argument must be a symbol", program); if (nil == env) env = new(pObject); Object_put(env, code[cpc].arg.obj, nil); break; @@ -4894,10 +4898,6 @@ vmInsn *vmCompile(oop grammar, oop symbol) } ++cpc; } -#if 0 - if (!cpc || code[0].op != ENTER) valueError("__match__", "program does not begin with ENTER", program); - code[0].arg.obj = env; // clone this to make a list of local variables for the rule -#endif if (opt_d) { printf("---- BEGIN "); println(symbol, 0); @@ -5098,7 +5098,7 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) continue; } default: { - fatal("this cannot happen"); + fatal("this cannot happen %d", i->op); break; } }