Kaynağa Gözat

String_append(), _appendAll(), and _format() allocate new memory to allow raw pointers to old content to persist. Add PEG operations TEST (fail if function returns false) and RULE2 (call rule in other grammar). PEG instruction's second operand is object not integer. Initialise top level state.variables with empty object in vmRun(). PEG instruction FAIL removes all actions added by its rule.

master
Ian Piumarta 10 ay önce
ebeveyn
işleme
4065107170
1 değiştirilmiş dosya ile 55 ekleme ve 27 silme
  1. +55
    -27
      minproto.leg

+ 55
- 27
minproto.leg Dosyayı Görüntüle

@ -1,6 +1,6 @@
# minproto.leg -- minimal prototype langauge for semantic experiments # 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); int length = get(str, String,length);
char *value = get(str, String,value); 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); set(str, String,length, length+1);
value[length] = c;
copy[length] = c;
return str; return str;
} }
@ -399,9 +400,10 @@ oop String_appendAllLen(oop str, char *s, int len)
if (len < 1) return str; if (len < 1) return str;
int length = get(str, String,length); int length = get(str, String,length);
char *value = get(str, String,value); 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); set(str, String,length, length+len);
return str; return str;
} }
@ -422,7 +424,9 @@ oop String_format(oop str, char *fmt, ...)
int length = get(str, String,length); int length = get(str, String,length);
char *value = get(str, String,value); char *value = get(str, String,value);
for (;;) { for (;;) {
value = xrealloc(value, length + cap);
char *orig = value;
value = xmalloc(length + cap);
memcpy(value, orig, length);
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
len = vsnprintf(value + length, cap, fmt, ap); 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 *Object_ref(oop obj, oop key)
{ {
oop o;
oop o = nil;
switch (getType(obj)) { switch (getType(obj)) {
case Undefined: o = pUndefined; break; case Undefined: o = pUndefined; break;
case Integer: o = pInteger; 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 Object_getOwner(oop obj, oop key, oop *ownerp)
{ {
oop o;
oop o = nil;
switch (getType(obj)) { switch (getType(obj)) {
case Undefined: o = pUndefined; break; case Undefined: o = pUndefined; break;
case Integer: o = pInteger; 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 Object_get(oop obj, oop key)
{ {
oop o;
oop o = nil;
switch (getType(obj)) { switch (getType(obj)) {
case Undefined: o = pUndefined; break; case Undefined: o = pUndefined; break;
case Integer: o = pInteger; break; case Integer: o = pInteger; break;
@ -4763,12 +4767,12 @@ oop applyThunkIn(oop func, oop env)
typedef unsigned char byte; typedef unsigned char byte;
typedef enum op_t { 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, SUCCEED, FAIL, ACTION, BEGIN, END, UNEND, SET,
} op_t; } op_t;
char *op_n[] = { 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", "SUCCEED", "FAIL", "ACTION", "BEGIN", "END", "UNEND", "SET",
}; };
@ -4779,8 +4783,9 @@ struct vmInsn {
char *str; char *str;
oop obj; oop obj;
vmInsn *code; vmInsn *code;
} arg;
unsigned short op, arglen, ok, ko;
int len;
} arg, arg2;
unsigned short op, ok, ko;
}; };
typedef struct vmState typedef struct vmState
@ -4824,15 +4829,15 @@ void vmDisassemble(vmInsn *code, int pc)
case CLASS: case CLASS:
case STRING: case STRING:
printf("%03d %-7s \"%s\" %2d %2d %2d\n", 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; break;
case CALL: case CALL:
printf("%03d %-7s %p %2d %2d %2d\n", 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; break;
default: default:
printf("%03d %-7s %s %2d %2d %2d\n", 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; break;
} }
} }
@ -4867,18 +4872,27 @@ vmInsn *vmCompile(oop grammar, oop symbol)
int cpc = 0; int cpc = 0;
while (ppc < plen) { while (ppc < plen) {
int op = integerValue(prog[ppc++], "__match__"); 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 ok = integerValue(prog[ppc++], "__match__");
int ko = integerValue(prog[ppc++], "__match__"); int ko = integerValue(prog[ppc++], "__match__");
if (ok < 0 || ok >= clen) valueError("__match__", "OK destination out of range", program); 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); 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) { switch (op) {
case CLASS: case CLASS:
case STRING: { 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; break;
} }
case RULE: { case RULE: {
@ -4952,6 +4966,7 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
context.nactions = 0; context.nactions = 0;
vmState state = VM_STATE_INITIALISER; vmState state = VM_STATE_INITIALISER;
state.variables = new(pObject);
# define saveAction(ACT, OBJ, BEG, LEN) { \ # define saveAction(ACT, OBJ, BEG, LEN) { \
if (context.nactions >= maxactions) \ if (context.nactions >= maxactions) \
@ -4973,7 +4988,6 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
frame.pc = 0; frame.pc = 0;
frame.nactions = context.nactions; frame.nactions = context.nactions;
int textbeg = 0, textend = 0; int textbeg = 0, textend = 0;
int result = 0; int result = 0;
@ -5021,9 +5035,9 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
continue; continue;
} }
case STRING: { 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; frame.pc = i->ok;
continue; continue;
} }
@ -5031,6 +5045,16 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
frame.pc = i->ko; frame.pc = i->ko;
continue; 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: { case RULE: {
// frame.pc--; // save pc of call insn // frame.pc--; // save pc of call insn
// push(r, frame); // push(r, frame);
@ -5073,11 +5097,15 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
} }
case FAIL: { case FAIL: {
if (rsp) { if (rsp) {
context.nactions = frame.nactions - 1; // remove all actions added by this rule
frame = pop(r); frame = pop(r);
i = frame.code + frame.pc; i = frame.code + frame.pc;
frame.pc = i->ko; frame.pc = i->ko;
continue; continue;
} }
else {
context.nactions = 0;
}
result = -1; result = -1;
break; break;
} }

Yükleniyor…
İptal
Kaydet