aboutsummaryrefslogtreecommitdiff
path: root/lpcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'lpcode.c')
-rw-r--r--lpcode.c143
1 files changed, 84 insertions, 59 deletions
diff --git a/lpcode.c b/lpcode.c
index 4431146..1ee6ed1 100644
--- a/lpcode.c
+++ b/lpcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lpcode.c,v 1.18 2013/04/12 16:30:33 roberto Exp $ 2** $Id: lpcode.c,v 1.21 2014/12/12 17:01:29 roberto Exp $
3** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) 3** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
4*/ 4*/
5 5
@@ -33,26 +33,30 @@ static const Charset *fullset = &fullset_;
33*/ 33*/
34 34
35/* 35/*
36** Check whether a charset is empty (IFail), singleton (IChar), 36** Check whether a charset is empty (returns IFail), singleton (IChar),
37** full (IAny), or none of those (ISet). 37** full (IAny), or none of those (ISet). When singleton, '*c' returns
38** which character it is. (When generic set, the set was the input,
39** so there is no need to return it.)
38*/ 40*/
39static Opcode charsettype (const byte *cs, int *c) { 41static Opcode charsettype (const byte *cs, int *c) {
40 int count = 0; 42 int count = 0; /* number of characters in the set */
41 int i; 43 int i;
42 int candidate = -1; /* candidate position for a char */ 44 int candidate = -1; /* candidate position for the singleton char */
43 for (i = 0; i < CHARSETSIZE; i++) { 45 for (i = 0; i < CHARSETSIZE; i++) { /* for each byte */
44 int b = cs[i]; 46 int b = cs[i];
45 if (b == 0) { 47 if (b == 0) { /* is byte empty? */
46 if (count > 1) return ISet; /* else set is still empty */ 48 if (count > 1) /* was set neither empty nor singleton? */
49 return ISet; /* neither full nor empty nor singleton */
50 /* else set is still empty or singleton */
47 } 51 }
48 else if (b == 0xFF) { 52 else if (b == 0xFF) { /* is byte full? */
49 if (count < (i * BITSPERCHAR)) 53 if (count < (i * BITSPERCHAR)) /* was set not full? */
50 return ISet; 54 return ISet; /* neither full nor empty nor singleton */
51 else count += BITSPERCHAR; /* set is still full */ 55 else count += BITSPERCHAR; /* set is still full */
52 } 56 }
53 else if ((b & (b - 1)) == 0) { /* byte has only one bit? */ 57 else if ((b & (b - 1)) == 0) { /* has byte only one bit? */
54 if (count > 0) 58 if (count > 0) /* was set not empty? */
55 return ISet; /* set is neither full nor empty */ 59 return ISet; /* neither full nor empty nor singleton */
56 else { /* set has only one char till now; track it */ 60 else { /* set has only one char till now; track it */
57 count++; 61 count++;
58 candidate = i; 62 candidate = i;
@@ -77,6 +81,7 @@ static Opcode charsettype (const byte *cs, int *c) {
77 } 81 }
78} 82}
79 83
84
80/* 85/*
81** A few basic operations on Charsets 86** A few basic operations on Charsets
82*/ 87*/
@@ -84,16 +89,11 @@ static void cs_complement (Charset *cs) {
84 loopset(i, cs->cs[i] = ~cs->cs[i]); 89 loopset(i, cs->cs[i] = ~cs->cs[i]);
85} 90}
86 91
87
88static int cs_equal (const byte *cs1, const byte *cs2) { 92static int cs_equal (const byte *cs1, const byte *cs2) {
89 loopset(i, if (cs1[i] != cs2[i]) return 0); 93 loopset(i, if (cs1[i] != cs2[i]) return 0);
90 return 1; 94 return 1;
91} 95}
92 96
93
94/*
95** computes whether sets cs1 and cs2 are disjoint
96*/
97static int cs_disjoint (const Charset *cs1, const Charset *cs2) { 97static int cs_disjoint (const Charset *cs1, const Charset *cs2) {
98 loopset(i, if ((cs1->cs[i] & cs2->cs[i]) != 0) return 0;) 98 loopset(i, if ((cs1->cs[i] & cs2->cs[i]) != 0) return 0;)
99 return 1; 99 return 1;
@@ -101,7 +101,8 @@ static int cs_disjoint (const Charset *cs1, const Charset *cs2) {
101 101
102 102
103/* 103/*
104** Convert a 'char' pattern (TSet, TChar, TAny) to a charset 104** If 'tree' is a 'char' pattern (TSet, TChar, TAny), convert it into a
105** charset and return 1; else return 0.
105*/ 106*/
106int tocharset (TTree *tree, Charset *cs) { 107int tocharset (TTree *tree, Charset *cs) {
107 switch (tree->tag) { 108 switch (tree->tag) {
@@ -116,7 +117,7 @@ int tocharset (TTree *tree, Charset *cs) {
116 return 1; 117 return 1;
117 } 118 }
118 case TAny: { 119 case TAny: {
119 loopset(i, cs->cs[i] = 0xFF); /* add all to the set */ 120 loopset(i, cs->cs[i] = 0xFF); /* add all characters to the set */
120 return 1; 121 return 1;
121 } 122 }
122 default: return 0; 123 default: return 0;
@@ -125,13 +126,16 @@ int tocharset (TTree *tree, Charset *cs) {
125 126
126 127
127/* 128/*
128** Checks whether a pattern has captures 129** Check whether a pattern tree has captures
129*/ 130*/
130int hascaptures (TTree *tree) { 131int hascaptures (TTree *tree) {
131 tailcall: 132 tailcall:
132 switch (tree->tag) { 133 switch (tree->tag) {
133 case TCapture: case TRunTime: 134 case TCapture: case TRunTime:
134 return 1; 135 return 1;
136 case TCall:
137 tree = sib2(tree); goto tailcall; /* return hascaptures(sib2(tree)); */
138 case TOpenCall: assert(0);
135 default: { 139 default: {
136 switch (numsiblings[tree->tag]) { 140 switch (numsiblings[tree->tag]) {
137 case 1: /* return hascaptures(sib1(tree)); */ 141 case 1: /* return hascaptures(sib1(tree)); */
@@ -161,7 +165,7 @@ int hascaptures (TTree *tree) {
161** p is nullable => nullable(p) 165** p is nullable => nullable(p)
162** nofail(p) => p cannot fail 166** nofail(p) => p cannot fail
163** The function assumes that TOpenCall is not nullable; 167** The function assumes that TOpenCall is not nullable;
164** this will be checked again when the grammar is fixed.) 168** this will be checked again when the grammar is fixed.
165** Run-time captures can do whatever they want, so the result 169** Run-time captures can do whatever they want, so the result
166** is conservative. 170** is conservative.
167*/ 171*/
@@ -188,7 +192,7 @@ int checkaux (TTree *tree, int pred) {
188 if (!checkaux(sib1(tree), pred)) return 0; 192 if (!checkaux(sib1(tree), pred)) return 0;
189 /* else return checkaux(sib2(tree), pred); */ 193 /* else return checkaux(sib2(tree), pred); */
190 tree = sib2(tree); goto tailcall; 194 tree = sib2(tree); goto tailcall;
191 case TChoice: case TLabChoice: /* labeled failure */ 195 case TChoice: case TLabChoice: /* labeled failure */
192 if (checkaux(sib2(tree), pred)) return 1; 196 if (checkaux(sib2(tree), pred)) return 1;
193 /* else return checkaux(sib1(tree), pred); */ 197 /* else return checkaux(sib1(tree), pred); */
194 tree = sib1(tree); goto tailcall; 198 tree = sib1(tree); goto tailcall;
@@ -198,7 +202,7 @@ int checkaux (TTree *tree, int pred) {
198 case TCall: /* return checkaux(sib2(tree), pred); */ 202 case TCall: /* return checkaux(sib2(tree), pred); */
199 tree = sib2(tree); goto tailcall; 203 tree = sib2(tree); goto tailcall;
200 default: assert(0); return 0; 204 default: assert(0); return 0;
201 }; 205 }
202} 206}
203 207
204 208
@@ -246,16 +250,20 @@ int fixedlenx (TTree *tree, int count, int len) {
246/* 250/*
247** Computes the 'first set' of a pattern. 251** Computes the 'first set' of a pattern.
248** The result is a conservative aproximation: 252** The result is a conservative aproximation:
249** match p ax -> x' for some x ==> a in first(p). 253** match p ax -> x (for some x) ==> a belongs to first(p)
254** or
255** a not in first(p) ==> match p ax -> fail (for all x)
256**
250** The set 'follow' is the first set of what follows the 257** The set 'follow' is the first set of what follows the
251** pattern (full set if nothing follows it). 258** pattern (full set if nothing follows it).
252** The function returns 0 when this set can be used for 259**
253** tests that avoid the pattern altogether. 260** The function returns 0 when this resulting set can be used for
261** test instructions that avoid the pattern altogether.
254** A non-zero return can happen for two reasons: 262** A non-zero return can happen for two reasons:
255** 1) match p '' -> '' ==> returns 1. 263** 1) match p '' -> '' ==> return has bit 1 set
256** (tests cannot be used because they always fail for an empty input) 264** (tests cannot be used because they would always fail for an empty input);
257** 2) there is a match-time capture ==> returns 2. 265** 2) there is a match-time capture ==> return has bit 2 set
258** (match-time captures should not be avoided by optimizations) 266** (optimizations should not bypass match-time captures).
259*/ 267*/
260static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) { 268static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) {
261 tailcall: 269 tailcall:
@@ -266,16 +274,16 @@ static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) {
266 } 274 }
267 case TTrue: { 275 case TTrue: {
268 loopset(i, firstset->cs[i] = follow->cs[i]); 276 loopset(i, firstset->cs[i] = follow->cs[i]);
269 return 1; 277 return 1; /* accepts the empty string */
270 } 278 }
271 case TFalse: { 279 case TFalse: {
272 loopset(i, firstset->cs[i] = 0); 280 loopset(i, firstset->cs[i] = 0);
273 return 0; 281 return 0;
274 } 282 }
275 case TThrow: { /* labeled failure: must always throw the label */ 283 case TThrow: { /* labeled failure: must always throw the label */
276 loopset(i, firstset->cs[i] = follow->cs[i]); /* follow = fullset(?) */ 284 loopset(i, firstset->cs[i] = follow->cs[i]); /* follow = fullset(?) */
277 return 1; 285 return 1;
278 } 286 }
279 case TChoice: case TLabChoice: { /*(?) labeled failure */ 287 case TChoice: case TLabChoice: { /*(?) labeled failure */
280 Charset csaux; 288 Charset csaux;
281 int e1 = getfirst(sib1(tree), follow, firstset); 289 int e1 = getfirst(sib1(tree), follow, firstset);
@@ -285,7 +293,8 @@ static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) {
285 } 293 }
286 case TSeq: { 294 case TSeq: {
287 if (!nullable(sib1(tree))) { 295 if (!nullable(sib1(tree))) {
288 /* return getfirst(sib1(tree), fullset, firstset); */ 296 /* when p1 is not nullable, p2 has nothing to contribute;
297 return getfirst(sib1(tree), fullset, firstset); */
289 tree = sib1(tree); follow = fullset; goto tailcall; 298 tree = sib1(tree); follow = fullset; goto tailcall;
290 } 299 }
291 else { /* FIRST(p1 p2, fl) = FIRST(p1, FIRST(p2, fl)) */ 300 else { /* FIRST(p1 p2, fl) = FIRST(p1, FIRST(p2, fl)) */
@@ -329,7 +338,7 @@ static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) {
329 /* else go through */ 338 /* else go through */
330 } 339 }
331 case TBehind: { /* instruction gives no new information */ 340 case TBehind: { /* instruction gives no new information */
332 /* call 'getfirst' to check for math-time captures */ 341 /* call 'getfirst' only to check for math-time captures */
333 int e = getfirst(sib1(tree), follow, firstset); 342 int e = getfirst(sib1(tree), follow, firstset);
334 loopset(i, firstset->cs[i] = follow->cs[i]); /* uses follow */ 343 loopset(i, firstset->cs[i] = follow->cs[i]); /* uses follow */
335 return e | 1; /* always can accept the empty string */ 344 return e | 1; /* always can accept the empty string */
@@ -340,13 +349,13 @@ static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) {
340 349
341 350
342/* 351/*
343** If it returns true, then pattern can fail only depending on the next 352** If 'headfail(tree)' true, then 'tree' can fail only depending on the
344** character of the subject 353** next character of the subject.
345*/ 354*/
346static int headfail (TTree *tree) { 355static int headfail (TTree *tree) {
347 tailcall: 356 tailcall:
348 switch (tree->tag) { 357 switch (tree->tag) {
349 case TChar: case TSet: case TAny: case TFalse: 358 case TChar: case TSet: case TAny: case TFalse:
350 return 1; 359 return 1;
351 case TTrue: case TRep: case TRunTime: case TNot: 360 case TTrue: case TRep: case TRunTime: case TNot:
352 case TBehind: 361 case TBehind:
@@ -410,10 +419,12 @@ int sizei (const Instruction *i) {
410 switch((Opcode)i->i.code) { 419 switch((Opcode)i->i.code) {
411 case ISet: case ISpan: return CHARSETINSTSIZE; 420 case ISet: case ISpan: return CHARSETINSTSIZE;
412 case ITestSet: return CHARSETINSTSIZE + 1; 421 case ITestSet: return CHARSETINSTSIZE + 1;
413 case ITestChar: case ITestAny: case IChoice: case IJmp: 422 case ITestChar: case ITestAny: case IChoice: case IJmp: case ICall:
414 case ICall: case IOpenCall: case ICommit: case IPartialCommit: 423 case IOpenCall: case ICommit: case IPartialCommit: case IBackCommit:
415 case IBackCommit: case IThrow: return 2; /* labeled failure */ 424 case IThrow: /* labeled failure */
425 return 2;
416 case ILabChoice: return 3; /* labeled failure */ 426 case ILabChoice: return 3; /* labeled failure */
427 return 2;
417 default: return 1; 428 default: return 1;
418 } 429 }
419} 430}
@@ -431,7 +442,8 @@ typedef struct CompileState {
431 442
432/* 443/*
433** code generation is recursive; 'opt' indicates that the code is 444** code generation is recursive; 'opt' indicates that the code is
434** being generated under a 'IChoice' operator jumping to its end. 445** being generated under a 'IChoice' operator jumping to its end
446** (that is, the match is "optional").
435** 'tt' points to a previous test protecting this code. 'fl' is 447** 'tt' points to a previous test protecting this code. 'fl' is
436** the follow set of the pattern. 448** the follow set of the pattern.
437*/ 449*/
@@ -439,7 +451,7 @@ static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
439 const Charset *fl); 451 const Charset *fl);
440 452
441 453
442void reallocprog (lua_State *L, Pattern *p, int nsize) { 454void realloccode (lua_State *L, Pattern *p, int nsize) {
443 void *ud; 455 void *ud;
444 lua_Alloc f = lua_getallocf(L, &ud); 456 lua_Alloc f = lua_getallocf(L, &ud);
445 void *newblock = f(ud, p->code, p->codesize * sizeof(Instruction), 457 void *newblock = f(ud, p->code, p->codesize * sizeof(Instruction),
@@ -454,7 +466,7 @@ void reallocprog (lua_State *L, Pattern *p, int nsize) {
454static int nextinstruction (CompileState *compst) { 466static int nextinstruction (CompileState *compst) {
455 int size = compst->p->codesize; 467 int size = compst->p->codesize;
456 if (compst->ncode >= size) 468 if (compst->ncode >= size)
457 reallocprog(compst->L, compst->p, size * 2); 469 realloccode(compst->L, compst->p, size * 2);
458 return compst->ncode++; 470 return compst->ncode++;
459} 471}
460 472
@@ -470,6 +482,9 @@ static int addinstruction (CompileState *compst, Opcode op, int aux) {
470} 482}
471 483
472 484
485/*
486** Add an instruction followed by space for an offset (to be set later)
487*/
473static int addoffsetinst (CompileState *compst, Opcode op) { 488static int addoffsetinst (CompileState *compst, Opcode op) {
474 int i = addinstruction(compst, op, 0); /* instruction */ 489 int i = addinstruction(compst, op, 0); /* instruction */
475 addinstruction(compst, (Opcode)0, 0); /* open space for offset */ 490 addinstruction(compst, (Opcode)0, 0); /* open space for offset */
@@ -496,7 +511,9 @@ static int addoffsetlabinst (CompileState *compst, Labelset ls) {
496} 511}
497/* labeled failure end */ 512/* labeled failure end */
498 513
499 514/*
515** Set the offset of an instruction
516*/
500static void setoffset (CompileState *compst, int instruction, int offset) { 517static void setoffset (CompileState *compst, int instruction, int offset) {
501 getinstr(compst, instruction + 1).offset = offset; 518 getinstr(compst, instruction + 1).offset = offset;
502} 519}
@@ -505,7 +522,7 @@ static void setoffset (CompileState *compst, int instruction, int offset) {
505/* 522/*
506** Add a capture instruction: 523** Add a capture instruction:
507** 'op' is the capture instruction; 'cap' the capture kind; 524** 'op' is the capture instruction; 'cap' the capture kind;
508** 'key' the key into ktable; 'aux' is optional offset 525** 'key' the key into ktable; 'aux' is the optional capture offset
509** 526**
510*/ 527*/
511static int addinstcap (CompileState *compst, Opcode op, int cap, int key, 528static int addinstcap (CompileState *compst, Opcode op, int cap, int key,
@@ -521,12 +538,18 @@ static int addinstcap (CompileState *compst, Opcode op, int cap, int key,
521#define target(code,i) ((i) + code[i + 1].offset) 538#define target(code,i) ((i) + code[i + 1].offset)
522 539
523 540
541/*
542** Patch 'instruction' to jump to 'target'
543*/
524static void jumptothere (CompileState *compst, int instruction, int target) { 544static void jumptothere (CompileState *compst, int instruction, int target) {
525 if (instruction >= 0) 545 if (instruction >= 0)
526 setoffset(compst, instruction, target - instruction); 546 setoffset(compst, instruction, target - instruction);
527} 547}
528 548
529 549
550/*
551** Patch 'instruction' to jump to current position
552*/
530static void jumptohere (CompileState *compst, int instruction) { 553static void jumptohere (CompileState *compst, int instruction) {
531 jumptothere(compst, instruction, gethere(compst)); 554 jumptothere(compst, instruction, gethere(compst));
532} 555}
@@ -594,7 +617,7 @@ static int codetestset (CompileState *compst, Charset *cs, int e) {
594 else { 617 else {
595 int c = 0; 618 int c = 0;
596 Opcode op = charsettype(cs->cs, &c); 619 Opcode op = charsettype(cs->cs, &c);
597 switch (op) { 620 switch (op) {
598 case IFail: return addoffsetinst(compst, IJmp); /* always jump */ 621 case IFail: return addoffsetinst(compst, IJmp); /* always jump */
599 case IAny: return addoffsetinst(compst, ITestAny); 622 case IAny: return addoffsetinst(compst, ITestAny);
600 case IChar: { 623 case IChar: {
@@ -658,8 +681,7 @@ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
658 Charset cs1, cs2; 681 Charset cs1, cs2;
659 int e1 = getfirst(p1, fullset, &cs1); 682 int e1 = getfirst(p1, fullset, &cs1);
660 if (headfail(p1) || 683 if (headfail(p1) ||
661 (!e1 && (getfirst(p2, fl, &cs2), cs_disjoint(&cs1, &cs2)))) { 684 (!e1 && (getfirst(p2, fl, &cs2), cs_disjoint(&cs1, &cs2)))) {
662 /*if (0) {*/
663 /* <p1 / p2> == test (fail(p1)) -> L1 ; p1 ; jmp L2; L1: p2; L2: */ 685 /* <p1 / p2> == test (fail(p1)) -> L1 ; p1 ; jmp L2; L1: p2; L2: */
664 int test = codetestset(compst, &cs1, 0); 686 int test = codetestset(compst, &cs1, 0);
665 int jmp = NOINST; 687 int jmp = NOINST;
@@ -690,6 +712,7 @@ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
690 } 712 }
691} 713}
692 714
715
693/* labeled failure begin */ 716/* labeled failure begin */
694static void codelabchoice (CompileState *compst, TTree *p1, TTree *p2, int opt, 717static void codelabchoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
695 const Charset *fl, Labelset ls) { 718 const Charset *fl, Labelset ls) {
@@ -707,6 +730,7 @@ static void codelabchoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
707} 730}
708/* labeled failure end */ 731/* labeled failure end */
709 732
733
710/* 734/*
711** And predicate 735** And predicate
712** optimization: fixedlen(p) = n ==> <&p> == <p>; behind n 736** optimization: fixedlen(p) = n ==> <&p> == <p>; behind n
@@ -907,7 +931,8 @@ static int codeseq1 (CompileState *compst, TTree *p1, TTree *p2,
907 931
908/* 932/*
909** Main code-generation function: dispatch to auxiliar functions 933** Main code-generation function: dispatch to auxiliar functions
910** according to kind of tree 934** according to kind of tree. ('needfollow' should return true
935** only for consructions that use 'fl'.)
911*/ 936*/
912static void codegen (CompileState *compst, TTree *tree, int opt, int tt, 937static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
913 const Charset *fl) { 938 const Charset *fl) {
@@ -932,7 +957,7 @@ static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
932 /* codegen(compst, p2, opt, tt, fl); */ 957 /* codegen(compst, p2, opt, tt, fl); */
933 tree = sib2(tree); goto tailcall; 958 tree = sib2(tree); goto tailcall;
934 } 959 }
935 case TThrow: { /* labeled failure */ 960 case TThrow: { /* labeled failure */
936 addthrowinstruction(compst, tree->labels); 961 addthrowinstruction(compst, tree->labels);
937 break; 962 break;
938 } 963 }
@@ -958,6 +983,7 @@ static void peephole (CompileState *compst) {
958 Instruction *code = compst->p->code; 983 Instruction *code = compst->p->code;
959 int i; 984 int i;
960 for (i = 0; i < compst->ncode; i += sizei(&code[i])) { 985 for (i = 0; i < compst->ncode; i += sizei(&code[i])) {
986 redo:
961 switch (code[i].i.code) { 987 switch (code[i].i.code) {
962 case IChoice: case ICall: case ICommit: case IPartialCommit: 988 case IChoice: case ICall: case ICommit: case IPartialCommit:
963 case IBackCommit: case ITestChar: case ITestSet: case ILabChoice: /* labeled failure */ 989 case IBackCommit: case ITestChar: case ITestSet: case ILabChoice: /* labeled failure */
@@ -979,8 +1005,7 @@ static void peephole (CompileState *compst) {
979 int fft = finallabel(code, ft); 1005 int fft = finallabel(code, ft);
980 code[i] = code[ft]; /* jump becomes that instruction... */ 1006 code[i] = code[ft]; /* jump becomes that instruction... */
981 jumptothere(compst, i, fft); /* but must correct its offset */ 1007 jumptothere(compst, i, fft); /* but must correct its offset */
982 i--; /* reoptimize its label */ 1008 goto redo; /* reoptimize its label */
983 break;
984 } 1009 }
985 default: { 1010 default: {
986 jumptothere(compst, i, ft); /* optimize label */ 1011 jumptothere(compst, i, ft); /* optimize label */
@@ -1002,11 +1027,11 @@ static void peephole (CompileState *compst) {
1002Instruction *compile (lua_State *L, Pattern *p) { 1027Instruction *compile (lua_State *L, Pattern *p) {
1003 CompileState compst; 1028 CompileState compst;
1004 compst.p = p; compst.ncode = 0; compst.L = L; 1029 compst.p = p; compst.ncode = 0; compst.L = L;
1005 reallocprog(L, p, 2); /* minimum initial size */ 1030 realloccode(L, p, 2); /* minimum initial size */
1006 codegen(&compst, p->tree, 0, NOINST, fullset); 1031 codegen(&compst, p->tree, 0, NOINST, fullset);
1007 addinstruction(&compst, IEnd, 0); 1032 addinstruction(&compst, IEnd, 0);
1008 reallocprog(L, p, compst.ncode); /* set final size */ 1033 realloccode(L, p, compst.ncode); /* set final size */
1009 peephole(&compst); /* labeled failure */ 1034 peephole(&compst);
1010 return p->code; 1035 return p->code;
1011} 1036}
1012 1037