aboutsummaryrefslogtreecommitdiff
path: root/lpvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lpvm.c')
-rw-r--r--lpvm.c82
1 files changed, 51 insertions, 31 deletions
diff --git a/lpvm.c b/lpvm.c
index 9812e19..f56f1d5 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -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 */