aboutsummaryrefslogtreecommitdiff
path: root/lpvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lpvm.c')
-rw-r--r--lpvm.c56
1 files changed, 43 insertions, 13 deletions
diff --git a/lpvm.c b/lpvm.c
index 277acf7..db996e5 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -48,6 +48,12 @@ typedef struct Stack {
48} Stack; 48} Stack;
49 49
50 50
51typedef struct RecStack {
52 const Labelset *ls; /* labeled failure */
53 const Instruction *prec; /* recovery instruction */
54} RecStack;
55
56
51#define getstackbase(L, ptop) ((Stack *)lua_touserdata(L, stackidx(ptop))) 57#define getstackbase(L, ptop) ((Stack *)lua_touserdata(L, stackidx(ptop)))
52 58
53 59
@@ -156,15 +162,20 @@ static int removedyncap (lua_State *L, Capture *capture,
156const char *match (lua_State *L, const char *o, const char *s, const char *e, 162const char *match (lua_State *L, const char *o, const char *s, const char *e,
157 Instruction *op, Capture *capture, int ptop, byte *labelf, const char **sfail) { /* labeled failure */ 163 Instruction *op, Capture *capture, int ptop, byte *labelf, const char **sfail) { /* labeled failure */
158 Stack stackbase[INITBACK]; 164 Stack stackbase[INITBACK];
165 RecStack recbase[MAXRECOVERY];
159 Stack *stacklimit = stackbase + INITBACK; 166 Stack *stacklimit = stackbase + INITBACK;
160 Stack *stack = stackbase; /* point to first empty slot in stack */ 167 Stack *stack = stackbase; /* point to first empty slot in stack */
161 int capsize = INITCAPSIZE; 168 RecStack *reclimit = recbase + MAXRECOVERY;
169 RecStack *recstack = recbase;
170 int capsize = INITCAPSIZE;
162 int captop = 0; /* point to first empty slot in captures */ 171 int captop = 0; /* point to first empty slot in captures */
163 int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ 172 int ndyncap = 0; /* number of dynamic captures (in Lua stack) */
164 const Instruction *p = op; /* current instruction */ 173 const Instruction *p = op; /* current instruction */
174 const Instruction *pk = NULL; /* resume instruction */
165 Labelset lsfail; 175 Labelset lsfail;
166 setlabelfail(&lsfail); 176 setlabelfail(&lsfail);
167 stack->p = &giveup; stack->s = s; stack->ls = &lsfail; stack->caplevel = 0; stack++; /* labeled failure */ 177 stack->p = &giveup; stack->s = s; stack->ls = &lsfail; stack->caplevel = 0; stack++; /* labeled failure */
178 recstack->prec = &giveup; recstack->ls = &lsfail; recstack++; /* labeled failure */
168 lua_pushlightuserdata(L, stackbase); 179 lua_pushlightuserdata(L, stackbase);
169 for (;;) { 180 for (;;) {
170#if defined(DEBUG) 181#if defined(DEBUG)
@@ -194,6 +205,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
194 if (s < e) { p++; s++; } 205 if (s < e) { p++; s++; }
195 else { 206 else {
196 *labelf = LFAIL; /* labeled failure */ 207 *labelf = LFAIL; /* labeled failure */
208 pk = p + 1;
197 *sfail = s; 209 *sfail = s;
198 goto fail; 210 goto fail;
199 } 211 }
@@ -208,6 +220,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
208 if ((byte)*s == p->i.aux && s < e) { p++; s++; } 220 if ((byte)*s == p->i.aux && s < e) { p++; s++; }
209 else { 221 else {
210 *labelf = LFAIL; /* labeled failure */ 222 *labelf = LFAIL; /* labeled failure */
223 pk = p + 1;
211 *sfail = s; 224 *sfail = s;
212 goto fail; 225 goto fail;
213 } 226 }
@@ -224,6 +237,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
224 { p += CHARSETINSTSIZE; s++; } 237 { p += CHARSETINSTSIZE; s++; }
225 else { 238 else {
226 *labelf = LFAIL; /* labeled failure */ 239 *labelf = LFAIL; /* labeled failure */
240 pk = p + CHARSETINSTSIZE;
227 *sfail = s; 241 *sfail = s;
228 goto fail; 242 goto fail;
229 } 243 }
@@ -240,6 +254,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
240 int n = p->i.aux; 254 int n = p->i.aux;
241 if (n > s - o) { 255 if (n > s - o) {
242 *labelf = LFAIL; /* labeled failure */ 256 *labelf = LFAIL; /* labeled failure */
257 pk = p + 1;
243 *sfail = s; 258 *sfail = s;
244 goto fail; 259 goto fail;
245 } 260 }
@@ -281,17 +296,14 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
281 continue; 296 continue;
282 } 297 }
283 case IRecov: { /* labeled failure */ 298 case IRecov: { /* labeled failure */
284 if (stack == stacklimit) 299 if (recstack == reclimit)
285 stack = doublestack(L, &stacklimit, ptop); 300 luaL_error(L, "recovery stack overflow (current limit is %d)", MAXRECOVERY);
286 stack->p = p + getoffset(p); 301 recstack->prec = p + getoffset(p);
287 stack->s = NULL; 302 recstack->ls = (const Labelset *) ((p + 2)->buff);
288 stack->ls = (const Labelset *) ((p + 2)->buff); 303 recstack++;
289 stack->caplevel = captop;
290 stack++;
291 p += (CHARSETINSTSIZE - 1) + 2; 304 p += (CHARSETINSTSIZE - 1) + 2;
292 continue; 305 continue;
293 } 306 }
294
295 case ICall: { 307 case ICall: {
296 if (stack == stacklimit) 308 if (stack == stacklimit)
297 stack = doublestack(L, &stacklimit, ptop); 309 stack = doublestack(L, &stacklimit, ptop);
@@ -303,8 +315,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
303 continue; 315 continue;
304 } 316 }
305 case ICommit: { 317 case ICommit: {
306 assert(stack > getstackbase(L, ptop) && (stack - 1)->ls != NULL); /* labeled failure */ 318 /*assert(stack > getstackbase(L, ptop) && (stack - 1)->ls != NULL); */ /* labeled failure */
307 /* assert((stack - 1)->s != NULL); labeled failure: IRecov does not push s onto the stack */ 319 assert((stack - 1)->s != NULL); /* labeled failure: IRecov does not push s onto the stack */
308 stack--; 320 stack--;
309 p += getoffset(p); 321 p += getoffset(p);
310 continue; 322 continue;
@@ -325,8 +337,24 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
325 } 337 }
326 case IThrow: { /* labeled failure */ 338 case IThrow: { /* labeled failure */
327 *labelf = p->i.aux; 339 *labelf = p->i.aux;
340 while ((--recstack)->prec != &giveup) {
341 if (testlabel(recstack->ls->cs, *labelf)) {
342 /* Push resume/call frame */
343 stack->s = NULL;
344 stack->p = p + 1; /* resume to instruction after IThrow */
345 stack->ls = NULL;
346 stack++;
347 p = recstack->prec;
348 break;
349 }
350 }
351 if (recstack->prec != &giveup)
352 continue;
353 p = recstack->prec; /* p = IGiveup */
354 stack = getstackbase(L, ptop);
328 *sfail = s; 355 *sfail = s;
329 goto fail; 356 /*goto fail;*/
357 continue;
330 } 358 }
331 case IFailTwice: 359 case IFailTwice:
332 assert(stack > getstackbase(L, ptop)); 360 assert(stack > getstackbase(L, ptop));
@@ -334,6 +362,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
334 /* go through */ 362 /* go through */
335 case IFail: 363 case IFail:
336 *labelf = LFAIL; /* labeled failure */ 364 *labelf = LFAIL; /* labeled failure */
365 pk = NULL;
337 *sfail = s; 366 *sfail = s;
338 fail: { /* pattern failed: try to backtrack */ 367 fail: { /* pattern failed: try to backtrack */
339 const Labelset *auxlab = NULL; 368 const Labelset *auxlab = NULL;
@@ -343,7 +372,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
343 } while (auxlab == NULL || (stack->p != &giveup && !testlabel(stack->ls->cs, *labelf))); 372 } while (auxlab == NULL || (stack->p != &giveup && !testlabel(stack->ls->cs, *labelf)));
344 if (stack->p == &giveup || stack->s != NULL) { /* labeled failure */ 373 if (stack->p == &giveup || stack->s != NULL) { /* labeled failure */
345 s = stack->s; 374 s = stack->s;
346 } 375 }
347 if (ndyncap > 0) /* is there matchtime captures? */ 376 if (ndyncap > 0) /* is there matchtime captures? */
348 ndyncap -= removedyncap(L, capture, stack->caplevel, captop); 377 ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
349 captop = stack->caplevel; 378 captop = stack->caplevel;
@@ -362,6 +391,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
362 if (res == -1) { /* fail? */ 391 if (res == -1) { /* fail? */
363 *labelf = LFAIL; /* labeled failure */ 392 *labelf = LFAIL; /* labeled failure */
364 *sfail = (const char *) s; /* TODO: ??? */ 393 *sfail = (const char *) s; /* TODO: ??? */
394 pk = NULL;
365 goto fail; 395 goto fail;
366 } 396 }
367 s = o + res; /* else update current position */ 397 s = o + res; /* else update current position */