| ... | @@ -136,6 +136,7 @@ struct RuleTuple { | ... | @@ -136,6 +136,7 @@ struct RuleTuple { |
| 136 | Buf name; | 136 | Buf name; |
| 137 | ZigList<RuleNode *> children; | 137 | ZigList<RuleNode *> children; |
| 138 | Buf body; | 138 | Buf body; |
| | 139 | Buf union_field_name; |
| 139 | }; | 140 | }; |
| 140 | | 141 | |
| 141 | struct RuleMany { | 142 | struct RuleMany { |
| ... | @@ -161,6 +162,9 @@ struct RuleList { | ... | @@ -161,6 +162,9 @@ struct RuleList { |
| 161 | | 162 | |
| 162 | struct RuleSubRule { | 163 | struct RuleSubRule { |
| 163 | RuleNode *child; | 164 | RuleNode *child; |
| | 165 | |
| | 166 | // for lexer use only |
| | 167 | Buf name; |
| 164 | }; | 168 | }; |
| 165 | | 169 | |
| 166 | enum RuleNodeType { | 170 | enum RuleNodeType { |
| ... | @@ -175,6 +179,8 @@ enum RuleNodeType { | ... | @@ -175,6 +179,8 @@ enum RuleNodeType { |
| 175 | | 179 | |
| 176 | struct RuleNode { | 180 | struct RuleNode { |
| 177 | RuleNodeType type; | 181 | RuleNodeType type; |
| | 182 | int lex_line; |
| | 183 | int lex_column; |
| 178 | union { | 184 | union { |
| 179 | RuleTuple tuple; | 185 | RuleTuple tuple; |
| 180 | RuleMany many; | 186 | RuleMany many; |
| ... | @@ -205,6 +211,7 @@ struct CodeGenCapture { | ... | @@ -205,6 +211,7 @@ struct CodeGenCapture { |
| 205 | Buf *body; | 211 | Buf *body; |
| 206 | bool is_root; | 212 | bool is_root; |
| 207 | Buf *field_names; | 213 | Buf *field_names; |
| | 214 | Buf *union_field_name; |
| 208 | }; | 215 | }; |
| 209 | | 216 | |
| 210 | struct CodeGen { | 217 | struct CodeGen { |
| ... | @@ -225,6 +232,8 @@ struct ParserState { | ... | @@ -225,6 +232,8 @@ struct ParserState { |
| 225 | enum LexState { | 232 | enum LexState { |
| 226 | LexStateStart, | 233 | LexStateStart, |
| 227 | LexStateRuleName, | 234 | LexStateRuleName, |
| | 235 | LexStateRuleFieldNameStart, |
| | 236 | LexStateRuleFieldName, |
| 228 | LexStateWaitForColon, | 237 | LexStateWaitForColon, |
| 229 | LexStateTupleRule, | 238 | LexStateTupleRule, |
| 230 | LexStateFnName, | 239 | LexStateFnName, |
| ... | @@ -232,6 +241,7 @@ enum LexState { | ... | @@ -232,6 +241,7 @@ enum LexState { |
| 232 | LexStateToken, | 241 | LexStateToken, |
| 233 | LexStateBody, | 242 | LexStateBody, |
| 234 | LexStateEndOrOr, | 243 | LexStateEndOrOr, |
| | 244 | LexStateSubTupleName, |
| 235 | }; | 245 | }; |
| 236 | | 246 | |
| 237 | struct LexStack { | 247 | struct LexStack { |
| ... | @@ -258,6 +268,8 @@ struct Gen { | ... | @@ -258,6 +268,8 @@ struct Gen { |
| 258 | int lex_token_name_begin; | 268 | int lex_token_name_begin; |
| 259 | int lex_body_begin; | 269 | int lex_body_begin; |
| 260 | int lex_body_end; | 270 | int lex_body_end; |
| | 271 | int lex_sub_tuple_begin; |
| | 272 | int lex_field_name_begin; |
| 261 | }; | 273 | }; |
| 262 | | 274 | |
| 263 | static ParserState *create_state(Gen *g) { | 275 | static ParserState *create_state(Gen *g) { |
| ... | @@ -303,12 +315,13 @@ static void state_add_push_node(ParserState *state) { | ... | @@ -303,12 +315,13 @@ static void state_add_push_node(ParserState *state) { |
| 303 | state_add_code(state, code); | 315 | state_add_code(state, code); |
| 304 | } | 316 | } |
| 305 | | 317 | |
| 306 | static CodeGen *codegen_create_capture(Buf *body, bool is_root, int field_name_count) { | 318 | static CodeGen *codegen_create_capture(Buf *body, bool is_root, int field_name_count, Buf *union_field_name) { |
| 307 | CodeGen *code = allocate<CodeGen>(1); | 319 | CodeGen *code = allocate<CodeGen>(1); |
| 308 | code->type = CodeGenTypeCapture; | 320 | code->type = CodeGenTypeCapture; |
| 309 | code->capture.body = body; | 321 | code->capture.body = body; |
| 310 | code->capture.is_root = is_root; | 322 | code->capture.is_root = is_root; |
| 311 | code->capture.field_names = allocate<Buf>(field_name_count); | 323 | code->capture.field_names = allocate<Buf>(field_name_count); |
| | 324 | code->capture.union_field_name = union_field_name; |
| 312 | return code; | 325 | return code; |
| 313 | } | 326 | } |
| 314 | | 327 | |
| ... | @@ -325,6 +338,7 @@ static void state_add_eat_token(ParserState *state) { | ... | @@ -325,6 +338,7 @@ static void state_add_eat_token(ParserState *state) { |
| 325 | } | 338 | } |
| 326 | | 339 | |
| 327 | static void gen(Gen *g, RuleNode *node, Buf *out_field_name) { | 340 | static void gen(Gen *g, RuleNode *node, Buf *out_field_name) { |
| | 341 | assert(node); |
| 328 | switch (node->type) { | 342 | switch (node->type) { |
| 329 | case RuleNodeTypeToken: | 343 | case RuleNodeTypeToken: |
| 330 | { | 344 | { |
| ... | @@ -346,13 +360,14 @@ static void gen(Gen *g, RuleNode *node, Buf *out_field_name) { | ... | @@ -346,13 +360,14 @@ static void gen(Gen *g, RuleNode *node, Buf *out_field_name) { |
| 346 | break; | 360 | break; |
| 347 | case RuleNodeTypeTuple: | 361 | case RuleNodeTypeTuple: |
| 348 | { | 362 | { |
| 349 | buf_init_from_str(out_field_name, "node"); | 363 | buf_init_from_buf(out_field_name, &node->tuple.union_field_name); |
| 350 | | 364 | |
| 351 | state_add_push_node(g->cur_state); | 365 | state_add_push_node(g->cur_state); |
| 352 | | 366 | |
| 353 | bool is_root = (node == g->root); | 367 | bool is_root = (node == g->root); |
| 354 | int field_name_count = node->tuple.children.length; | 368 | int field_name_count = node->tuple.children.length; |
| 355 | CodeGen *code = codegen_create_capture(&node->tuple.body, is_root, field_name_count); | 369 | CodeGen *code = codegen_create_capture(&node->tuple.body, is_root, field_name_count, |
| | 370 | &node->tuple.union_field_name); |
| 356 | | 371 | |
| 357 | for (int i = 0; i < node->tuple.children.length; i += 1) { | 372 | for (int i = 0; i < node->tuple.children.length; i += 1) { |
| 358 | RuleNode *child = node->tuple.children.at(i); | 373 | RuleNode *child = node->tuple.children.at(i); |
| ... | @@ -411,7 +426,7 @@ static void lex_error(Gen *g, const char *format, ...) { | ... | @@ -411,7 +426,7 @@ static void lex_error(Gen *g, const char *format, ...) { |
| 411 | | 426 | |
| 412 | va_list ap; | 427 | va_list ap; |
| 413 | va_start(ap, format); | 428 | va_start(ap, format); |
| 414 | fprintf(stderr, "Error: Line %d, column %d: ", line, column); | 429 | fprintf(stderr, "Grammar Error: Line %d, column %d: ", line, column); |
| 415 | vfprintf(stderr, format, ap); | 430 | vfprintf(stderr, format, ap); |
| 416 | fprintf(stderr, "\n"); | 431 | fprintf(stderr, "\n"); |
| 417 | va_end(ap); | 432 | va_end(ap); |
| ... | @@ -428,10 +443,16 @@ static void lex_pop_stack(Gen *g) { | ... | @@ -428,10 +443,16 @@ static void lex_pop_stack(Gen *g) { |
| 428 | g->lex_stack.pop(); | 443 | g->lex_stack.pop(); |
| 429 | } | 444 | } |
| 430 | | 445 | |
| | 446 | static RuleNode *create_rule_node(Gen *g) { |
| | 447 | RuleNode *node = allocate<RuleNode>(1); |
| | 448 | node->lex_line = g->lex_line; |
| | 449 | node->lex_column = g->lex_column; |
| | 450 | return node; |
| | 451 | } |
| 431 | | 452 | |
| 432 | static void begin_rule(Gen *g) { | 453 | static void begin_rule(Gen *g) { |
| 433 | assert(!g->lex_cur_rule); | 454 | assert(!g->lex_cur_rule); |
| 434 | g->lex_cur_rule = allocate<RuleNode>(1); | 455 | g->lex_cur_rule = create_rule_node(g); |
| 435 | g->lex_cur_rule->type = RuleNodeTypeTuple; | 456 | g->lex_cur_rule->type = RuleNodeTypeTuple; |
| 436 | g->lex_cur_rule_begin = g->lex_pos; | 457 | g->lex_cur_rule_begin = g->lex_pos; |
| 437 | | 458 | |
| ... | @@ -452,6 +473,18 @@ static void end_rule_name(Gen *g) { | ... | @@ -452,6 +473,18 @@ static void end_rule_name(Gen *g) { |
| 452 | buf_init_from_mem(&g->lex_cur_rule->tuple.name, ptr, len); | 473 | buf_init_from_mem(&g->lex_cur_rule->tuple.name, ptr, len); |
| 453 | } | 474 | } |
| 454 | | 475 | |
| | 476 | static void begin_rule_field_name(Gen *g) { |
| | 477 | assert(g->lex_cur_rule); |
| | 478 | g->lex_field_name_begin = g->lex_pos; |
| | 479 | } |
| | 480 | |
| | 481 | static void end_rule_field_name(Gen *g) { |
| | 482 | assert(g->lex_cur_rule); |
| | 483 | char *ptr = &buf_ptr(g->in_buf)[g->lex_field_name_begin]; |
| | 484 | int len = g->lex_pos - g->lex_field_name_begin; |
| | 485 | buf_init_from_mem(&g->lex_cur_rule->tuple.union_field_name, ptr, len); |
| | 486 | } |
| | 487 | |
| 455 | static void begin_fn_name(Gen *g) { | 488 | static void begin_fn_name(Gen *g) { |
| 456 | g->lex_fn_name_begin = g->lex_pos; | 489 | g->lex_fn_name_begin = g->lex_pos; |
| 457 | lex_push_stack(g); | 490 | lex_push_stack(g); |
| ... | @@ -478,15 +511,13 @@ static void end_token_name(Gen *g) { | ... | @@ -478,15 +511,13 @@ static void end_token_name(Gen *g) { |
| 478 | buf_init_from_mem(&token_name, ptr, len); | 511 | buf_init_from_mem(&token_name, ptr, len); |
| 479 | | 512 | |
| 480 | Token *token = find_or_create_token(g, &token_name); | 513 | Token *token = find_or_create_token(g, &token_name); |
| 481 | RuleNode *node = allocate<RuleNode>(1); | 514 | RuleNode *node = create_rule_node(g); |
| 482 | node->type = RuleNodeTypeToken; | 515 | node->type = RuleNodeTypeToken; |
| 483 | node->token.token = token; | 516 | node->token.token = token; |
| 484 | | 517 | |
| 485 | assert(g->lex_cur_rule->type == RuleNodeTypeTuple); | 518 | assert(g->lex_cur_rule->type == RuleNodeTypeTuple); |
| 486 | g->lex_cur_rule->tuple.children.append(node); | 519 | g->lex_cur_rule->tuple.children.append(node); |
| 487 | | 520 | |
| 488 | g->biggest_tuple_len = max(g->biggest_tuple_len, g->lex_cur_rule->tuple.children.length); | | |
| 489 | | | |
| 490 | | 521 | |
| 491 | lex_pop_stack(g); | 522 | lex_pop_stack(g); |
| 492 | } | 523 | } |
| ... | @@ -504,6 +535,36 @@ static void end_tuple_body(Gen *g) { | ... | @@ -504,6 +535,36 @@ static void end_tuple_body(Gen *g) { |
| 504 | buf_init_from_mem(&g->lex_cur_rule->tuple.body, ptr, len); | 535 | buf_init_from_mem(&g->lex_cur_rule->tuple.body, ptr, len); |
| 505 | } | 536 | } |
| 506 | | 537 | |
| | 538 | static void begin_sub_tuple(Gen *g) { |
| | 539 | g->lex_sub_tuple_begin = g->lex_pos; |
| | 540 | lex_push_stack(g); |
| | 541 | } |
| | 542 | |
| | 543 | static void end_sub_tuple(Gen *g) { |
| | 544 | assert(g->lex_cur_rule->type == RuleNodeTypeTuple); |
| | 545 | char *ptr = &buf_ptr(g->in_buf)[g->lex_sub_tuple_begin]; |
| | 546 | int len = g->lex_pos - g->lex_sub_tuple_begin; |
| | 547 | |
| | 548 | RuleNode *node = create_rule_node(g); |
| | 549 | node->type = RuleNodeTypeSubRule; |
| | 550 | buf_init_from_mem(&node->sub_rule.name, ptr, len); |
| | 551 | |
| | 552 | g->lex_cur_rule->tuple.children.append(node); |
| | 553 | |
| | 554 | lex_pop_stack(g); |
| | 555 | } |
| | 556 | |
| | 557 | static RuleNode *find_rule_node(Gen *g, Buf *name) { |
| | 558 | for (int i = 0; i < g->rules.length; i += 1) { |
| | 559 | RuleNode *node = g->rules.at(i); |
| | 560 | assert(node->type == RuleNodeTypeTuple); |
| | 561 | if (buf_eql_buf(&node->tuple.name, name)) { |
| | 562 | return node; |
| | 563 | } |
| | 564 | } |
| | 565 | return nullptr; |
| | 566 | } |
| | 567 | |
| 507 | static void initialize_rules(Gen *g) { | 568 | static void initialize_rules(Gen *g) { |
| 508 | g->lex_state = LexStateStart; | 569 | g->lex_state = LexStateStart; |
| 509 | for (g->lex_pos = 0; g->lex_pos < buf_len(g->in_buf); g->lex_pos += 1) { | 570 | for (g->lex_pos = 0; g->lex_pos < buf_len(g->in_buf); g->lex_pos += 1) { |
| ... | @@ -524,18 +585,36 @@ static void initialize_rules(Gen *g) { | ... | @@ -524,18 +585,36 @@ static void initialize_rules(Gen *g) { |
| 524 | break; | 585 | break; |
| 525 | case LexStateRuleName: | 586 | case LexStateRuleName: |
| 526 | switch (c) { | 587 | switch (c) { |
| 527 | case WHITESPACE: | 588 | case '<': |
| 528 | end_rule_name(g); | 589 | end_rule_name(g); |
| 529 | g->lex_state = LexStateWaitForColon; | 590 | g->lex_state = LexStateRuleFieldNameStart; |
| 530 | break; | 591 | break; |
| 531 | case ':': | 592 | case SYMBOL_CHAR: |
| 532 | end_rule_name(g); | 593 | // ok |
| 533 | g->lex_state = LexStateTupleRule; | | |
| 534 | break; | 594 | break; |
| | 595 | default: |
| | 596 | lex_error(g, "expected '<', not '%c'", c); |
| | 597 | } |
| | 598 | break; |
| | 599 | case LexStateRuleFieldNameStart: |
| | 600 | switch (c) { |
| 535 | case SYMBOL_CHAR: | 601 | case SYMBOL_CHAR: |
| | 602 | begin_rule_field_name(g); |
| | 603 | g->lex_state = LexStateRuleFieldName; |
| 536 | break; | 604 | break; |
| 537 | default: | 605 | default: |
| 538 | lex_error(g, "invalid char: '%c'", c); | 606 | lex_error(g, "expected field name, not '%c'", c); |
| | 607 | } |
| | 608 | break; |
| | 609 | case LexStateRuleFieldName: |
| | 610 | switch (c) { |
| | 611 | case SYMBOL_CHAR: |
| | 612 | // ok |
| | 613 | break; |
| | 614 | case '>': |
| | 615 | end_rule_field_name(g); |
| | 616 | g->lex_state = LexStateWaitForColon; |
| | 617 | break; |
| 539 | } | 618 | } |
| 540 | break; | 619 | break; |
| 541 | case LexStateWaitForColon: | 620 | case LexStateWaitForColon: |
| ... | @@ -559,12 +638,16 @@ static void initialize_rules(Gen *g) { | ... | @@ -559,12 +638,16 @@ static void initialize_rules(Gen *g) { |
| 559 | begin_fn_name(g); | 638 | begin_fn_name(g); |
| 560 | g->lex_state = LexStateFnName; | 639 | g->lex_state = LexStateFnName; |
| 561 | break; | 640 | break; |
| | 641 | case UPPER_ALPHA: |
| | 642 | begin_sub_tuple(g); |
| | 643 | g->lex_state = LexStateSubTupleName; |
| | 644 | break; |
| 562 | case '{': | 645 | case '{': |
| 563 | begin_tuple_body(g); | 646 | begin_tuple_body(g); |
| 564 | g->lex_state = LexStateBody; | 647 | g->lex_state = LexStateBody; |
| 565 | break; | 648 | break; |
| 566 | default: | 649 | default: |
| 567 | lex_error(g, "invalid char: '%c'", c); | 650 | lex_error(g, "expected rule, not '%c'", c); |
| 568 | } | 651 | } |
| 569 | break; | 652 | break; |
| 570 | case LexStateFnName: | 653 | case LexStateFnName: |
| ... | @@ -589,7 +672,7 @@ static void initialize_rules(Gen *g) { | ... | @@ -589,7 +672,7 @@ static void initialize_rules(Gen *g) { |
| 589 | g->lex_state = LexStateToken; | 672 | g->lex_state = LexStateToken; |
| 590 | break; | 673 | break; |
| 591 | default: | 674 | default: |
| 592 | lex_error(g, "invalid char '%c'", c); | 675 | lex_error(g, "expected token name, not '%c'", c); |
| 593 | } | 676 | } |
| 594 | break; | 677 | break; |
| 595 | case LexStateToken: | 678 | case LexStateToken: |
| ... | @@ -601,7 +684,7 @@ static void initialize_rules(Gen *g) { | ... | @@ -601,7 +684,7 @@ static void initialize_rules(Gen *g) { |
| 601 | end_token_name(g); | 684 | end_token_name(g); |
| 602 | break; | 685 | break; |
| 603 | default: | 686 | default: |
| 604 | lex_error(g, "invalid char '%c'", c); | 687 | lex_error(g, "expected token name or ')', not '%c'", c); |
| 605 | } | 688 | } |
| 606 | break; | 689 | break; |
| 607 | case LexStateBody: | 690 | case LexStateBody: |
| ... | @@ -627,6 +710,20 @@ static void initialize_rules(Gen *g) { | ... | @@ -627,6 +710,20 @@ static void initialize_rules(Gen *g) { |
| 627 | default: | 710 | default: |
| 628 | lex_error(g, "expected ';' or '|'"); | 711 | lex_error(g, "expected ';' or '|'"); |
| 629 | } | 712 | } |
| | 713 | break; |
| | 714 | case LexStateSubTupleName: |
| | 715 | switch (c) { |
| | 716 | case ALPHA: |
| | 717 | // ignore |
| | 718 | break; |
| | 719 | case WHITESPACE: |
| | 720 | end_sub_tuple(g); |
| | 721 | assert(g->lex_state == LexStateTupleRule); |
| | 722 | break; |
| | 723 | default: |
| | 724 | lex_error(g, "expected rule name, not '%c'", c); |
| | 725 | } |
| | 726 | break; |
| 630 | } | 727 | } |
| 631 | if (c == '\n') { | 728 | if (c == '\n') { |
| 632 | g->lex_line += 1; | 729 | g->lex_line += 1; |
| ... | @@ -647,9 +744,40 @@ static void initialize_rules(Gen *g) { | ... | @@ -647,9 +744,40 @@ static void initialize_rules(Gen *g) { |
| 647 | case LexStateTokenStart: | 744 | case LexStateTokenStart: |
| 648 | case LexStateToken: | 745 | case LexStateToken: |
| 649 | case LexStateBody: | 746 | case LexStateBody: |
| | 747 | case LexStateSubTupleName: |
| | 748 | case LexStateRuleFieldNameStart: |
| | 749 | case LexStateRuleFieldName: |
| 650 | lex_error(g, "unexpected EOF"); | 750 | lex_error(g, "unexpected EOF"); |
| 651 | break; | 751 | break; |
| 652 | } | 752 | } |
| | 753 | |
| | 754 | // Resolve child references into pointers |
| | 755 | for (int tuple_i = 0; tuple_i < g->rules.length; tuple_i += 1) { |
| | 756 | RuleNode *node = g->rules.at(tuple_i); |
| | 757 | assert(node->type == RuleNodeTypeTuple); |
| | 758 | |
| | 759 | for (int child_i = 0; child_i < node->tuple.children.length; child_i += 1) { |
| | 760 | RuleNode *child = node->tuple.children.at(child_i); |
| | 761 | if (child->type == RuleNodeTypeSubRule) { |
| | 762 | int line = child->lex_line + 1; |
| | 763 | int column = child->lex_column + 1; |
| | 764 | RuleNode *referenced_node = find_rule_node(g, &child->sub_rule.name); |
| | 765 | if (!referenced_node) { |
| | 766 | fprintf(stderr, "Grammar Error: Line %d, column %d: Rule not defined: '%s'\n", |
| | 767 | line, column, buf_ptr(&child->sub_rule.name)); |
| | 768 | } |
| | 769 | child->sub_rule.child = referenced_node; |
| | 770 | } |
| | 771 | } |
| | 772 | } |
| | 773 | |
| | 774 | |
| | 775 | // calculate the biggest tuple len |
| | 776 | for (int i = 0; i < g->rules.length; i += 1) { |
| | 777 | RuleNode *node = g->rules.at(i); |
| | 778 | assert(node->type == RuleNodeTypeTuple); |
| | 779 | g->biggest_tuple_len = max(g->biggest_tuple_len, node->tuple.children.length); |
| | 780 | } |
| 653 | } | 781 | } |
| 654 | | 782 | |
| 655 | enum TemplateState { | 783 | enum TemplateState { |
| ... | @@ -828,6 +956,8 @@ int main(int argc, char **argv) { | ... | @@ -828,6 +956,8 @@ int main(int argc, char **argv) { |
| 828 | fprintf(out_f, " state = transition[%d][token->id];\n", state->index); | 956 | fprintf(out_f, " state = transition[%d][token->id];\n", state->index); |
| 829 | break; | 957 | break; |
| 830 | case CodeGenTypeError: | 958 | case CodeGenTypeError: |
| | 959 | fprintf(out_f, " token_index -= 1;\n"); |
| | 960 | fprintf(out_f, " token = &tokens->at(token_index);\n"); |
| 831 | fprintf(out_f, " ast_error(token, \"%s\");\n", buf_ptr(code->error.msg)); | 961 | fprintf(out_f, " ast_error(token, \"%s\");\n", buf_ptr(code->error.msg)); |
| 832 | break; | 962 | break; |
| 833 | case CodeGenTypeSave: | 963 | case CodeGenTypeSave: |
| ... | @@ -843,7 +973,12 @@ int main(int argc, char **argv) { | ... | @@ -843,7 +973,12 @@ int main(int argc, char **argv) { |
| 843 | fprintf(out_f, "%s\n", buf_ptr(code_text)); | 973 | fprintf(out_f, "%s\n", buf_ptr(code_text)); |
| 844 | fprintf(out_f, " return root;\n"); | 974 | fprintf(out_f, " return root;\n"); |
| 845 | } else { | 975 | } else { |
| 846 | zig_panic("TODO capture non-root"); | 976 | fprintf(out_f, " ParserGenNode *parent_node = stack.at(stack.length - 2);\n"); |
| | 977 | Buf *dest = buf_sprintf("parent_node->data[parent_node->next_index++].%s", |
| | 978 | buf_ptr(code->capture.union_field_name)); |
| | 979 | Buf *code_text = fill_template(code->capture.body, buf_ptr(dest), |
| | 980 | code->capture.field_names); |
| | 981 | fprintf(out_f, "%s\n", buf_ptr(code_text)); |
| 847 | } | 982 | } |
| 848 | break; | 983 | break; |
| 849 | case CodeGenTypePopNode: | 984 | case CodeGenTypePopNode: |