prism 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -1
- data/Makefile +5 -5
- data/README.md +2 -2
- data/config.yml +26 -13
- data/docs/build_system.md +6 -6
- data/docs/building.md +1 -1
- data/docs/configuration.md +1 -0
- data/docs/encoding.md +68 -32
- data/docs/heredocs.md +1 -1
- data/docs/javascript.md +29 -1
- data/docs/releasing.md +4 -1
- data/docs/ruby_api.md +14 -0
- data/ext/prism/api_node.c +74 -45
- data/ext/prism/extconf.rb +91 -127
- data/ext/prism/extension.c +4 -1
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +148 -133
- data/include/prism/diagnostic.h +27 -1
- data/include/prism/enc/pm_encoding.h +42 -1
- data/include/prism/parser.h +6 -0
- data/include/prism/version.h +2 -2
- data/lib/prism/compiler.rb +3 -3
- data/lib/prism/debug.rb +4 -0
- data/lib/prism/desugar_compiler.rb +1 -0
- data/lib/prism/dispatcher.rb +14 -14
- data/lib/prism/dot_visitor.rb +4334 -0
- data/lib/prism/dsl.rb +11 -11
- data/lib/prism/ffi.rb +3 -3
- data/lib/prism/mutation_compiler.rb +6 -6
- data/lib/prism/node.rb +182 -113
- data/lib/prism/node_ext.rb +61 -3
- data/lib/prism/parse_result.rb +46 -12
- data/lib/prism/serialize.rb +124 -130
- data/lib/prism/visitor.rb +3 -3
- data/lib/prism.rb +1 -0
- data/prism.gemspec +5 -1
- data/rbi/prism.rbi +5565 -5540
- data/rbi/prism_static.rbi +138 -142
- data/sig/prism.rbs +47 -32
- data/src/diagnostic.c +61 -3
- data/src/enc/pm_big5.c +63 -0
- data/src/enc/pm_cp51932.c +57 -0
- data/src/enc/pm_euc_jp.c +10 -0
- data/src/enc/pm_gbk.c +5 -2
- data/src/enc/pm_tables.c +1478 -148
- data/src/node.c +33 -21
- data/src/prettyprint.c +1027 -925
- data/src/prism.c +925 -374
- data/src/regexp.c +12 -12
- data/src/serialize.c +36 -9
- metadata +6 -2
    
        data/ext/prism/api_node.c
    CHANGED
    
    | @@ -36,6 +36,7 @@ static VALUE rb_cPrismCallNode; | |
| 36 36 | 
             
            static VALUE rb_cPrismCallOperatorWriteNode;
         | 
| 37 37 | 
             
            static VALUE rb_cPrismCallOrWriteNode;
         | 
| 38 38 | 
             
            static VALUE rb_cPrismCapturePatternNode;
         | 
| 39 | 
            +
            static VALUE rb_cPrismCaseMatchNode;
         | 
| 39 40 | 
             
            static VALUE rb_cPrismCaseNode;
         | 
| 40 41 | 
             
            static VALUE rb_cPrismClassNode;
         | 
| 41 42 | 
             
            static VALUE rb_cPrismClassVariableAndWriteNode;
         | 
| @@ -146,7 +147,6 @@ static VALUE rb_cPrismSourceFileNode; | |
| 146 147 | 
             
            static VALUE rb_cPrismSourceLineNode;
         | 
| 147 148 | 
             
            static VALUE rb_cPrismSplatNode;
         | 
| 148 149 | 
             
            static VALUE rb_cPrismStatementsNode;
         | 
| 149 | 
            -
            static VALUE rb_cPrismStringConcatNode;
         | 
| 150 150 | 
             
            static VALUE rb_cPrismStringNode;
         | 
| 151 151 | 
             
            static VALUE rb_cPrismSuperNode;
         | 
| 152 152 | 
             
            static VALUE rb_cPrismSymbolNode;
         | 
| @@ -403,6 +403,16 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 403 403 | 
             
                                pm_node_stack_push(&node_stack, (pm_node_t *) cast->target);
         | 
| 404 404 | 
             
                                break;
         | 
| 405 405 | 
             
                            }
         | 
| 406 | 
            +
            #line 118 "api_node.c.erb"
         | 
