diff --git a/minproto.leg b/minproto.leg index b10d7ec..882c1b8 100644 --- a/minproto.leg +++ b/minproto.leg @@ -1,6 +1,6 @@ # minproto.leg -- minimal prototype langauge for semantic experiments # -# last edited: 2024-06-20 13:22:50 by piumarta on m1mbp +# last edited: 2024-07-04 10:07:00 by piumarta on zora %{ ; @@ -387,10 +387,11 @@ oop String_append(oop str, int c) { int length = get(str, String,length); char *value = get(str, String,value); - value = xrealloc(value, length + 1); - set(str, String,value, value); + char *copy = xmalloc(length + 1); + memcpy(copy, value, length); + set(str, String,value, copy); set(str, String,length, length+1); - value[length] = c; + copy[length] = c; return str; } @@ -399,9 +400,10 @@ oop String_appendAllLen(oop str, char *s, int len) if (len < 1) return str; int length = get(str, String,length); char *value = get(str, String,value); - value = xrealloc(value, length + len); - memcpy(value + length, s, len); - set(str, String,value, value); + char *copy = xmalloc(length + len); + memcpy(copy, value, length); + memcpy(copy + length, s, len); + set(str, String,value, copy); set(str, String,length, length+len); return str; } @@ -422,7 +424,9 @@ oop String_format(oop str, char *fmt, ...) int length = get(str, String,length); char *value = get(str, String,value); for (;;) { - value = xrealloc(value, length + cap); + char *orig = value; + value = xmalloc(length + cap); + memcpy(value, orig, length); va_list ap; va_start(ap, fmt); len = vsnprintf(value + length, cap, fmt, ap); @@ -767,7 +771,7 @@ char *storeString(oop obj, int indent); oop *Object_ref(oop obj, oop key) { - oop o; + oop o = nil; switch (getType(obj)) { case Undefined: o = pUndefined; break; case Integer: o = pInteger; break; @@ -810,7 +814,7 @@ oop *Object_ref(oop obj, oop key) oop Object_getOwner(oop obj, oop key, oop *ownerp) { - oop o; + oop o = nil; switch (getType(obj)) { case Undefined: o = pUndefined; break; case Integer: o = pInteger; break; @@ -853,7 +857,7 @@ oop Object_getOwner(oop obj, oop key, oop *ownerp) oop Object_get(oop obj, oop key) { - oop o; + oop o = nil; switch (getType(obj)) { case Undefined: o = pUndefined; break; case Integer: o = pInteger; break; @@ -4763,12 +4767,12 @@ oop applyThunkIn(oop func, oop env) typedef unsigned char byte; typedef enum op_t { - PUSH, DROP, POP, DOT, CLASS, STRING, RULE, CALL, + PUSH, DROP, POP, DOT, CLASS, STRING, TEST, RULE2, RULE, CALL, SUCCEED, FAIL, ACTION, BEGIN, END, UNEND, SET, } op_t; char *op_n[] = { - "PUSH", "DROP", "POP", "DOT", "CLASS", "STRING", "RULE", "CALL", + "PUSH", "DROP", "POP", "DOT", "CLASS", "STRING", "TEST", "RULE2", "RULE", "CALL", "SUCCEED", "FAIL", "ACTION", "BEGIN", "END", "UNEND", "SET", }; @@ -4779,8 +4783,9 @@ struct vmInsn { char *str; oop obj; vmInsn *code; - } arg; - unsigned short op, arglen, ok, ko; + int len; + } arg, arg2; + unsigned short op, ok, ko; }; typedef struct vmState @@ -4824,15 +4829,15 @@ void vmDisassemble(vmInsn *code, int pc) case CLASS: case STRING: printf("%03d %-7s \"%s\" %2d %2d %2d\n", - pc, op_n[i->op], i->arg.str, i->arglen, i->ok, i->ko); + pc, op_n[i->op], i->arg.str, i->arg2.len, i->ok, i->ko); break; case CALL: printf("%03d %-7s %p %2d %2d %2d\n", - pc, op_n[i->op], i->arg.code, i->arglen, i->ok, i->ko); + pc, op_n[i->op], i->arg.code, i->arg2.len, i->ok, i->ko); break; default: printf("%03d %-7s %s %2d %2d %2d\n", - pc, op_n[i->op], codeString(i->arg.obj, 0), i->arglen, i->ok, i->ko); + pc, op_n[i->op], codeString(i->arg.obj, 0), i->arg2.len, i->ok, i->ko); break; } } @@ -4867,18 +4872,27 @@ vmInsn *vmCompile(oop grammar, oop symbol) int cpc = 0; while (ppc < plen) { int op = integerValue(prog[ppc++], "__match__"); - oop arg = prog[ppc++]; - int arglen = integerValue(prog[ppc++], "__match__"); + oop arg = prog[ppc++]; assert(arg); + oop arg2 = prog[ppc++]; assert(arg2); 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 }; + code[cpc] = (vmInsn){ .arg.obj = arg, .arg2.obj = arg2, .op = op, .ok = ok, .ko = ko }; switch (op) { case CLASS: case STRING: { - code[cpc].arglen = stringLength(code[cpc].arg.obj, "__match__"); - code[cpc].arg.str = stringValue (code[cpc].arg.obj, "__match__"); + code[cpc].arg2.len = stringLength(code[cpc].arg.obj, "__match__"); + code[cpc].arg.str = stringValue (code[cpc].arg.obj, "__match__"); + break; + } + case TEST: { + if (!isClosure(code[cpc].arg.obj)) valueError("__match__", "TEST argument must be a closure", program); + break; + } + case RULE2: { + if (!is(Symbol, code[cpc].arg.obj )) valueError("__match__", "RULE2 argument must be a symbol", program); + if (!is(Object, code[cpc].arg2.obj)) valueError("__match__", "RULE2 argument2 must be an object", program); break; } case RULE: { @@ -4952,6 +4966,7 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) context.nactions = 0; vmState state = VM_STATE_INITIALISER; + state.variables = new(pObject); # define saveAction(ACT, OBJ, BEG, LEN) { \ if (context.nactions >= maxactions) \ @@ -4973,7 +4988,6 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) frame.pc = 0; frame.nactions = context.nactions; - int textbeg = 0, textend = 0; int result = 0; @@ -5021,9 +5035,9 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) continue; } case STRING: { - if (context.position + i->arglen <= length) { - if (0 == memcmp(text + context.position, i->arg.str, i->arglen)) { - context.position += i->arglen; + if (context.position + i->arg2.len <= length) { + if (0 == memcmp(text + context.position, i->arg.str, i->arg2.len)) { + context.position += i->arg2.len; frame.pc = i->ok; continue; } @@ -5031,6 +5045,16 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) frame.pc = i->ko; continue; } + case TEST: { + oop result = apply(i->arg.obj, nil, new(pObject), nil, nil); + frame.pc = (nil == result) ? i->ko : i->ok; + continue; + } + case RULE2: { + i->op = CALL; + i->arg.code = vmCacheGet(i->arg2.obj, i->arg.obj); + goto doCall; + } case RULE: { // frame.pc--; // save pc of call insn // push(r, frame); @@ -5073,11 +5097,15 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) } case FAIL: { if (rsp) { + context.nactions = frame.nactions - 1; // remove all actions added by this rule frame = pop(r); i = frame.code + frame.pc; frame.pc = i->ko; continue; } + else { + context.nactions = 0; + } result = -1; break; }