@ -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;
}