prism 0.17.0 → 0.18.0
Sign up to get free protection for your applications and to get access to all the features.
- 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) };
|