diff options
Diffstat (limited to 'lpvm.c')
-rw-r--r-- | lpvm.c | 59 |
1 files changed, 41 insertions, 18 deletions
@@ -26,6 +26,23 @@ | |||
26 | 26 | ||
27 | static const Instruction giveup = {{IGiveup, 0, 0}}; | 27 | static const Instruction giveup = {{IGiveup, 0, 0}}; |
28 | 28 | ||
29 | /* labeled failure */ | ||
30 | static void setlabelfail(Labelset *ls) { | ||
31 | loopset(i, ls->cs[i] = 0); | ||
32 | ls->cs[IDXLFAIL] = 1; | ||
33 | } | ||
34 | |||
35 | static void clearandsetlabel(Labelset *ls, byte b) { | ||
36 | loopset(i, ls->cs[i] = 0); | ||
37 | setlabel(ls->cs, b); | ||
38 | } | ||
39 | |||
40 | |||
41 | static int cs_disjoint (const Charset *cs1, const Charset *cs2) { | ||
42 | loopset(i, if ((cs1->cs[i] & cs2->cs[i]) != 0) return 0;) | ||
43 | return 1; | ||
44 | } | ||
45 | /* labeled failure end */ | ||
29 | 46 | ||
30 | /* | 47 | /* |
31 | ** {====================================================== | 48 | ** {====================================================== |
@@ -38,7 +55,7 @@ typedef struct Stack { | |||
38 | const char *s; /* saved position (or NULL for calls) */ | 55 | const char *s; /* saved position (or NULL for calls) */ |
39 | const Instruction *p; /* next instruction */ | 56 | const Instruction *p; /* next instruction */ |
40 | int caplevel; | 57 | int caplevel; |
41 | Labelset ls; /* labeled failure */ | 58 | const Labelset *ls; /* labeled failure */ |
42 | } Stack; | 59 | } Stack; |
43 | 60 | ||
44 | 61 | ||
@@ -142,6 +159,8 @@ static int removedyncap (lua_State *L, Capture *capture, | |||
142 | } | 159 | } |
143 | 160 | ||
144 | 161 | ||
162 | |||
163 | |||
145 | /* | 164 | /* |
146 | ** Opcode interpreter | 165 | ** Opcode interpreter |
147 | */ | 166 | */ |
@@ -154,15 +173,18 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
154 | int captop = 0; /* point to first empty slot in captures */ | 173 | int captop = 0; /* point to first empty slot in captures */ |
155 | int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ | 174 | int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ |
156 | const Instruction *p = op; /* current instruction */ | 175 | const Instruction *p = op; /* current instruction */ |
176 | Labelset lsfail; | ||
177 | setlabelfail(&lsfail); | ||
157 | stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++; | 178 | stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++; |
158 | lua_pushlightuserdata(L, stackbase); | 179 | lua_pushlightuserdata(L, stackbase); |
159 | for (;;) { | 180 | /*printf("match: %s\n", s);*/ |
160 | #if defined(DEBUG) | 181 | for (;;) { |
161 | printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ", | 182 | /*#if defined(DEBUG)*/ |
183 | /* printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ", | ||
162 | s, stack - getstackbase(L, ptop), ndyncap, captop); | 184 | s, stack - getstackbase(L, ptop), ndyncap, captop); |
163 | printinst(op, p); | 185 | printinst(op, p);*/ |
164 | printcaplist(capture, capture + captop); | 186 | /*printcaplist(capture, capture + captop);*/ |
165 | #endif | 187 | /*#endif*/ |
166 | assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); | 188 | assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); |
167 | switch ((Opcode)p->i.code) { | 189 | switch ((Opcode)p->i.code) { |
168 | case IEnd: { | 190 | case IEnd: { |
@@ -183,7 +205,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
183 | case IAny: { | 205 | case IAny: { |
184 | if (s < e) { p++; s++; } | 206 | if (s < e) { p++; s++; } |
185 | else { | 207 | else { |
186 | *labelf = LFAIL; /* labeled failure */ | 208 | setlabelfail(labelf); /* labeled failure */ |
187 | *sfail = s; | 209 | *sfail = s; |
188 | goto fail; | 210 | goto fail; |
189 | } | 211 | } |
@@ -197,7 +219,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
197 | case IChar: { | 219 | case IChar: { |
198 | if ((byte)*s == p->i.aux && s < e) { p++; s++; } | 220 | if ((byte)*s == p->i.aux && s < e) { p++; s++; } |
199 | else { | 221 | else { |
200 | *labelf = LFAIL; /* labeled failure */ | 222 | setlabelfail(labelf); /* labeled failure */ |
201 | *sfail = s; | 223 | *sfail = s; |
202 | goto fail; | 224 | goto fail; |
203 | } | 225 | } |
@@ -213,7 +235,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
213 | if (testchar((p+1)->buff, c) && s < e) | 235 | if (testchar((p+1)->buff, c) && s < e) |
214 | { p += CHARSETINSTSIZE; s++; } | 236 | { p += CHARSETINSTSIZE; s++; } |
215 | else { | 237 | else { |
216 | *labelf = LFAIL; /* labeled failure */ | 238 | setlabelfail(labelf); /* labeled failure */ |
217 | *sfail = s; | 239 | *sfail = s; |
218 | goto fail; | 240 | goto fail; |
219 | } | 241 | } |
@@ -229,7 +251,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
229 | case IBehind: { | 251 | case IBehind: { |
230 | int n = p->i.aux; | 252 | int n = p->i.aux; |
231 | if (n > s - o) { | 253 | if (n > s - o) { |
232 | *labelf = LFAIL; /* labeled failure */ | 254 | setlabelfail(labelf); /* labeled failure */ |
233 | *sfail = s; | 255 | *sfail = s; |
234 | goto fail; | 256 | goto fail; |
235 | } | 257 | } |
@@ -253,7 +275,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
253 | stack = doublestack(L, &stacklimit, ptop); | 275 | stack = doublestack(L, &stacklimit, ptop); |
254 | stack->p = p + getoffset(p); | 276 | stack->p = p + getoffset(p); |
255 | stack->s = s; | 277 | stack->s = s; |
256 | stack->ls = LFAIL; /* labeled failure */ | 278 | stack->ls = &lsfail; /* labeled failure */ |
257 | stack->caplevel = captop; | 279 | stack->caplevel = captop; |
258 | stack++; | 280 | stack++; |
259 | p += 2; | 281 | p += 2; |
@@ -264,10 +286,10 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
264 | stack = doublestack(L, &stacklimit, ptop); | 286 | stack = doublestack(L, &stacklimit, ptop); |
265 | stack->p = p + getoffset(p); | 287 | stack->p = p + getoffset(p); |
266 | stack->s = s; | 288 | stack->s = s; |
267 | stack->ls = (p + 2)->labels; | 289 | stack->ls = (const Labelset *) ((p + 2)->buff); |
268 | stack->caplevel = captop; | 290 | stack->caplevel = captop; |
269 | stack++; | 291 | stack++; |
270 | p += 3; | 292 | p += (CHARSETINSTSIZE - 1) + 2; |
271 | continue; | 293 | continue; |
272 | } | 294 | } |
273 | case ICall: { | 295 | case ICall: { |
@@ -300,7 +322,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
300 | continue; | 322 | continue; |
301 | } | 323 | } |
302 | case IThrow: { /* labeled failure */ | 324 | case IThrow: { /* labeled failure */ |
303 | *labelf = (p+1)->labels; | 325 | clearandsetlabel(labelf, p->i.aux); |
304 | *sfail = s; | 326 | *sfail = s; |
305 | /*printf("s = %s, sfail = %s\n", s, *sfail);*/ | 327 | /*printf("s = %s, sfail = %s\n", s, *sfail);*/ |
306 | goto fail; | 328 | goto fail; |
@@ -310,13 +332,14 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
310 | stack--; | 332 | stack--; |
311 | /* go through */ | 333 | /* go through */ |
312 | case IFail: | 334 | case IFail: |
313 | *labelf = LFAIL; /* labeled failure */ | 335 | setlabelfail(labelf); /* labeled failure */ |
314 | *sfail = s; | 336 | *sfail = s; |
315 | fail: { /* pattern failed: try to backtrack */ | 337 | fail: { /* pattern failed: try to backtrack */ |
316 | do { /* remove pending calls */ | 338 | do { /* remove pending calls */ |
317 | assert(stack > getstackbase(L, ptop)); | 339 | assert(stack > getstackbase(L, ptop)); |
318 | s = (--stack)->s; | 340 | s = (--stack)->s; |
319 | } while (s == NULL || (!(stack->ls & *labelf) && stack->p != &giveup)); | 341 | /*printf("s = %s, disj = %d\n", s, cs_disjoint(stack->ls, labelf));*/ |
342 | } while (s == NULL || (stack->p != &giveup && cs_disjoint(stack->ls, labelf))); | ||
320 | if (ndyncap > 0) /* is there matchtime captures? */ | 343 | if (ndyncap > 0) /* is there matchtime captures? */ |
321 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); | 344 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); |
322 | captop = stack->caplevel; | 345 | captop = stack->caplevel; |
@@ -333,7 +356,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
333 | fr -= rem; /* 'rem' items were popped from Lua stack */ | 356 | fr -= rem; /* 'rem' items were popped from Lua stack */ |
334 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ | 357 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ |
335 | if (res == -1) { /* fail? */ | 358 | if (res == -1) { /* fail? */ |
336 | *labelf = LFAIL; /* labeled failure */ | 359 | setlabelfail(labelf); /* labeled failure */ |
337 | *sfail = (const char *) s; /* TODO: ??? */ | 360 | *sfail = (const char *) s; /* TODO: ??? */ |
338 | goto fail; | 361 | goto fail; |
339 | } | 362 | } |