summaryrefslogtreecommitdiff
path: root/pez.c
diff options
context:
space:
mode:
Diffstat (limited to 'pez.c')
-rw-r--r--pez.c59
1 files changed, 35 insertions, 24 deletions
diff --git a/pez.c b/pez.c
index b7ebad5..3f64b28 100644
--- a/pez.c
+++ b/pez.c
@@ -203,6 +203,7 @@ struct PezContext {
Obj *heap;
Upval *openup;
uint nalloc, gcthresh, gccanrun : 1;
+ int exedepth;
StrPool strpool;
Globals globals;
};
@@ -1599,7 +1600,8 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
}
/* Val *start = stktop; */
assert(pr->nstack > 0);
- if (stktop + pr->nstack >= cx->stkend) {
+ if (stktop + pr->nstack >= cx->stkend || cx->exedepth++ > 6000) {
+ --cx->exedepth;
return cx->err = PEZ_EStack, 0;
}
@@ -1631,6 +1633,7 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
push(ret);
closeups(cx, args);
cx->stktop = stktop;
+ --cx->exedepth;
return 1;
}
CASE(Opop) {
@@ -1715,7 +1718,7 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
k = pr->con[idx];
assert(isobj_of(k, PEZ_TFnProto));
cx->stktop = stktop;
- TRY(ofn = newfn(cx, unbox_obj(k), args, locals, fn));
+ ETRY(ofn = newfn(cx, unbox_obj(k), args, locals, fn));
stktop = cx->stktop;
push(box_obj(ofn));
}
@@ -1726,19 +1729,20 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
CASE(Oneg) {
Val *p = peek();
if (!isnum(*p)) {
- return runerr(cx, fn, ip, "attempt to negate %s value", typestr(*p)), 0;
+ runerr(cx, fn, ip, "attempt to negate %s value", typestr(*p));
+ goto Err;
}
*p = box_num(-(uint32_t)unbox_num(*p));
}
#define ARITH(o, oname) \
CASE(O##o) { \
- Val b = pop(), a = pop(); \
+ Val b = pop(), a = pop(); \
if (!isnum(a) || !isnum(b)) { \
runerr(cx, fn, ip, "cannot %s %s and %s values", \
oname, typestr(a), typestr(b)); \
- return 0; \
+ goto Err; \
} \
- push(UDO_O##o(a, b)); \
+ push(UDO_O##o(a, b)); \
}
ARITH(add, "add")
ARITH(sub, "subtract")
@@ -1765,7 +1769,7 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
if (!isnum(a)) { \
runerr(cx, fn, ip, "cannot %s %s and number values", \
oname, typestr(a)); \
- return 0; \
+ goto Err; \
} \
*p = expr; \
}
@@ -1836,16 +1840,17 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
fixnum num = unbox_num(a);
int idx = fixtoint(num) + pr->nparams;
if (!isnum(a) || num < 0 || fixtrunc(num) != num) {
- return runerr(cx, fn, ip, "SEL expected positive integer index"), 0;
+ runerr(cx, fn, ip, "SEL expected positive integer index");
+ goto Err;
}
push(idx >= nargs ? VOID : args[idx]);
}
CASE(Ogather) {
int n = nargs - pr->nparams;
Array *arr = newarr(cx, n);
- TRY(arr);
+ ETRY(arr);
push(box_obj(arr));
- TRY(arrpushn(cx, arr, args + pr->nparams, n));
+ ETRY(arrpushn(cx, arr, args + pr->nparams, n));
}
CASE(Oglobal) {
Val *k = peek(), *v;
@@ -1861,7 +1866,8 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
Str *s = unbox_obj(*k);
name = s->dat;
} else { assert(0); }
- return runerr(cx, fn, ip, "no such global \"%s\"", name), 0;
+ runerr(cx, fn, ip, "no such global \"%s\"", name);
+ goto Err;
}
}
CASE(Osetglo) {
@@ -1880,14 +1886,15 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
Str *s = unbox_obj(k);
name = s->dat;
} else { assert(0); }
- return runerr(cx, fn, ip, "no such global \"%s\"", name), 0;
+ runerr(cx, fn, ip, "no such global \"%s\"", name);
+ goto Err;
}
}
CASE(Oputglo) {
Val k, v;
v = pop();
k = pop();
- TRY(putglobal(cx, k, v));
+ ETRY(putglobal(cx, k, v));
}
CASE(Oapply) {
uint8_t n = code[ip++];
@@ -1901,17 +1908,17 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
if (pr->variadic ? n < pr->nparams : n != pr->nparams) {
runerr(cx, fn, ip, "function takes %d arg(s), %d %s given",
pr->nparams, n, n == 1 ? "was" : "were");
- return 0;
+ goto Err;
}
cx->stktop = stktop;
- TRY(exefn(cx, f, n));
+ ETRY(exefn(cx, f, n));
stktop = cx->stktop;
ret = pop();
stktop -= n-1;
*peek() = ret;
} else {
cx->stktop = stktop;
- TRY(apply(cx, &ret, fn, ip, lhs, n));
+ ETRY(apply(cx, &ret, fn, ip, lhs, n));
stktop = cx->stktop;
stktop -= n-1;
*peek() = ret;
@@ -1923,7 +1930,7 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
a = stktop[-1 - n],
ret;
cx->stktop = stktop;
- TRY(setapply(cx, &ret, fn, ip, a, n, rval));
+ ETRY(setapply(cx, &ret, fn, ip, a, n, rval));
stktop = cx->stktop;
stktop -= n;
stktop[-1] = ret;
@@ -1938,7 +1945,7 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
assert(ok);
push(arg);
cx->stktop = stktop;
- TRY(apply(cx, &ret, fn, ip, a, 1));
+ ETRY(apply(cx, &ret, fn, ip, a, 1));
stktop = cx->stktop;
--stktop;
*peek() = ret;
@@ -1948,10 +1955,10 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
uint8_t n = code[ip++];
Array *arr;
cx->stktop = stktop;
- TRY((arr = newarr(cx, n)) != NULL);
- TRY((push)(cx, box_obj(arr))); // gc keep
+ ETRY((arr = newarr(cx, n)) != NULL);
+ ETRY((push)(cx, box_obj(arr))); // gc keep
stktop = cx->stktop;
- TRY(arrpushn(cx, arr, cx->stktop - n - 1, n));
+ ETRY(arrpushn(cx, arr, cx->stktop - n - 1, n));
stktop -= n + 1;
push(box_obj(arr));
}
@@ -1960,13 +1967,13 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
Val r = stktop[-n - 1];
Array *arr = unbox_obj(r);
assert(isobj(r) && arr->t == PEZ_TArray);
- TRY(arrpushn(cx, arr, stktop - n, n));
+ ETRY(arrpushn(cx, arr, stktop - n, n));
stktop -= n;
}
CASE(Onewrec) {
uint8_t n = code[ip++];
Record *rc;
- TRY((rc = newrecord(cx, n, stktop - 2*n)) != NULL);
+ ETRY((rc = newrecord(cx, n, stktop - 2*n)) != NULL);
stktop -= 2*n;
push(box_obj(rc));
}
@@ -2001,7 +2008,8 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
}
}
BADOP {
- return runerr(cx, fn, ip, "bad opcode %#x", code[ip-1]), 0;
+ runerr(cx, fn, ip, "bad opcode %#x", code[ip-1]);
+ goto Err;
}
VMEND
#undef peek
@@ -2011,6 +2019,9 @@ exefn(PezContext *cx, Fn *fn, uint nargs)
#undef CASE
#undef VMEND
#undef VMBEGIN
+Err:
+ --cx->exedepth;
+ return 0;
}
/******************/