diff options
Diffstat (limited to 'lpvm.c')
-rw-r--r-- | lpvm.c | 82 |
1 files changed, 51 insertions, 31 deletions
@@ -39,6 +39,7 @@ typedef struct Stack { | |||
39 | const Instruction *p; /* next instruction */ | 39 | const Instruction *p; /* next instruction */ |
40 | int caplevel; | 40 | int caplevel; |
41 | byte labenv; /* labeled failure */ | 41 | byte labenv; /* labeled failure */ |
42 | byte predchoice; /* labeled failure */ | ||
42 | } Stack; | 43 | } Stack; |
43 | 44 | ||
44 | 45 | ||
@@ -156,8 +157,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
156 | int captop = 0; /* point to first empty slot in captures */ | 157 | int captop = 0; /* point to first empty slot in captures */ |
157 | int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ | 158 | int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ |
158 | const Instruction *p = op; /* current instruction */ | 159 | const Instruction *p = op; /* current instruction */ |
159 | byte labenv = 1; /* labeled failure: label environment is on */ | 160 | byte insidepred = OUTPRED; /* labeled failure: label environment is off inside predicates */ |
160 | stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack->labenv = 1; stack++; /* labeled failure */ | 161 | stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack->labenv = insidepred; stack++; /* labeled failure */ |
161 | *sfail = s; /* labeled failure */ | 162 | *sfail = s; /* labeled failure */ |
162 | lua_pushlightuserdata(L, stackbase); | 163 | lua_pushlightuserdata(L, stackbase); |
163 | for (;;) { | 164 | for (;;) { |
@@ -168,9 +169,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
168 | s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop); | 169 | s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop); |
169 | printinst(op, p); | 170 | printinst(op, p); |
170 | #endif | 171 | #endif |
171 | printinst(op, p); | ||
172 | assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); | 172 | assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); |
173 | assert(labenv == 1); | 173 | assert(insidepred == NOTPRED || insidepred == ANDPRED || insidepred == OUTPRED); |
174 | switch ((Opcode)p->i.code) { | 174 | switch ((Opcode)p->i.code) { |
175 | case IEnd: { | 175 | case IEnd: { |
176 | assert(stack == getstackbase(L, ptop) + 1); | 176 | assert(stack == getstackbase(L, ptop) + 1); |
@@ -191,7 +191,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
191 | if (s < e) { p++; s++; } | 191 | if (s < e) { p++; s++; } |
192 | else { | 192 | else { |
193 | *labelf = LFAIL; /* labeled failure */ | 193 | *labelf = LFAIL; /* labeled failure */ |
194 | updatefarthest(*sfail, s); /*labeled failure */ | 194 | if (insidepred == OUTPRED) |
195 | updatefarthest(*sfail, s); /*labeled failure */ | ||
195 | goto fail; | 196 | goto fail; |
196 | } | 197 | } |
197 | continue; | 198 | continue; |
@@ -205,7 +206,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
205 | if ((byte)*s == p->i.aux && s < e) { p++; s++; } | 206 | if ((byte)*s == p->i.aux && s < e) { p++; s++; } |
206 | else { | 207 | else { |
207 | *labelf = LFAIL; /* labeled failure */ | 208 | *labelf = LFAIL; /* labeled failure */ |
208 | updatefarthest(*sfail, s); /*labeled failure */ | 209 | if (insidepred == OUTPRED) |
210 | updatefarthest(*sfail, s); /*labeled failure */ | ||
209 | goto fail; | 211 | goto fail; |
210 | } | 212 | } |
211 | continue; | 213 | continue; |
@@ -221,7 +223,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
221 | { p += CHARSETINSTSIZE; s++; } | 223 | { p += CHARSETINSTSIZE; s++; } |
222 | else { | 224 | else { |
223 | *labelf = LFAIL; /* labeled failure */ | 225 | *labelf = LFAIL; /* labeled failure */ |
224 | updatefarthest(*sfail, s); /*labeled failure */ | 226 | if (insidepred == OUTPRED) |
227 | updatefarthest(*sfail, s); /*labeled failure */ | ||
225 | goto fail; | 228 | goto fail; |
226 | } | 229 | } |
227 | continue; | 230 | continue; |
@@ -237,7 +240,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
237 | int n = p->i.aux; | 240 | int n = p->i.aux; |
238 | if (n > s - o) { | 241 | if (n > s - o) { |
239 | *labelf = LFAIL; /* labeled failure */ | 242 | *labelf = LFAIL; /* labeled failure */ |
240 | updatefarthest(*sfail, s); /*labeled failure */ | 243 | if (insidepred == OUTPRED) |
244 | updatefarthest(*sfail, s); /*labeled failure */ | ||
241 | goto fail; | 245 | goto fail; |
242 | } | 246 | } |
243 | s -= n; p++; | 247 | s -= n; p++; |
@@ -261,10 +265,24 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
261 | stack->p = p + getoffset(p); | 265 | stack->p = p + getoffset(p); |
262 | stack->s = s; | 266 | stack->s = s; |
263 | stack->caplevel = captop; | 267 | stack->caplevel = captop; |
264 | stack->labenv = labenv; /* labeled failure */ | 268 | stack->labenv = insidepred; /* labeled failure */ |
269 | stack->predchoice = 0; /* labeled failure */ | ||
265 | stack++; | 270 | stack++; |
266 | p += 2; | 271 | p += 2; |
267 | continue; | 272 | continue; |
273 | } | ||
274 | case IPredChoice: { /* labeled failure: new instruction */ | ||
275 | if (stack == stacklimit) | ||
276 | stack = doublestack(L, &stacklimit, ptop); | ||
277 | stack->p = p + getoffset(p); | ||
278 | stack->s = s; | ||
279 | stack->caplevel = captop; | ||
280 | stack->labenv = insidepred; | ||
281 | stack->predchoice = 1; | ||
282 | stack++; | ||
283 | insidepred = p->i.aux; | ||
284 | p += 2; | ||
285 | continue; | ||
268 | } | 286 | } |
269 | case ICall: { | 287 | case ICall: { |
270 | if (stack == stacklimit) | 288 | if (stack == stacklimit) |
@@ -292,38 +310,30 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
292 | case IBackCommit: { | 310 | case IBackCommit: { |
293 | assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL); | 311 | assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL); |
294 | s = (--stack)->s; | 312 | s = (--stack)->s; |
295 | labenv = stack->labenv; /* labeled failure */ | 313 | insidepred = stack->labenv; /* labeled failure */ |
296 | assert(labenv == 1); /* labeled failure */ | ||
297 | captop = stack->caplevel; | 314 | captop = stack->caplevel; |
298 | p += getoffset(p); | 315 | p += getoffset(p); |
299 | continue; | 316 | continue; |
300 | } | 317 | } |
301 | case IThrow: { /* labeled failure */ | 318 | case IThrow: { /* labeled failure */ |
302 | /*printf("IThrow here: key=%d, key+1=%d aux = %d top = %d\n", p->i.key, (p+1)->i.key, p->i.aux, lua_gettop(L)); | 319 | if (insidepred == OUTPRED) { |
303 | lua_rawgeti(L, ktableidx(ptop), (p+1)->i.key); | ||
304 | printf("IThrow there %s top = %d\n", lua_tostring(L, -1), lua_gettop(L)); | ||
305 | lua_pop(L, 1);*/ | ||
306 | if (labenv) { | ||
307 | *labelf = (p+1)->i.key; | 320 | *labelf = (p+1)->i.key; |
308 | if (*labelf == LFAIL) | 321 | if (*labelf == LFAIL) |
309 | luaL_error(L, "labelf is %d", *labelf); | 322 | luaL_error(L, "labelf is %d", *labelf); |
310 | stack = getstackbase(L, ptop); | 323 | stack = getstackbase(L, ptop); |
311 | stack++; | 324 | stack++; |
312 | printf("IThrow stack->labenv = %d\n", stack->labenv); | 325 | *sfail = s; |
313 | } | 326 | } |
314 | else { | 327 | else { |
315 | labelf = LFAIL; | 328 | while (!(stack-1)->predchoice) { |
329 | --stack; | ||
330 | } | ||
331 | *labelf = LFAIL; | ||
316 | } | 332 | } |
317 | *sfail = s; | ||
318 | goto fail; | 333 | goto fail; |
319 | } | 334 | } |
320 | case IThrowRec: { /* labeled failure */ | 335 | case IThrowRec: { /* labeled failure */ |
321 | /*printf("IThrowRec here: key=%d, key+2=%d aux = %d top = %d\n", p->i.key, (p+2)->i.key, p->i.aux, lua_gettop(L)); | 336 | if (insidepred == OUTPRED) { |
322 | lua_rawgeti(L, ktableidx(ptop), (p+2)->i.key); | ||
323 | printf("IThrowRec there %s top = %d\n", lua_tostring(L, -1), lua_gettop(L)); | ||
324 | lua_pop(L, 1);*/ | ||
325 | printf("labenv here = %d\n", labenv); | ||
326 | if (labenv) { | ||
327 | *labelf = (p+2)->i.key; | 337 | *labelf = (p+2)->i.key; |
328 | if (*labelf == LFAIL) | 338 | if (*labelf == LFAIL) |
329 | luaL_error(L, "labelf is %d", *labelf); | 339 | luaL_error(L, "labelf is %d", *labelf); |
@@ -334,12 +344,19 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
334 | stack->p = p + 3; | 344 | stack->p = p + 3; |
335 | stack->caplevel = captop; | 345 | stack->caplevel = captop; |
336 | stack++; | 346 | stack++; |
347 | *sfail = s; | ||
337 | p += getoffset(p); | 348 | p += getoffset(p); |
338 | continue; | 349 | continue; |
339 | } else { | 350 | } else { |
340 | labelf = LFAIL; | 351 | while (!(stack-1)->predchoice) { |
352 | --stack; | ||
353 | } | ||
354 | /*if ((stack-1)->labenv == ANDPRED) { | ||
355 | printf("ANDPRED: stack - 1\n"); | ||
356 | stack--; | ||
357 | }*/ | ||
358 | *labelf = LFAIL; | ||
341 | } | 359 | } |
342 | *sfail = s; | ||
343 | goto fail; | 360 | goto fail; |
344 | } | 361 | } |
345 | case IFailTwice: | 362 | case IFailTwice: |
@@ -348,7 +365,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
348 | /* go through */ | 365 | /* go through */ |
349 | case IFail: | 366 | case IFail: |
350 | *labelf = LFAIL; /* labeled failure */ | 367 | *labelf = LFAIL; /* labeled failure */ |
351 | updatefarthest(*sfail, s); /*labeled failure */ | 368 | if (insidepred == OUTPRED) |
369 | updatefarthest(*sfail, s); /*labeled failure */ | ||
352 | fail: { /* pattern failed: try to backtrack */ | 370 | fail: { /* pattern failed: try to backtrack */ |
353 | do { /* remove pending calls */ | 371 | do { /* remove pending calls */ |
354 | assert(stack > getstackbase(L, ptop)); | 372 | assert(stack > getstackbase(L, ptop)); |
@@ -357,8 +375,9 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
357 | if (ndyncap > 0) /* is there matchtime captures? */ | 375 | if (ndyncap > 0) /* is there matchtime captures? */ |
358 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); | 376 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); |
359 | captop = stack->caplevel; | 377 | captop = stack->caplevel; |
360 | labenv = stack->labenv; | 378 | assert(((insidepred == ANDPRED || insidepred == NOTPRED) && (stack->labenv == OUTPRED)) || insidepred == stack->labenv |
361 | assert(labenv == 1); | 379 | || (insidepred != OUTPRED && stack->labenv != OUTPRED)); |
380 | insidepred = stack->labenv; | ||
362 | p = stack->p; | 381 | p = stack->p; |
363 | #if defined(DEBUG) | 382 | #if defined(DEBUG) |
364 | printf("**FAIL**\n"); | 383 | printf("**FAIL**\n"); |
@@ -377,7 +396,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
377 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ | 396 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ |
378 | if (res == -1) { /* fail? */ | 397 | if (res == -1) { /* fail? */ |
379 | *labelf = LFAIL; /* labeled failure */ | 398 | *labelf = LFAIL; /* labeled failure */ |
380 | updatefarthest(*sfail, s); /*labeled failure */ | 399 | if (insidepred == OUTPRED) |
400 | updatefarthest(*sfail, s); /*labeled failure */ | ||
381 | goto fail; | 401 | goto fail; |
382 | } | 402 | } |
383 | s = o + res; /* else update current position */ | 403 | s = o + res; /* else update current position */ |