| 407 | 
            +
                            case PM_CASE_MATCH_NODE: {
         | 
| 408 | 
            +
                                pm_case_match_node_t *cast = (pm_case_match_node_t *) node;
         | 
| 409 | 
            +
                                pm_node_stack_push(&node_stack, (pm_node_t *) cast->predicate);
         | 
| 410 | 
            +
                                for (size_t index = 0; index < cast->conditions.size; index++) {
         | 
| 411 | 
            +
                                    pm_node_stack_push(&node_stack, (pm_node_t *) cast->conditions.nodes[index]);
         | 
| 412 | 
            +
                                }
         | 
| 413 | 
            +
                                pm_node_stack_push(&node_stack, (pm_node_t *) cast->consequent);
         | 
| 414 | 
            +
                                break;
         | 
| 415 | 
            +
                            }
         | 
| 406 416 | 
             
            #line 118 "api_node.c.erb"
         | 
| 407 417 | 
             
                            case PM_CASE_NODE: {
         | 
| 408 418 | 
             
                                pm_case_node_t *cast = (pm_case_node_t *) node;
         | 
| @@ -798,6 +808,9 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 798 808 | 
             
                            case PM_MATCH_WRITE_NODE: {
         | 
| 799 809 | 
             
                                pm_match_write_node_t *cast = (pm_match_write_node_t *) node;
         | 
| 800 810 | 
             
                                pm_node_stack_push(&node_stack, (pm_node_t *) cast->call);
         | 
| 811 | 
            +
                                for (size_t index = 0; index < cast->targets.size; index++) {
         | 
| 812 | 
            +
                                    pm_node_stack_push(&node_stack, (pm_node_t *) cast->targets.nodes[index]);
         | 
| 813 | 
            +
                                }
         | 
| 801 814 | 
             
                                break;
         | 
| 802 815 | 
             
                            }
         | 
| 803 816 | 
             
            #line 118 "api_node.c.erb"
         | 
| @@ -971,13 +984,6 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 971 984 | 
             
                                }
         | 
| 972 985 | 
             
                                break;
         | 
| 973 986 | 
             
                            }
         | 
| 974 | 
            -
            #line 118 "api_node.c.erb"
         | 
| 975 | 
            -
                            case PM_STRING_CONCAT_NODE: {
         | 
| 976 | 
            -
                                pm_string_concat_node_t *cast = (pm_string_concat_node_t *) node;
         | 
| 977 | 
            -
                                pm_node_stack_push(&node_stack, (pm_node_t *) cast->left);
         | 
| 978 | 
            -
                                pm_node_stack_push(&node_stack, (pm_node_t *) cast->right);
         | 
| 979 | 
            -
                                break;
         | 
| 980 | 
            -
                            }
         | 
| 981 987 | 
             
            #line 118 "api_node.c.erb"
         | 
| 982 988 | 
             
                            case PM_SUPER_NODE: {
         | 
| 983 989 | 
             
                                pm_super_node_t *cast = (pm_super_node_t *) node;
         | 
| @@ -1664,6 +1670,40 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 1664 1670 | 
             
                                rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cPrismCapturePatternNode));
         | 
| 1665 1671 | 
             
                                break;
         | 
| 1666 1672 | 
             
                            }
         | 
| 1673 | 
            +
            #line 144 "api_node.c.erb"
         | 
| 1674 | 
            +
                            case PM_CASE_MATCH_NODE: {
         | 
| 1675 | 
            +
                                pm_case_match_node_t *cast = (pm_case_match_node_t *) node;
         | 
| 1676 | 
            +
                                VALUE argv[6];
         | 
| 1677 | 
            +
             | 
| 1678 | 
            +
                                // predicate
         | 
| 1679 | 
            +
            #line 155 "api_node.c.erb"
         | 
| 1680 | 
            +
                                argv[0] = rb_ary_pop(value_stack);
         | 
| 1681 | 
            +
             | 
| 1682 | 
            +
                                // conditions
         | 
| 1683 | 
            +
            #line 158 "api_node.c.erb"
         | 
| 1684 | 
            +
                                argv[1] = rb_ary_new_capa(cast->conditions.size);
         | 
| 1685 | 
            +
                                for (size_t index = 0; index < cast->conditions.size; index++) {
         | 
| 1686 | 
            +
                                    rb_ary_push(argv[1], rb_ary_pop(value_stack));
         | 
| 1687 | 
            +
                                }
         | 
| 1688 | 
            +
             | 
| 1689 | 
            +
                                // consequent
         | 
| 1690 | 
            +
            #line 155 "api_node.c.erb"
         | 
| 1691 | 
            +
                                argv[2] = rb_ary_pop(value_stack);
         | 
| 1692 | 
            +
             | 
| 1693 | 
            +
                                // case_keyword_loc
         | 
| 1694 | 
            +
            #line 180 "api_node.c.erb"
         | 
| 1695 | 
            +
                                argv[3] = pm_location_new(parser, cast->case_keyword_loc.start, cast->case_keyword_loc.end, source);
         | 
| 1696 | 
            +
             | 
| 1697 | 
            +
                                // end_keyword_loc
         | 
| 1698 | 
            +
            #line 180 "api_node.c.erb"
         | 
| 1699 | 
            +
                                argv[4] = pm_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source);
         | 
