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) };
|