aboutsummaryrefslogtreecommitdiff
path: root/lpvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lpvm.c')
-rw-r--r--lpvm.c77
1 files changed, 35 insertions, 42 deletions
diff --git a/lpvm.c b/lpvm.c
index 917a626..44975a1 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -48,12 +48,6 @@ 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
57#define getstackbase(L, ptop) ((Stack *)lua_touserdata(L, stackidx(ptop))) 51#define getstackbase(L, ptop) ((Stack *)lua_touserdata(L, stackidx(ptop)))
58 52
59 53
@@ -162,25 +156,22 @@ static int removedyncap (lua_State *L, Capture *capture,
162const char *match (lua_State *L, const char *o, const char *s, const char *e, 156const char *match (lua_State *L, const char *o, const char *s, const char *e,
163 Instruction *op, Capture *capture, int ptop, byte *labelf, const char **sfail) { /* labeled failure */ 157 Instruction *op, Capture *capture, int ptop, byte *labelf, const char **sfail) { /* labeled failure */
164 Stack stackbase[INITBACK]; 158 Stack stackbase[INITBACK];
165 RecStack recbase[MAXRECOVERY];
166 Stack *stacklimit = stackbase + INITBACK; 159 Stack *stacklimit = stackbase + INITBACK;
167 Stack *stack = stackbase; /* point to first empty slot in stack */ 160 Stack *stack = stackbase; /* point to first empty slot in stack */
168 RecStack *reclimit = recbase + MAXRECOVERY; 161 int capsize = INITCAPSIZE;
169 RecStack *recstack = recbase;
170 int capsize = INITCAPSIZE;
171 int captop = 0; /* point to first empty slot in captures */ 162 int captop = 0; /* point to first empty slot in captures */
172 int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ 163 int ndyncap = 0; /* number of dynamic captures (in Lua stack) */
173 const Instruction *p = op; /* current instruction */ 164 const Instruction *p = op; /* current instruction */
165 const Instruction *pk = NULL; /* resume instruction */
174 Labelset lsfail; 166 Labelset lsfail;
175 setlabelfail(&lsfail); 167 setlabelfail(&lsfail);
176 stack->p = &giveup; stack->s = s; stack->ls = &lsfail; stack->caplevel = 0; stack++; /* labeled failure */ 168 stack->p = &giveup; stack->s = s; stack->ls = &lsfail; stack->caplevel = 0; stack++; /* labeled failure */
177 recstack->prec = &giveup; recstack->ls = &lsfail; recstack++; /* labeled failure */
178 lua_pushlightuserdata(L, stackbase); 169 lua_pushlightuserdata(L, stackbase);
179 for (;;) { 170 for (;;) {
180#if defined(DEBUG) 171#if defined(DEBUG)
172 printinst(op, p);
181 printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ", 173 printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ",
182 s, stack - getstackbase(L, ptop), ndyncap, captop); 174 s, stack - getstackbase(L, ptop), ndyncap, captop);
183 printinst(op, p);
184 printcaplist(capture, capture + captop); 175 printcaplist(capture, capture + captop);
185#endif 176#endif
186 assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); 177 assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop);
@@ -204,6 +195,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
204 if (s < e) { p++; s++; } 195 if (s < e) { p++; s++; }
205 else { 196 else {
206 *labelf = LFAIL; /* labeled failure */ 197 *labelf = LFAIL; /* labeled failure */
198 pk = p + 1;
207 *sfail = s; 199 *sfail = s;
208 goto fail; 200 goto fail;
209 } 201 }
@@ -218,6 +210,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
218 if ((byte)*s == p->i.aux && s < e) { p++; s++; } 210 if ((byte)*s == p->i.aux && s < e) { p++; s++; }
219 else { 211 else {
220 *labelf = LFAIL; /* labeled failure */ 212 *labelf = LFAIL; /* labeled failure */
213 pk = p + 1;
221 *sfail = s; 214 *sfail = s;
222 goto fail; 215 goto fail;
223 } 216 }
@@ -234,6 +227,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
234 { p += CHARSETINSTSIZE; s++; } 227 { p += CHARSETINSTSIZE; s++; }
235 else { 228 else {
236 *labelf = LFAIL; /* labeled failure */ 229 *labelf = LFAIL; /* labeled failure */
230 pk = p + CHARSETINSTSIZE;
237 *sfail = s; 231 *sfail = s;
238 goto fail; 232 goto fail;
239 } 233 }
@@ -250,6 +244,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
250 int n = p->i.aux; 244 int n = p->i.aux;
251 if (n > s - o) { 245 if (n > s - o) {
252 *labelf = LFAIL; /* labeled failure */ 246 *labelf = LFAIL; /* labeled failure */
247 pk = p + 1;
253 *sfail = s; 248 *sfail = s;
254 goto fail; 249 goto fail;
255 } 250 }
@@ -291,11 +286,13 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
291 continue; 286 continue;
292 } 287 }
293 case IRecov: { /* labeled failure */ 288 case IRecov: { /* labeled failure */
294 if (recstack == reclimit) 289 if (stack == stacklimit)
295 luaL_error(L, "recovery stack overflow (current limit is %d)", MAXRECOVERY); 290 stack = doublestack(L, &stacklimit, ptop);
296 recstack->prec = p + getoffset(p); 291 stack->p = p + getoffset(p);
297 recstack->ls = (const Labelset *) ((p + 2)->buff); 292 stack->s = NULL;
298 recstack++; 293 stack->ls = (const Labelset *) ((p + 2)->buff);
294 stack->caplevel = captop;
295 stack++;
299 p += (CHARSETINSTSIZE - 1) + 2; 296 p += (CHARSETINSTSIZE - 1) + 2;
300 continue; 297 continue;
301 } 298 }
@@ -310,8 +307,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
310 continue; 307 continue;
311 } 308 }
312 case ICommit: { 309 case ICommit: {
313 /*assert(stack > getstackbase(L, ptop) && (stack - 1)->ls != NULL); */ /* labeled failure */ 310 assert(stack > getstackbase(L, ptop) && (stack - 1)->ls != NULL); /* labeled failure */
314 assert((stack - 1)->s != NULL); /* labeled failure: IRecov does not push s onto the stack */ 311 /*assert((stack - 1)->s != NULL); labeled failure: IRecov does not push s onto the stack */
315 stack--; 312 stack--;
316 p += getoffset(p); 313 p += getoffset(p);
317 continue; 314 continue;
@@ -332,24 +329,9 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
332 } 329 }
333 case IThrow: { /* labeled failure */ 330 case IThrow: { /* labeled failure */
334 *labelf = p->i.aux; 331 *labelf = p->i.aux;
335 while ((--recstack)->prec != &giveup) { 332 pk = p + 1;
336 if (testlabel(recstack->ls->cs, *labelf)) {
337 /* Push resume/call frame */
338 stack->s = NULL;
339 stack->p = p + 1; /* resume to instruction after IThrow */
340 stack->ls = NULL;
341 stack++;
342 p = recstack->prec;
343 break;
344 }
345 }
346 if (recstack->prec != &giveup)
347 continue;
348 p = recstack->prec; /* p = IGiveup */
349 stack = getstackbase(L, ptop);
350 *sfail = s; 333 *sfail = s;
351 /*goto fail;*/ 334 goto fail;
352 continue;
353 } 335 }
354 case IFailTwice: 336 case IFailTwice:
355 assert(stack > getstackbase(L, ptop)); 337 assert(stack > getstackbase(L, ptop));
@@ -357,20 +339,30 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
357 /* go through */ 339 /* go through */
358 case IFail: 340 case IFail:
359 *labelf = LFAIL; /* labeled failure */ 341 *labelf = LFAIL; /* labeled failure */
342 pk = NULL;
360 *sfail = s; 343 *sfail = s;
361 fail: { /* pattern failed: try to backtrack */ 344 fail: { /* pattern failed: try to backtrack */
362 const Labelset *auxlab = NULL; 345 const Labelset *auxlab = NULL;
346 Stack *pstack = stack;
363 do { /* remove pending calls */ 347 do { /* remove pending calls */
364 assert(stack > getstackbase(L, ptop)); 348 assert(pstack > getstackbase(L, ptop));
365 auxlab = (--stack)->ls; 349 auxlab = (--pstack)->ls;
366 } while (auxlab == NULL || (stack->p != &giveup && !testlabel(stack->ls->cs, *labelf))); 350 } while (auxlab == NULL || (pstack->p != &giveup && labelf != LFAIL && !testlabel(pstack->ls->cs, *labelf)));
367 if (stack->p == &giveup || stack->s != NULL) { /* labeled failure */ 351 if (pstack->p == &giveup || pstack->s != NULL) { /* labeled failure: giveup or backtrack frame */
352 stack = pstack;
368 s = stack->s; 353 s = stack->s;
369 } 354 } else { /* labeled failure: recovery frame */
355 if (stack == stacklimit)
356 stack = doublestack(L, &stacklimit, ptop);
357 stack->s = NULL;
358 stack->p = pk; /* save return address */
359 stack->ls = NULL;
360 stack++;
361 }
370 if (ndyncap > 0) /* is there matchtime captures? */ 362 if (ndyncap > 0) /* is there matchtime captures? */
371 ndyncap -= removedyncap(L, capture, stack->caplevel, captop); 363 ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
372 captop = stack->caplevel; 364 captop = stack->caplevel;
373 p = stack->p; 365 p = pstack->p;
374 continue; 366 continue;
375 } 367 }
376 case ICloseRunTime: { 368 case ICloseRunTime: {
@@ -385,6 +377,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
385 if (res == -1) { /* fail? */ 377 if (res == -1) { /* fail? */
386 *labelf = LFAIL; /* labeled failure */ 378 *labelf = LFAIL; /* labeled failure */
387 *sfail = (const char *) s; /* TODO: ??? */ 379 *sfail = (const char *) s; /* TODO: ??? */
380 pk = NULL;
388 goto fail; 381 goto fail;
389 } 382 }
390 s = o + res; /* else update current position */ 383 s = o + res; /* else update current position */