소스 검색

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 달 전
부모
커밋
4065107170
1개의 변경된 파일55개의 추가작업 그리고 27개의 파일을 삭제
  1. +55
    -27
      minproto.leg

+ 55
- 27
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;
}

불러오는 중...
취소
저장