diff options
Diffstat (limited to 'lpvm.c')
-rw-r--r-- | lpvm.c | 77 |
1 files changed, 35 insertions, 42 deletions
@@ -48,12 +48,6 @@ typedef struct Stack { | |||
48 | } Stack; | 48 | } Stack; |
49 | 49 | ||
50 | 50 | ||
51 | typedef 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, | |||
162 | const char *match (lua_State *L, const char *o, const char *s, const char *e, | 156 | const 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 */ |