diff options
Diffstat (limited to 'lpvm.c')
-rw-r--r-- | lpvm.c | 56 |
1 files changed, 43 insertions, 13 deletions
@@ -48,6 +48,12 @@ 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 | |||
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, | |||
156 | const char *match (lua_State *L, const char *o, const char *s, const char *e, | 162 | const 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 */ |