| 1700 | 
            +
             | 
| 1701 | 
            +
                                // location
         | 
| 1702 | 
            +
                                argv[5] = pm_location_new(parser, node->location.start, node->location.end, source);
         | 
| 1703 | 
            +
             | 
| 1704 | 
            +
                                rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cPrismCaseMatchNode));
         | 
| 1705 | 
            +
                                break;
         | 
| 1706 | 
            +
                            }
         | 
| 1667 1707 | 
             
            #line 144 "api_node.c.erb"
         | 
| 1668 1708 | 
             
                            case PM_CASE_NODE: {
         | 
| 1669 1709 | 
             
                                pm_case_node_t *cast = (pm_case_node_t *) node;
         | 
| @@ -2736,7 +2776,7 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 2736 2776 | 
             
            #line 144 "api_node.c.erb"
         | 
| 2737 2777 | 
             
                            case PM_IF_NODE: {
         | 
| 2738 2778 | 
             
                                pm_if_node_t *cast = (pm_if_node_t *) node;
         | 
| 2739 | 
            -
                                VALUE argv[ | 
| 2779 | 
            +
                                VALUE argv[7];
         | 
| 2740 2780 |  | 
| 2741 2781 | 
             
                                // if_keyword_loc
         | 
| 2742 2782 | 
             
            #line 183 "api_node.c.erb"
         | 
| @@ -2746,22 +2786,26 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 2746 2786 | 
             
            #line 155 "api_node.c.erb"
         | 
| 2747 2787 | 
             
                                argv[1] = rb_ary_pop(value_stack);
         | 
| 2748 2788 |  | 
| 2789 | 
            +
                                // then_keyword_loc
         | 
| 2790 | 
            +
            #line 183 "api_node.c.erb"
         | 
| 2791 | 
            +
                                argv[2] = cast->then_keyword_loc.start == NULL ? Qnil : pm_location_new(parser, cast->then_keyword_loc.start, cast->then_keyword_loc.end, source);
         | 
| 2792 | 
            +
             | 
| 2749 2793 | 
             
                                // statements
         | 
| 2750 2794 | 
             
            #line 155 "api_node.c.erb"
         | 
| 2751 | 
            -
                                argv[ | 
| 2795 | 
            +
                                argv[3] = rb_ary_pop(value_stack);
         | 
| 2752 2796 |  | 
| 2753 2797 | 
             
                                // consequent
         | 
| 2754 2798 | 
             
            #line 155 "api_node.c.erb"
         | 
| 2755 | 
            -
                                argv[ | 
| 2799 | 
            +
                                argv[4] = rb_ary_pop(value_stack);
         | 
| 2756 2800 |  | 
| 2757 2801 | 
             
                                // end_keyword_loc
         | 
| 2758 2802 | 
             
            #line 183 "api_node.c.erb"
         | 
| 2759 | 
            -
                                argv[ | 
| 2803 | 
            +
                                argv[5] = cast->end_keyword_loc.start == NULL ? Qnil : pm_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source);
         | 
| 2760 2804 |  | 
| 2761 2805 | 
             
                                // location
         | 
| 2762 | 
            -
                                argv[ | 
| 2806 | 
            +
                                argv[6] = pm_location_new(parser, node->location.start, node->location.end, source);
         | 
| 2763 2807 |  | 
| 2764 | 
            -
                                rb_ary_push(value_stack, rb_class_new_instance( | 
| 2808 | 
            +
                                rb_ary_push(value_stack, rb_class_new_instance(7, argv, rb_cPrismIfNode));
         | 
| 2765 2809 | 
             
                                break;
         | 
| 2766 2810 | 
             
                            }
         | 
| 2767 2811 | 
             
            #line 144 "api_node.c.erb"
         | 
| @@ -3604,12 +3648,11 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 3604 3648 | 
             
            #line 155 "api_node.c.erb"
         | 
| 3605 3649 | 
             
                                argv[0] = rb_ary_pop(value_stack);
         | 
| 3606 3650 |  | 
| 3607 | 
            -
                                //  | 
| 3608 | 
            -
            #line  | 
| 3609 | 
            -
                                argv[1] = rb_ary_new_capa(cast-> | 
| 3610 | 
            -
                                for (size_t index = 0; index < cast-> | 
| 3611 | 
            -
                                     | 
| 3612 | 
            -
                                    rb_ary_push(argv[1], rb_id2sym(constants[cast->locals.ids[index] - 1]));
         | 
| 3651 | 
            +
                                // targets
         | 
| 3652 | 
            +
            #line 158 "api_node.c.erb"
         | 
| 3653 | 
            +
                                argv[1] = rb_ary_new_capa(cast->targets.size);
         | 
| 3654 | 
            +
                                for (size_t index = 0; index < cast->targets.size; index++) {
         | 
| 3655 | 
            +
                                    rb_ary_push(argv[1], rb_ary_pop(value_stack));
         | 
| 3613 3656 | 
             
                                }
         | 
| 3614 3657 |  | 
| 3615 3658 | 
             
                                // location
         | 
| @@ -4436,24 +4479,6 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 4436 4479 | 
             
                                rb_ary_push(value_stack, rb_class_new_instance(2, argv, rb_cPrismStatementsNode));
         | 
| 4437 4480 | 
             
                                break;
         | 
| 4438 4481 | 
             
                            }
         | 
| 4439 | 
            -
            #line 144 "api_node.c.erb"
         | 
| 4440 | 
            -
                            case PM_STRING_CONCAT_NODE: {
         | 
| 4441 | 
            -
                                VALUE argv[3];
         | 
| 4442 | 
            -
             | 
| 4443 | 
            -
                                // left
         | 
| 4444 | 
            -
            #line 155 "api_node.c.erb"
         | 
| 4445 | 
            -
                                argv[0] = rb_ary_pop(value_stack);
         | 
| 4446 | 
            -
             | 
| 4447 | 
            -
                                // right
         | 
| 4448 | 
            -
            #line 155 "api_node.c.erb"
         | 
| 4449 | 
            -
                                argv[1] = rb_ary_pop(value_stack);
         | 
| 4450 | 
            -
             | 
| 4451 | 
            -
                                // location
         | 
| 4452 | 
            -
                                argv[2] = pm_location_new(parser, node->location.start, node->location.end, source);
         | 
| 4453 | 
            -
             | 
| 4454 | 
            -
                                rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cPrismStringConcatNode));
         | 
| 4455 | 
            -
                                break;
         | 
| 4456 | 
            -
                            }
         | 
| 4457 4482 | 
             
            #line 144 "api_node.c.erb"
         | 
| 4458 4483 | 
             
                            case PM_STRING_NODE: {
         | 
| 4459 4484 | 
             
                                pm_string_node_t *cast = (pm_string_node_t *) node;
         | 
| @@ -4578,7 +4603,7 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 4578 4603 | 
             
            #line 144 "api_node.c.erb"
         | 
| 4579 4604 | 
             
                            case PM_UNLESS_NODE: {
         | 
| 4580 4605 | 
             
                                pm_unless_node_t *cast = (pm_unless_node_t *) node;
         | 
| 4581 | 
            -
                                VALUE argv[ | 
| 4606 | 
            +
                                VALUE argv[7];
         | 
| 4582 4607 |  | 
| 4583 4608 | 
             
                                // keyword_loc
         | 
| 4584 4609 | 
             
            #line 180 "api_node.c.erb"
         | 
| @@ -4588,22 +4613,26 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) { | |
| 4588 4613 | 
             
            #line 155 "api_node.c.erb"
         | 
| 4589 4614 | 
             
                                argv[1] = rb_ary_pop(value_stack);
         | 
| 4590 4615 |  | 
| 4616 | 
            +
                                // then_keyword_loc
         | 
| 4617 | 
            +
            #line 183 "api_node.c.erb"
         | 
| 4618 | 
            +
                                argv[2] = cast->then_keyword_loc.start == NULL ? Qnil : pm_location_new(parser, cast->then_keyword_loc.start, cast->then_keyword_loc.end, source);
         | 
| 4619 | 
            +
             | 
| 4591 4620 | 
             
                                // statements
         | 
| 4592 4621 | 
             
            #line 155 "api_node.c.erb"
         | 
| 4593 | 
            -
                                argv[ | 
| 4622 | 
            +
                                argv[3] = rb_ary_pop(value_stack);
         | 
| 4594 4623 |  | 
| 4595 4624 | 
             
                                // consequent
         | 
| 4596 4625 | 
             
            #line 155 "api_node.c.erb"
         | 
| 4597 | 
            -
                                argv[ | 
| 4626 | 
            +
                                argv[4] = rb_ary_pop(value_stack);
         | 
| 4598 4627 |  | 
| 4599 4628 | 
             
                                // end_keyword_loc
         | 
| 4600 4629 | 
             
            #line 183 "api_node.c.erb"
         | 
| 4601 | 
            -
                                argv[ | 
| 4630 | 
            +
                                argv[5] = cast->end_keyword_loc.start == NULL ? Qnil : pm_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source);
         | 
| 4602 4631 |  | 
| 4603 4632 | 
             
                                // location
         | 
| 4604 | 
            -
                                argv[ | 
| 4633 | 
            +
                                argv[6] = pm_location_new(parser, node->location.start, node->location.end, source);
         | 
| 4605 4634 |  | 
| 4606 | 
            -
                                rb_ary_push(value_stack, rb_class_new_instance( | 
| 4635 | 
            +
                                rb_ary_push(value_stack, rb_class_new_instance(7, argv, rb_cPrismUnlessNode));
         | 
| 4607 4636 | 
             
                                break;
         | 
| 4608 4637 | 
             
                            }
         | 
| 4609 4638 | 
             
            #line 144 "api_node.c.erb"
         | 
| @@ -4783,6 +4812,7 @@ Init_prism_api_node(void) { | |
| 4783 4812 | 
             
                rb_cPrismCallOperatorWriteNode = rb_define_class_under(rb_cPrism, "CallOperatorWriteNode", rb_cPrismNode);
         | 
| 4784 4813 | 
             
                rb_cPrismCallOrWriteNode = rb_define_class_under(rb_cPrism, "CallOrWriteNode", rb_cPrismNode);
         | 
| 4785 4814 | 
             
                rb_cPrismCapturePatternNode = rb_define_class_under(rb_cPrism, "CapturePatternNode", rb_cPrismNode);
         | 
| 4815 | 
            +
                rb_cPrismCaseMatchNode = rb_define_class_under(rb_cPrism, "CaseMatchNode", rb_cPrismNode);
         | 
| 4786 4816 | 
             
                rb_cPrismCaseNode = rb_define_class_under(rb_cPrism, "CaseNode", rb_cPrismNode);
         | 
| 4787 4817 | 
             
                rb_cPrismClassNode = rb_define_class_under(rb_cPrism, "ClassNode", rb_cPrismNode);
         | 
| 4788 4818 | 
             
                rb_cPrismClassVariableAndWriteNode = rb_define_class_under(rb_cPrism, "ClassVariableAndWriteNode", rb_cPrismNode);
         | 
| @@ -4893,7 +4923,6 @@ Init_prism_api_node(void) { | |
| 4893 4923 | 
             
                rb_cPrismSourceLineNode = rb_define_class_under(rb_cPrism, "SourceLineNode", rb_cPrismNode);
         | 
| 4894 4924 | 
             
                rb_cPrismSplatNode = rb_define_class_under(rb_cPrism, "SplatNode", rb_cPrismNode);
         | 
| 4895 4925 | 
             
                rb_cPrismStatementsNode = rb_define_class_under(rb_cPrism, "StatementsNode", rb_cPrismNode);
         | 
| 4896 | 
            -
                rb_cPrismStringConcatNode = rb_define_class_under(rb_cPrism, "StringConcatNode", rb_cPrismNode);
         | 
| 4897 4926 | 
             
                rb_cPrismStringNode = rb_define_class_under(rb_cPrism, "StringNode", rb_cPrismNode);
         | 
| 4898 4927 | 
             
                rb_cPrismSuperNode = rb_define_class_under(rb_cPrism, "SuperNode", rb_cPrismNode);
         | 
| 4899 4928 | 
             
                rb_cPrismSymbolNode = rb_define_class_under(rb_cPrism, "SymbolNode", rb_cPrismNode);
         | 
    
        data/ext/prism/extconf.rb
    CHANGED
    
    | @@ -1,136 +1,100 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            if ARGV.delete("--help")
         | 
| 4 | 
            +
              print(<<~TEXT)
         | 
| 5 | 
            +
                USAGE: ruby #{$PROGRAM_NAME} [options]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  Flags that are always valid:
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                      --enable-debug-mode-build
         | 
| 10 | 
            +
                          Enable debug mode build.
         | 
| 11 | 
            +
                          You may also use set PRISM_DEBUG_MODE_BUILD environment variable.
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                      --help
         | 
| 14 | 
            +
                          Display this message.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  Environment variables used:
         | 
| 4 17 |  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
                    create_makefile("prism/prism")
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                    if static_link?
         | 
| 25 | 
            -
                      File.open('Makefile', 'a') do |mf|
         | 
| 26 | 
            -
                        mf.puts
         | 
| 27 | 
            -
                        mf.puts '# Automatically rebuild the extension if librubyparser.a changed'
         | 
| 28 | 
            -
                        mf.puts '$(TARGET_SO): $(LOCAL_LIBS)'
         | 
| 29 | 
            -
                      end
         | 
| 30 | 
            -
                    end
         | 
| 31 | 
            -
                  end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                  def configure_c_extension
         | 
| 34 | 
            -
                    append_cflags("-DPRISM_DEBUG_MODE_BUILD") if debug_mode_build?
         | 
| 35 | 
            -
                    append_cflags("-fvisibility=hidden")
         | 
| 36 | 
            -
                  end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  def configure_rubyparser
         | 
| 39 | 
            -
                    if static_link?
         | 
| 40 | 
            -
                      static_archive_path = File.join(build_dir, "librubyparser.a")
         | 
| 41 | 
            -
                      unless File.exist?(static_archive_path)
         | 
| 42 | 
            -
                        build_static_rubyparser
         | 
| 43 | 
            -
                      end
         | 
| 44 | 
            -
                      $LOCAL_LIBS << " #{static_archive_path}"
         | 
| 45 | 
            -
                    else
         | 
| 46 | 
            -
                      shared_library_path = File.join(build_dir, "librubyparser.#{RbConfig::CONFIG["SOEXT"]}")
         | 
| 47 | 
            -
                      unless File.exist?(shared_library_path)
         | 
| 48 | 
            -
                        build_shared_rubyparser
         | 
| 49 | 
            -
                      end
         | 
| 50 | 
            -
                      unless find_library("rubyparser", "pm_parser_init", build_dir)
         | 
| 51 | 
            -
                        raise "could not link against #{File.basename(shared_library_path)}"
         | 
| 52 | 
            -
                      end
         | 
| 53 | 
            -
                    end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                    find_header("prism.h", include_dir) or raise "prism.h is required"
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                    # Explicitly look for the extension header in the parent directory
         | 
| 58 | 
            -
                    # because we want to consistently look for prism/extension.h in our
         | 
| 59 | 
            -
                    # source files to line up with our mirroring in CRuby.
         | 
| 60 | 
            -
                    find_header("prism/extension.h", File.join(__dir__, "..")) or raise "prism/extension.h is required"
         | 
| 61 | 
            -
                  end
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                  def build_shared_rubyparser
         | 
| 64 | 
            -
                    build_target_rubyparser "build/librubyparser.#{RbConfig::CONFIG["SOEXT"]}"
         | 
| 65 | 
            -
                  end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                  def build_static_rubyparser
         | 
| 68 | 
            -
                    build_target_rubyparser "build/librubyparser.a"
         | 
| 69 | 
            -
                  end
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                  def build_target_rubyparser(target)
         | 
| 72 | 
            -
                    Dir.chdir(root_dir) do
         | 
| 73 | 
            -
                      if !File.exist?("include/prism/ast.h") && Dir.exist?(".git")
         | 
| 74 | 
            -
                        # this block only exists to support building the gem from a "git" source,
         | 
| 75 | 
            -
                        # normally we package up the configure and other files in the gem itself
         | 
| 76 | 
            -
                        system("templates/template.rb", exception: true)
         | 
| 77 | 
            -
                      end
         | 
| 78 | 
            -
                      system("make", target, exception: true)
         | 
| 79 | 
            -
                    end
         | 
| 80 | 
            -
                  end
         | 
| 81 | 
            -
             | 
| 82 | 
            -
                  def root_dir
         | 
| 83 | 
            -
                    File.expand_path("../..", __dir__)
         | 
| 84 | 
            -
                  end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                  def include_dir
         | 
| 87 | 
            -
                    File.join(root_dir, "include")
         | 
| 88 | 
            -
                  end
         | 
| 89 | 
            -
             | 
| 90 | 
            -
                  def build_dir
         | 
| 91 | 
            -
                    File.join(root_dir, "build")
         | 
| 92 | 
            -
                  end
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                  def print_help
         | 
| 95 | 
            -
                    print(<<~TEXT)
         | 
| 96 | 
            -
                      USAGE: ruby #{$PROGRAM_NAME} [options]
         | 
| 97 | 
            -
             | 
| 98 | 
            -
                        Flags that are always valid:
         | 
| 99 | 
            -
             | 
| 100 | 
            -
                            --enable-static
         | 
| 101 | 
            -
                            --disable-static
         | 
| 102 | 
            -
                                Enable or disable static linking against librubyparser.
         | 
| 103 | 
            -
                                The default is to statically link.
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                            --enable-debug-mode-build
         | 
| 106 | 
            -
                                Enable debug mode build.
         | 
| 107 | 
            -
                                You may also use set PRISM_DEBUG_MODE_BUILD environment variable.
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                            --help
         | 
| 110 | 
            -
                                Display this message.
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                        Environment variables used:
         | 
| 113 | 
            -
             | 
| 114 | 
            -
                            PRISM_DEBUG_MODE_BUILD
         | 
| 115 | 
            -
                                Equivalent to `--enable-debug-mode-build` when set, even if nil or blank.
         | 
| 116 | 
            -
             | 
| 117 | 
            -
                    TEXT
         | 
| 118 | 
            -
                  end
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                  def static_link?
         | 
| 121 | 
            -
                    enable_config("static", true)
         | 
| 122 | 
            -
                  end
         | 
| 123 | 
            -
             | 
| 124 | 
            -
                  def debug_mode_build?
         | 
| 125 | 
            -
                    enable_config("debug-mode-build", ENV["PRISM_DEBUG_MODE_BUILD"] || false)
         | 
| 126 | 
            -
                  end
         | 
| 18 | 
            +
                      PRISM_DEBUG_MODE_BUILD
         | 
| 19 | 
            +
                          Equivalent to `--enable-debug-mode-build` when set, even if nil or blank.
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              TEXT
         | 
| 22 | 
            +
              exit!(0)
         | 
| 23 | 
            +
            end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            # Runs `make` in the root directory of the project. Note that this is the
         | 
| 26 | 
            +
            # `Makefile` for the overall project, not the `Makefile` that is being generated
         | 
| 27 | 
            +
            # by this script.`
         | 
| 28 | 
            +
            def make(target)
         | 
| 29 | 
            +
              Dir.chdir(File.expand_path("../..", __dir__)) do
         | 
| 30 | 
            +
                # If this gem is being build from a git source, then we need to run
         | 
| 31 | 
            +
                # templating if it hasn't been run yet. In normal packaging, we would have
         | 
| 32 | 
            +
                # shipped the templated files with the gem, so this wouldn't be necessary.
         | 
| 33 | 
            +
                if !File.exist?("include/prism/ast.h") && Dir.exist?(".git")
         | 
| 34 | 
            +
                  system("templates/template.rb", exception: true)
         | 
| 127 35 | 
             
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                system("make", target, exception: true)
         | 
| 128 38 | 
             
              end
         | 
| 129 39 | 
             
            end
         | 
| 130 40 |  | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 41 | 
            +
            require "rbconfig"
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            # On non-CRuby we only need the shared library since we'll interface with it
         | 
| 44 | 
            +
            # through FFI, so we'll build only that and not the C extension. We also avoid
         | 
| 45 | 
            +
            # `require "mkmf"` as that prepends the LLVM toolchain to PATH on TruffleRuby,
         | 
| 46 | 
            +
            # but we want to use the native toolchain here since libprism is run natively.
         | 
| 47 | 
            +
            if RUBY_ENGINE != "ruby"
         | 
| 48 | 
            +
              make("build/libprism.#{RbConfig::CONFIG["SOEXT"]}")
         | 
| 49 | 
            +
              File.write("Makefile", "all install clean:\n\t@#{RbConfig::CONFIG["NULLCMD"]}\n")
         | 
| 50 | 
            +
              return
         | 
| 51 | 
            +
            end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            require "mkmf"
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            # First, ensure that we can find the header for the prism library.
         | 
| 56 | 
            +
            unless find_header("prism.h", File.expand_path("../../include", __dir__))
         | 
| 57 | 
            +
              raise "prism.h is required"
         | 
| 134 58 | 
             
            end
         | 
| 135 59 |  | 
| 136 | 
            -
             | 
| 60 | 
            +
            # Next, ensure we can find the header for the C extension. Explicitly look for
         | 
| 61 | 
            +
            # the extension header in the parent directory because we want to consistently
         | 
| 62 | 
            +
            # look for `prism/extension.h` in our source files to line up with our mirroring
         | 
| 63 | 
            +
            # in CRuby.
         | 
| 64 | 
            +
            unless find_header("prism/extension.h", File.expand_path("..", __dir__))
         | 
| 65 | 
            +
              raise "prism/extension.h is required"
         | 
| 66 | 
            +
            end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            # If `--enable-debug-mode-build` is passed to this script or the
         | 
| 69 | 
            +
            # `PRISM_DEBUG_MODE_BUILD` environment variable is defined, we'll build with the
         | 
| 70 | 
            +
            # `PRISM_DEBUG_MODE_BUILD` macro defined. This causes parse functions to
         | 
| 71 | 
            +
            # duplicate their input so that they have clearly set bounds, which is useful
         | 
| 72 | 
            +
            # for finding bugs that cause the parser to read off the end of the input.
         | 
| 73 | 
            +
            if enable_config("debug-mode-build", ENV["PRISM_DEBUG_MODE_BUILD"] || false)
         | 
| 74 | 
            +
              append_cflags("-DPRISM_DEBUG_MODE_BUILD")
         | 
| 75 | 
            +
            end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            # By default, all symbols are hidden in the shared library.
         | 
| 78 | 
            +
            append_cflags("-fvisibility=hidden")
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            # We need to link against the libprism.a archive, which is built by the
         | 
| 81 | 
            +
            # project's `Makefile`. We'll build it if it doesn't exist yet, and then add it
         | 
| 82 | 
            +
            # to `mkmf`'s list of local libraries.
         | 
| 83 | 
            +
            archive_target = "build/libprism.a"
         | 
| 84 | 
            +
            archive_path = File.expand_path("../../#{archive_target}", __dir__)
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            make(archive_target) unless File.exist?(archive_path)
         | 
| 87 | 
            +
            $LOCAL_LIBS << " #{archive_path}"
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            # Finally, we'll create the `Makefile` that is going to be used to configure and
         | 
| 90 | 
            +
            # build the C extension.
         | 
| 91 | 
            +
            create_makefile("prism/prism")
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            # Now that the `Makefile` for the C extension is built, we'll append on an extra
         | 
| 94 | 
            +
            # rule that dictates that the extension should be rebuilt if the archive is
         | 
| 95 | 
            +
            # updated.
         | 
| 96 | 
            +
            File.open("Makefile", "a") do |mf|
         | 
| 97 | 
            +
              mf.puts
         | 
| 98 | 
            +
              mf.puts("# Automatically rebuild the extension if libprism.a changed")
         | 
| 99 | 
            +
              mf.puts("$(TARGET_SO): $(LOCAL_LIBS)")
         | 
| 100 | 
            +
            end
         | 
    
        data/ext/prism/extension.c
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            #include "prism/extension.h"
         | 
| 2 2 |  | 
| 3 3 | 
             
            // NOTE: this file should contain only bindings. All non-trivial logic should be
         | 
| 4 | 
            -
            // in  | 
| 4 | 
            +
            // in libprism so it can be shared its the various callers.
         | 
| 5 5 |  | 
| 6 6 | 
             
            VALUE rb_cPrism;
         | 
| 7 7 | 
             
            VALUE rb_cPrismNode;
         | 
| @@ -331,6 +331,9 @@ parser_comments(pm_parser_t *parser, VALUE source) { | |
| 331 331 | 
             
                        case PM_COMMENT___END__:
         | 
| 332 332 | 
             
                            type = rb_cPrismDATAComment;
         | 
| 333 333 | 
             
                            break;
         | 
| 334 | 
            +
                        default:
         | 
| 335 | 
            +
                            type = rb_cPrismInlineComment;
         | 
| 336 | 
            +
                            break;
         | 
| 334 337 | 
             
                    }
         | 
| 335 338 |  | 
| 336 339 | 
             
                    VALUE comment_argv[] = { rb_class_new_instance(3, location_argv, rb_cPrismLocation) };
         |