ikra 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/ast/builder.rb +100 -0
- data/lib/ast/lexical_variables_enumerator.rb +34 -0
- data/lib/ast/method_definition.rb +37 -0
- data/lib/ast/nodes.rb +208 -0
- data/lib/ast/printer.rb +99 -0
- data/lib/ast/translator.rb +264 -0
- data/lib/ast/visitor.rb +173 -0
- data/lib/config/configuration.rb +18 -0
- data/lib/config/os_configuration.rb +56 -0
- data/lib/entity.rb +11 -0
- data/lib/ikra.rb +7 -0
- data/lib/parsing.rb +32 -0
- data/lib/resources/cuda/block_function_head.cpp +1 -0
- data/lib/resources/cuda/env_builder_copy_array.cpp +4 -0
- data/lib/resources/cuda/header.cpp +46 -0
- data/lib/resources/cuda/kernel.cpp +8 -0
- data/lib/resources/cuda/kernel_launcher.cpp +28 -0
- data/lib/resources/cuda/soa_header.cpp +4 -0
- data/lib/scope.rb +166 -0
- data/lib/sourcify/Gemfile +10 -0
- data/lib/sourcify/HISTORY.txt +88 -0
- data/lib/sourcify/LICENSE +20 -0
- data/lib/sourcify/README.rdoc +352 -0
- data/lib/sourcify/Rakefile +111 -0
- data/lib/sourcify/lib/sourcify.rb +44 -0
- data/lib/sourcify/lib/sourcify/common/parser/converter.rb +29 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/comment.rb +23 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/counter.rb +43 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/dstring.rb +58 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/extensions.rb +140 -0
- data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/heredoc.rb +26 -0
- data/lib/sourcify/lib/sourcify/common/parser/source_code.rb +45 -0
- data/lib/sourcify/lib/sourcify/common/ragel/common.rl +5 -0
- data/lib/sourcify/lib/sourcify/common/ragel/expressions.rl +38 -0
- data/lib/sourcify/lib/sourcify/common/ragel/machines.rl +317 -0
- data/lib/sourcify/lib/sourcify/errors.rb +4 -0
- data/lib/sourcify/lib/sourcify/method.rb +138 -0
- data/lib/sourcify/lib/sourcify/method/methods.rb +3 -0
- data/lib/sourcify/lib/sourcify/method/methods/to_raw_source.rb +30 -0
- data/lib/sourcify/lib/sourcify/method/methods/to_sexp.rb +30 -0
- data/lib/sourcify/lib/sourcify/method/methods/to_source.rb +30 -0
- data/lib/sourcify/lib/sourcify/method/parser.rb +110 -0
- data/lib/sourcify/lib/sourcify/method/parser/converter.rb +8 -0
- data/lib/sourcify/lib/sourcify/method/parser/raw_scanner.rb +2494 -0
- data/lib/sourcify/lib/sourcify/method/parser/raw_scanner.rl +144 -0
- data/lib/sourcify/lib/sourcify/method/parser/raw_scanner_extensions.rb +68 -0
- data/lib/sourcify/lib/sourcify/method/parser/scanner.rb +52 -0
- data/lib/sourcify/lib/sourcify/method/parser/source_code.rb +8 -0
- data/lib/sourcify/lib/sourcify/patches.rb +63 -0
- data/lib/sourcify/lib/sourcify/proc.rb +183 -0
- data/lib/sourcify/lib/sourcify/proc/methods.rb +3 -0
- data/lib/sourcify/lib/sourcify/proc/methods/source_location.rb +61 -0
- data/lib/sourcify/lib/sourcify/proc/methods/to_raw_source.rb +20 -0
- data/lib/sourcify/lib/sourcify/proc/methods/to_sexp.rb +40 -0
- data/lib/sourcify/lib/sourcify/proc/methods/to_source.rb +48 -0
- data/lib/sourcify/lib/sourcify/proc/parser.rb +51 -0
- data/lib/sourcify/lib/sourcify/proc/parser/converter.rb +8 -0
- data/lib/sourcify/lib/sourcify/proc/parser/normalizer.rb +43 -0
- data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner.rb +2498 -0
- data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner.rl +149 -0
- data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner_extensions.rb +74 -0
- data/lib/sourcify/lib/sourcify/proc/parser/scanner.rb +49 -0
- data/lib/sourcify/lib/sourcify/proc/parser/source_code.rb +8 -0
- data/lib/sourcify/lib/sourcify/version.rb +3 -0
- data/lib/sourcify/sourcify.gemspec +31 -0
- data/lib/sourcify/spec/dump_object_space_procs.rb +84 -0
- data/lib/sourcify/spec/method/encoding_from_def_end_block_spec.rb +33 -0
- data/lib/sourcify/spec/method/encoding_from_define_method_spec.rb +37 -0
- data/lib/sourcify/spec/method/others_from_def_end_block_spec.rb +49 -0
- data/lib/sourcify/spec/method/others_from_define_method_spec.rb +63 -0
- data/lib/sourcify/spec/method/raw_scanner/block_comment_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/double_colons_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/heredoc_w_indent_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
- data/lib/sourcify/spec/method/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
- data/lib/sourcify/spec/method/raw_scanner/per_line_comment_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/single_quote_str_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/slash_operator_spec.rb +8 -0
- data/lib/sourcify/spec/method/raw_scanner/spec_helper.rb +80 -0
- data/lib/sourcify/spec/method/spec_helper.rb +1 -0
- data/lib/sourcify/spec/method/to_raw_source_spec.rb +31 -0
- data/lib/sourcify/spec/method/to_raw_source_w_specified_strip_enclosure_spec.rb +148 -0
- data/lib/sourcify/spec/method/to_sexp_from_def_end_block_w_variables_spec.rb +46 -0
- data/lib/sourcify/spec/method/to_sexp_from_def_end_block_within_irb_spec.rb +38 -0
- data/lib/sourcify/spec/method/to_sexp_from_def_end_block_within_pry_spec.rb +38 -0
- data/lib/sourcify/spec/method/to_sexp_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +56 -0
- data/lib/sourcify/spec/method/to_sexp_from_define_method_w_variables_spec.rb +52 -0
- data/lib/sourcify/spec/method/to_sexp_from_define_method_within_irb_spec.rb +42 -0
- data/lib/sourcify/spec/method/to_sexp_from_define_method_within_pry_spec.rb +42 -0
- data/lib/sourcify/spec/method/to_sexp_w_specified_strip_enclosure_spec.rb +74 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_19_extras_spec.rb +23 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_begin_spec.rb +35 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_case_spec.rb +35 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_class_spec.rb +51 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_do_end_block_spec.rb +33 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_for_spec.rb +126 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_if_spec.rb +83 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_literal_keyword_spec.rb +141 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_method_spec.rb +33 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_module_spec.rb +59 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_unless_spec.rb +83 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_until_spec.rb +179 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_while_spec.rb +179 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_w_singleton_method_spec.rb +19 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_within_irb_spec.rb +30 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_block_within_pry_spec.rb +45 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_w_multi_blocks_and_many_matches_spec.rb +30 -0
- data/lib/sourcify/spec/method/to_source_from_def_end_w_multi_blocks_and_single_match_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_braced_block_spec.rb +113 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_do_end_block_spec.rb +145 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_many_matches_spec.rb +56 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_single_match_spec.rb +73 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_many_matches_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_no_match_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_single_match_spec.rb +28 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +103 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_many_matches_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_no_match_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_single_match_spec.rb +28 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_ignore_nested_spec.rb +36 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_within_irb_spec.rb +32 -0
- data/lib/sourcify/spec/method/to_source_from_define_method_within_pry_spec.rb +49 -0
- data/lib/sourcify/spec/method/to_source_magic_file_var_spec.rb +176 -0
- data/lib/sourcify/spec/method/to_source_magic_line_var_spec.rb +298 -0
- data/lib/sourcify/spec/method/to_source_w_specified_strip_enclosure_spec.rb +39 -0
- data/lib/sourcify/spec/no_method/unsupported_platform_spec.rb +26 -0
- data/lib/sourcify/spec/proc/19x_extras.rb +27 -0
- data/lib/sourcify/spec/proc/created_on_the_fly_proc_spec.rb +80 -0
- data/lib/sourcify/spec/proc/encoding_spec.rb +36 -0
- data/lib/sourcify/spec/proc/others_spec.rb +40 -0
- data/lib/sourcify/spec/proc/raw_scanner/block_comment_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/double_colons_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/heredoc_w_indent_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
- data/lib/sourcify/spec/proc/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
- data/lib/sourcify/spec/proc/raw_scanner/per_line_comment_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/single_quote_str_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/slash_operator_spec.rb +8 -0
- data/lib/sourcify/spec/proc/raw_scanner/spec_helper.rb +63 -0
- data/lib/sourcify/spec/proc/readme +5 -0
- data/lib/sourcify/spec/proc/spec_helper.rb +1 -0
- data/lib/sourcify/spec/proc/to_raw_source_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_raw_source_w_specified_strip_enclosure_spec.rb +69 -0
- data/lib/sourcify/spec/proc/to_sexp_from_multi_blocks_w_specified_attached_to_spec.rb +46 -0
- data/lib/sourcify/spec/proc/to_sexp_variables_spec.rb +146 -0
- data/lib/sourcify/spec/proc/to_sexp_w_specified_strip_enclosure_spec.rb +60 -0
- data/lib/sourcify/spec/proc/to_sexp_within_irb_spec.rb +146 -0
- data/lib/sourcify/spec/proc/to_sexp_within_pry_spec.rb +149 -0
- data/lib/sourcify/spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_source_from_braced_block_w_nested_hash_spec.rb +82 -0
- data/lib/sourcify/spec/proc/to_source_from_braced_block_wo_nesting_complication_spec.rb +46 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_begin_spec.rb +35 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_case_spec.rb +35 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_class_spec.rb +89 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_do_end_block_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_for_spec.rb +132 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_if_spec.rb +87 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb +103 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_method_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_module_spec.rb +49 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_unless_spec.rb +87 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb +189 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_while_spec.rb +189 -0
- data/lib/sourcify/spec/proc/to_source_from_do_end_block_wo_nesting_complication_spec.rb +46 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_many_matches_spec.rb +43 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_single_match_spec.rb +20 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_many_matches_spec.rb +45 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_no_match_spec.rb +45 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_single_match_spec.rb +22 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_spec.rb +84 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_many_matches_spec.rb +45 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_no_match_spec.rb +45 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_single_match_spec.rb +22 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_ignore_nested_spec.rb +43 -0
- data/lib/sourcify/spec/proc/to_source_from_multi_do_end_blocks_w_single_match_spec.rb +31 -0
- data/lib/sourcify/spec/proc/to_source_magic_file_var_spec.rb +127 -0
- data/lib/sourcify/spec/proc/to_source_magic_line_var_spec.rb +127 -0
- data/lib/sourcify/spec/proc/to_source_variables_spec.rb +29 -0
- data/lib/sourcify/spec/proc/to_source_w_specified_strip_enclosure_spec.rb +33 -0
- data/lib/sourcify/spec/proc/to_source_within_irb_spec.rb +38 -0
- data/lib/sourcify/spec/proc/to_source_within_pry_spec.rb +61 -0
- data/lib/sourcify/spec/raw_scanner/block_comment_shared_spec.rb +57 -0
- data/lib/sourcify/spec/raw_scanner/double_colons_shared_spec.rb +11 -0
- data/lib/sourcify/spec/raw_scanner/double_quote_str_w_interpolation_shared_spec.rb +60 -0
- data/lib/sourcify/spec/raw_scanner/double_quote_str_wo_interpolation_shared_spec.rb +86 -0
- data/lib/sourcify/spec/raw_scanner/heredoc_w_indent_shared_spec.rb +69 -0
- data/lib/sourcify/spec/raw_scanner/heredoc_wo_indent_shared_spec.rb +70 -0
- data/lib/sourcify/spec/raw_scanner/kw_block_start_alias1_shared_spec.rb +73 -0
- data/lib/sourcify/spec/raw_scanner/kw_block_start_alias2_shared_spec.rb +73 -0
- data/lib/sourcify/spec/raw_scanner/per_line_comment_shared_spec.rb +32 -0
- data/lib/sourcify/spec/raw_scanner/shared_specs.rb +3 -0
- data/lib/sourcify/spec/raw_scanner/single_quote_str_shared_spec.rb +79 -0
- data/lib/sourcify/spec/raw_scanner/slash_operator_shared_spec.rb +71 -0
- data/lib/sourcify/spec/run_build.sh +25 -0
- data/lib/sourcify/spec/spec_helper.rb +130 -0
- data/lib/symbolic/symbolic.rb +248 -0
- data/lib/symbolic/visitor.rb +51 -0
- data/lib/translator/block_translator.rb +123 -0
- data/lib/translator/command_translator.rb +421 -0
- data/lib/translator/last_returns_visitor.rb +57 -0
- data/lib/translator/local_variables_enumerator.rb +35 -0
- data/lib/translator/method_translator.rb +24 -0
- data/lib/translator/translator.rb +49 -0
- data/lib/type_aware_array.rb +71 -0
- data/lib/types/array_type.rb +51 -0
- data/lib/types/class_type.rb +128 -0
- data/lib/types/object_tracer.rb +162 -0
- data/lib/types/primitive_type.rb +73 -0
- data/lib/types/ruby_extension.rb +67 -0
- data/lib/types/ruby_type.rb +45 -0
- data/lib/types/type_inference.rb +382 -0
- data/lib/types/union_type.rb +155 -0
- metadata +321 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 NgTzeYang
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,352 @@
|
|
1
|
+
= Sourcify
|
2
|
+
|
3
|
+
== IMPORTANT#1: Sourcify was written in the days of ruby 1.9.x, it should be buggy for anything beyond that.
|
4
|
+
== IMPORTANT#2: Sourcify is no longer maintained, use it at your own risk, & expect no bug fixes.
|
5
|
+
|
6
|
+
ParseTree[http://github.com/seattlerb/parsetree] is great, it accesses the runtime AST
|
7
|
+
(abstract syntax tree) and makes it possible to convert any object to ruby code &
|
8
|
+
S-expression, BUT ParseTree doesn't work for 1.9.* & JRuby.
|
9
|
+
|
10
|
+
RubyParser[http://github.com/seattlerb/ruby_parser] is great, and it works for any rubies
|
11
|
+
(of course, not 100% compatible for 1.8.7 & 1.9.* syntax yet), BUT it works only with
|
12
|
+
static code.
|
13
|
+
|
14
|
+
I truely enjoy using the above tools, but with my other projects, the absence of ParseTree
|
15
|
+
on the different rubies is forcing me to hand-baked my own solution each time to extract
|
16
|
+
the proc code i need at runtime. This is frustrating, the solution for each of them is
|
17
|
+
never perfect, and i'm reinventing the wheel each time just to address a particular
|
18
|
+
pattern of usage (using regexp kungfu).
|
19
|
+
|
20
|
+
Enough is enough, and now we have Sourcify, a unified solution to extract proc code.
|
21
|
+
When ParseTree is available, it simply works as a thin wrapper round it, otherwise, it
|
22
|
+
uses a home-baked ragel-generated scanner to extract the proc code. Further processing
|
23
|
+
with RubyParser & Ruby2Ruby to ensure 100% with ParseTree (yup, there is no denying that
|
24
|
+
i really like ParseTree).
|
25
|
+
|
26
|
+
|
27
|
+
== Installing It
|
28
|
+
|
29
|
+
The religiously standard way:
|
30
|
+
|
31
|
+
$ gem install ParseTree sourcify
|
32
|
+
|
33
|
+
Or on 1.9.* or JRuby:
|
34
|
+
|
35
|
+
$ gem install ruby_parser file-tail sourcify
|
36
|
+
|
37
|
+
|
38
|
+
== Sourcify adds 4 methods to Proc
|
39
|
+
|
40
|
+
=== 1. Proc#to_source
|
41
|
+
|
42
|
+
Returns the code representation of the proc:
|
43
|
+
|
44
|
+
require 'sourcify'
|
45
|
+
|
46
|
+
lambda { x + y }.to_source
|
47
|
+
# >> "proc { (x + y) }"
|
48
|
+
|
49
|
+
proc { x + y }.to_source
|
50
|
+
# >> "proc { (x + y) }"
|
51
|
+
|
52
|
+
Like it or not, a lambda is represented as a proc when converted to source (exactly the
|
53
|
+
same way as ParseTree). It is possible to only extract the body of the proc by passing
|
54
|
+
in {:strip_enclosure => true}:
|
55
|
+
|
56
|
+
lambda { x + y }.to_source(:strip_enclosure => true)
|
57
|
+
# >> "(x + y)"
|
58
|
+
|
59
|
+
lambda {|i| i + 2 }.to_source(:strip_enclosure => true)
|
60
|
+
# >> "(i + 2)"
|
61
|
+
|
62
|
+
=== 2. Proc#to_sexp
|
63
|
+
|
64
|
+
Returns the S-expression of the proc:
|
65
|
+
|
66
|
+
require 'sourcify'
|
67
|
+
|
68
|
+
x = 1
|
69
|
+
lambda { x + y }.to_sexp
|
70
|
+
# >> s(:iter,
|
71
|
+
# >> s(:call, nil, :proc, s(:arglist)),
|
72
|
+
# >> nil,
|
73
|
+
# >> s(:call, s(:lvar, :x), :+, s(:arglist, s(:call, nil, :y, s(:arglist)))))
|
74
|
+
|
75
|
+
To extract only the body of the proc:
|
76
|
+
|
77
|
+
lambda { x + y }.to_sexp(:strip_enclosure => true)
|
78
|
+
# >> s(:call, s(:lvar, :x), :+, s(:arglist, s(:call, nil, :y, s(:arglist)))))
|
79
|
+
|
80
|
+
=== 3. Proc#to_raw_source
|
81
|
+
|
82
|
+
Unlike Proc#to_source, which returns code that retains only functional aspects,
|
83
|
+
fetching of raw source returns the raw code enclosed within the proc, including
|
84
|
+
fluff like comments:
|
85
|
+
|
86
|
+
lambda do |i|
|
87
|
+
i+1 # (blah)
|
88
|
+
end.to_raw_source
|
89
|
+
# >> "proc do |i|
|
90
|
+
# >> i+1 # (blah)
|
91
|
+
# >> end"
|
92
|
+
|
93
|
+
NOTE: This is extracting of raw code, it relies on static code scanning (even when
|
94
|
+
running in ParseTree mode), the gotchas for static code scanning always apply.
|
95
|
+
|
96
|
+
=== 4. Proc#source_location
|
97
|
+
|
98
|
+
By default, this is only available on 1.9.*, it is added (as a bonus) to provide
|
99
|
+
consistency under 1.8.*:
|
100
|
+
|
101
|
+
# /tmp/test.rb
|
102
|
+
require 'sourcify'
|
103
|
+
|
104
|
+
lambda { x + y }.source_location
|
105
|
+
# >> ["/tmp/test.rb", 5]
|
106
|
+
|
107
|
+
|
108
|
+
== Sourcify adds 3 methods to Method
|
109
|
+
|
110
|
+
*IMPORTANT*: These only work for MRI-1.9.2, as currently, only it supports
|
111
|
+
(1) discovering of the original source location with Method#source_location,
|
112
|
+
and (2) reliably determinig a method's parameters with Method#parameters.
|
113
|
+
Attempting to use these methods on other rubies will raise
|
114
|
+
Sourcify::PlatformNotSupportedError.
|
115
|
+
|
116
|
+
*NOTE*: The following works for methods defined using both def .. end &
|
117
|
+
Module#define_method. However, when a method is defined using the later
|
118
|
+
approach, sourcify uses Proc#to_source to handle the processing, thus, the
|
119
|
+
usual gotchas related to proc source extraction apply.
|
120
|
+
|
121
|
+
=== 1. Method#to_source
|
122
|
+
|
123
|
+
Returns the code representation of the method:
|
124
|
+
|
125
|
+
require 'sourcify'
|
126
|
+
|
127
|
+
class MyMath
|
128
|
+
def self.sum(x, y)
|
129
|
+
x + y # (blah)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
MyMath.method(:sum).to_source
|
134
|
+
# >> "def sum(x, y)
|
135
|
+
# >> (x + y)
|
136
|
+
# >> end"
|
137
|
+
|
138
|
+
Just like the Proc#to_source equivalent, u can set :strip_enclosure => true
|
139
|
+
to extract only the body within.
|
140
|
+
|
141
|
+
=== 2. Method#to_sexp
|
142
|
+
|
143
|
+
Returns the S-expression of the method:
|
144
|
+
|
145
|
+
require 'sourcify'
|
146
|
+
|
147
|
+
class MyMath
|
148
|
+
def self.sum(x, y)
|
149
|
+
x + y # (blah)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
MyMath.method(:sum).to_sexp
|
154
|
+
>> s(:defn,
|
155
|
+
>> :sum,
|
156
|
+
>> s(:args, :x, :y),
|
157
|
+
>> s(:scope, s(:block, s(:call, s(:lvar, :x), :+, s(:arglist, s(:lvar, :y))))))
|
158
|
+
|
159
|
+
Just like the Proc#to_sexp equivalent, u can set :strip_enclosure => true
|
160
|
+
to extract only the body within.
|
161
|
+
|
162
|
+
=== 3. Method#to_raw_source
|
163
|
+
|
164
|
+
Unlike Method#to_source, which returns code that retains only functional aspects,
|
165
|
+
fetching of raw source returns the method's raw code, including fluff like comments:
|
166
|
+
|
167
|
+
require 'sourcify'
|
168
|
+
|
169
|
+
class MyMath
|
170
|
+
def self.sum(x, y)
|
171
|
+
x + y # (blah)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
MyMath.method(:sum).to_raw_source
|
176
|
+
# >> "def sum(x, y)
|
177
|
+
# >> x + y # (blah)
|
178
|
+
# >> end"
|
179
|
+
|
180
|
+
Just like the Proc#to_raw_source equivalent, u can set :strip_enclosure => true
|
181
|
+
to extract only the body within.
|
182
|
+
|
183
|
+
|
184
|
+
== Performance
|
185
|
+
|
186
|
+
Performance is embarassing for now, benchmarking results for processing 500 procs
|
187
|
+
(in the ObjectSpace of an average rails project) yiels the following:
|
188
|
+
|
189
|
+
ruby user system total real
|
190
|
+
ruby-1.8.7-p299 (w ParseTree) 10.270000 0.010000 10.280000 ( 10.311430)
|
191
|
+
ruby-1.8.7-p299 (static scanner) 14.120000 0.080000 14.200000 ( 14.283817)
|
192
|
+
ruby-1.9.1-p376 (static scanner) 17.380000 0.050000 17.430000 ( 17.405966)
|
193
|
+
jruby-1.5.2 (static scanner) 21.318000 0.000000 21.318000 ( 21.318000)
|
194
|
+
|
195
|
+
Since i'm still pretty new to ragel[http://www.complang.org/ragel], the code scanner will
|
196
|
+
probably become better & faster as my knowlegde & skills with ragel improve. Also,
|
197
|
+
instead of generating a pure ruby scanner, we can generate native code (eg. C or java, or
|
198
|
+
whatever) instead. As i'm a C & java noob, this will probably take some time to realize.
|
199
|
+
|
200
|
+
|
201
|
+
== Gotchas
|
202
|
+
|
203
|
+
Nothing beats ParseTree's ability to access the runtime AST, it is a very powerful feature.
|
204
|
+
The scanner-based (static) implementation suffer the following gotchas:
|
205
|
+
|
206
|
+
=== 1. The source code is everything
|
207
|
+
|
208
|
+
Since static code analysis is involved, the subject code needs to physically exist within a
|
209
|
+
file, meaning Proc#source_location must return the expected *[file, lineno]*, the following
|
210
|
+
will not work:
|
211
|
+
|
212
|
+
def test
|
213
|
+
eval('lambda { x + y }')
|
214
|
+
end
|
215
|
+
|
216
|
+
test.source_location
|
217
|
+
# >> ["(eval)", 1]
|
218
|
+
|
219
|
+
test.to_source
|
220
|
+
# >> Sourcify::CannotParseEvalCodeError
|
221
|
+
|
222
|
+
The same applies to *Blah#to_proc* & *&:blah*:
|
223
|
+
|
224
|
+
klass = Class.new do
|
225
|
+
def aa(&block); block ; end
|
226
|
+
def bb; 1+2; end
|
227
|
+
end
|
228
|
+
|
229
|
+
klass.new.method(:bb).to_proc.to_source
|
230
|
+
# >> Sourcify::CannotHandleCreatedOnTheFlyProcError
|
231
|
+
|
232
|
+
klass.new.aa(&:bb).to_source
|
233
|
+
# >> Sourcify::CannotHandleCreatedOnTheFlyProcError
|
234
|
+
|
235
|
+
=== 2. Multiple matching procs per line error
|
236
|
+
|
237
|
+
Sometimes, we may have multiple procs on a line, Sourcify can handle this as long as the
|
238
|
+
subject proc has arity that is unique from others:
|
239
|
+
|
240
|
+
# Yup, this works as expected :)
|
241
|
+
b1 = lambda {|a| a+1 }; b2 = lambda { 1+2 }
|
242
|
+
b2.to_source
|
243
|
+
# >> proc { (1 + 2) }
|
244
|
+
|
245
|
+
# Nope, this won't work :(
|
246
|
+
b1 = lambda { 1+2 }; b2 = lambda { 2+3 }
|
247
|
+
b2.to_source
|
248
|
+
# >> raises Sourcify::MultipleMatchingProcsPerLineError
|
249
|
+
|
250
|
+
As observed, the above does not work when there are multiple procs having the same arity,
|
251
|
+
on the same line. Furthermore, this bug[http://redmine.ruby-lang.org/issues/show/574]
|
252
|
+
under 1.8.* affects the accuracy of this approach.
|
253
|
+
|
254
|
+
To better narrow down the scanning, try:
|
255
|
+
|
256
|
+
* passing in the {:attached_to => ...} option
|
257
|
+
|
258
|
+
x = lambda { proc { :blah } }
|
259
|
+
|
260
|
+
x.to_source
|
261
|
+
# >> Sourcify::MultipleMatchingProcsPerLineError
|
262
|
+
|
263
|
+
x.to_source(:attached_to => :lambda)
|
264
|
+
# >> "proc { proc { :blah } }"
|
265
|
+
|
266
|
+
* passing in the {:ignore_nested => ...} option
|
267
|
+
|
268
|
+
x = lambda { lambda { :blah } }
|
269
|
+
|
270
|
+
x.to_source
|
271
|
+
# >> Sourcify::MultipleMatchingProcsPerLineError
|
272
|
+
|
273
|
+
x.to_source(:ignore_nested => true)
|
274
|
+
# >> "proc { lambda { :blah } }"
|
275
|
+
|
276
|
+
* attaching a body matcher proc
|
277
|
+
|
278
|
+
x, y = lambda { def secret; 1; end }, lambda { :blah }
|
279
|
+
|
280
|
+
x.to_source
|
281
|
+
# >> Sourcify::MultipleMatchingProcsPerLineError
|
282
|
+
|
283
|
+
x.to_source{|body| body =~ /^(.*\W|)def\W/ }
|
284
|
+
# >> 'proc { def secret; 1; end }'
|
285
|
+
|
286
|
+
Pls refer to the rdoc for more details.
|
287
|
+
|
288
|
+
=== 3. Occasional Racc::ParseError
|
289
|
+
|
290
|
+
Under the hood, sourcify relies on RubyParser to yield s-expression, and since RubyParser
|
291
|
+
does not yet fully handle 1.8.7 & 1.9.* syntax, you will get a nasty Racc::ParseError when
|
292
|
+
you have any code that is not compatible with 1.8.6.
|
293
|
+
|
294
|
+
=== 4. Lambda operator doesn't work
|
295
|
+
|
296
|
+
When a lambda has been created using the lambda operator "->", sourcify can't handle it:
|
297
|
+
|
298
|
+
x = ->{ :blah }
|
299
|
+
x.to_source
|
300
|
+
# >> Sourcify::NoMatchingProcError
|
301
|
+
|
302
|
+
|
303
|
+
== Is it really working ??
|
304
|
+
|
305
|
+
Sourcify spec suite currently passes in the following rubies:
|
306
|
+
* MRI-1.8.*, REE-1.8.7 (both ParseTree & static scanner modes)
|
307
|
+
* JRuby-1.6.*, MRI-1.9.* (static scanner ONLY)
|
308
|
+
|
309
|
+
Besides its own spec suite, sourcify has also been tested to handle:
|
310
|
+
|
311
|
+
ObjectSpace.each_object(Proc) {|o| puts o.to_source }
|
312
|
+
|
313
|
+
For projects:
|
314
|
+
* Spree[http://github.com/railsdog/spree]
|
315
|
+
* Redmine[http://github.com/edavis10/redmine]
|
316
|
+
|
317
|
+
(TODO: the more the merrier)
|
318
|
+
|
319
|
+
|
320
|
+
== Projects using it
|
321
|
+
|
322
|
+
Projects using sourcify include:
|
323
|
+
* wrong[http://github.com/sconover/wrong]
|
324
|
+
* ruote[http://ruote.rubyforge.org/]
|
325
|
+
* dm-ambition[https://github.com/dkubb/dm-ambition]
|
326
|
+
|
327
|
+
|
328
|
+
== Additional Resources
|
329
|
+
|
330
|
+
Sourcify is heavily inspired by many ideas gathered from the ruby community:
|
331
|
+
* http://www.justskins.com/forums/breaking-ruby-code-into-117453.html
|
332
|
+
* http://rubyquiz.com/quiz38.html (Florian Groß's solution)
|
333
|
+
* http://svenfuchs.com/2009/07/05/using-ruby-1-9-ripper.html
|
334
|
+
|
335
|
+
The sad fact that Proc#to_source wouldn't be available in the near future:
|
336
|
+
* http://redmine.ruby-lang.org/issues/show/2080
|
337
|
+
|
338
|
+
|
339
|
+
== Note on Patches/Pull Requests
|
340
|
+
|
341
|
+
* Fork the project.
|
342
|
+
* Make your feature addition or bug fix.
|
343
|
+
* Add tests for it. This is important so I don't break it in a
|
344
|
+
future version unintentionally.
|
345
|
+
* Commit, do not mess with rakefile, version, or history.
|
346
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
347
|
+
* Send me a pull request. Bonus points for topic branches.
|
348
|
+
|
349
|
+
|
350
|
+
== Copyright
|
351
|
+
|
352
|
+
Copyright (c) 2010 NgTzeYang. See LICENSE for details.
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'bundler'
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
SPEC_SCRIPT = File.expand_path('../spec/run_build.sh', __FILE__)
|
7
|
+
task :default => :spec
|
8
|
+
|
9
|
+
RUBIES = {
|
10
|
+
:parsetree => [
|
11
|
+
[nil, 'ruby-1.8.6-p420@sourcify-parsetree'],
|
12
|
+
[nil, 'ruby-1.8.7-p334@sourcify-parsetree'],
|
13
|
+
[nil, 'ree-1.8.7--2012.02@sourcify-parsetree']
|
14
|
+
],
|
15
|
+
:static => [
|
16
|
+
[nil, 'ruby-1.8.6-p420@sourcify'],
|
17
|
+
[nil, 'ruby-1.8.7-p334@sourcify'],
|
18
|
+
[nil, 'ree-1.8.7--2012.02@sourcify'],
|
19
|
+
[nil, 'jruby-1.6.3@sourcify'],
|
20
|
+
[nil, 'ruby-1.9.2-p320@sourcify'],
|
21
|
+
[nil, 'ruby-1.9.3-p194@sourcify'],
|
22
|
+
|
23
|
+
# NOTE: This doesn't support Method#to_source (& friends) yet yet due to
|
24
|
+
# jruby's Method#parameters bug, see http://jira.codehaus.org/browse/JRUBY-5954
|
25
|
+
['JRUBY_OPTS="--1.9"', 'jruby-1.6.3@sourcify'],
|
26
|
+
|
27
|
+
]
|
28
|
+
}
|
29
|
+
|
30
|
+
def run_build_for(envs_and_rubies)
|
31
|
+
envs_and_rubies.group_by{|arry| arry[0..-2] }.each do |envs, arry|
|
32
|
+
rubies = arry.map(&:last)
|
33
|
+
declared_envs = ['export MUTE_BACON=true']
|
34
|
+
declared_envs << envs.map{|env| env ? "export #{env}" : nil }.compact
|
35
|
+
|
36
|
+
system [
|
37
|
+
declared_envs.flatten.join('; '),
|
38
|
+
"rvm #{rubies.join(',')} exec #{SPEC_SCRIPT}"
|
39
|
+
].join('; ')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# ///////////////////////////////////////////////////////////
|
44
|
+
# Running Specs
|
45
|
+
# ///////////////////////////////////////////////////////////
|
46
|
+
desc "Run all specs"
|
47
|
+
task :spec do |t|
|
48
|
+
system SPEC_SCRIPT
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Run specs in all rubies (both ParseTree & static scanner modes)"
|
52
|
+
task :'spec:all' do
|
53
|
+
run_build_for RUBIES.values.flatten(1)
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "Run specs in rubies supporting ParseTree mode"
|
57
|
+
task :'spec:parsetree' do
|
58
|
+
run_build_for RUBIES[:parsetree]
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Run specs in rubies supporting static scanner mode"
|
62
|
+
task :'spec:static' do
|
63
|
+
run_build_for RUBIES[:static]
|
64
|
+
end
|
65
|
+
|
66
|
+
# ///////////////////////////////////////////////////////////
|
67
|
+
# Build ruby files from ragel definitions
|
68
|
+
# ///////////////////////////////////////////////////////////
|
69
|
+
desc "Run ragel to generate ruby scanner files from ragel definitions"
|
70
|
+
task :ragel do
|
71
|
+
%w{method proc}.each do |m|
|
72
|
+
common_dir = File.expand_path('../lib/sourcify/common/ragel', __FILE__)
|
73
|
+
ragel_dir = File.expand_path("../lib/sourcify/#{m}/parser", __FILE__)
|
74
|
+
ragel_file = File.join(ragel_dir, 'raw_scanner.rl')
|
75
|
+
ruby_file = File.join(ragel_dir, 'raw_scanner.rb')
|
76
|
+
File.delete(ruby_file) rescue nil
|
77
|
+
puts 'Processing %s -> %s' %
|
78
|
+
[ragel_file, ruby_file].map{|f| f.sub(File.expand_path('../', __FILE__) + '/', '')}
|
79
|
+
system("ragel -I #{common_dir} -R #{ragel_file}")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# ///////////////////////////////////////////////////////////
|
84
|
+
# Benchmarking
|
85
|
+
# ///////////////////////////////////////////////////////////
|
86
|
+
desc "Benchmarking"
|
87
|
+
task :benchmark, :task, :times do |t, args|
|
88
|
+
times, task = (args.times || 5).to_i.method(:times), args.task
|
89
|
+
title = " ~ Benchmark Results for Task :#{task} ~ "
|
90
|
+
results = [%w{nth}, %w{user}, %w{system}, %w{total}, %w{real}]
|
91
|
+
|
92
|
+
# Running benchmarking & collecting results
|
93
|
+
require 'benchmark'
|
94
|
+
times.call do |i|
|
95
|
+
result = Benchmark.measure{ Rake::Task[task].execute }.to_s
|
96
|
+
user, system, total, real =
|
97
|
+
result.match(/^\s*(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+\(\s*(\d+\.\d+)\)$/)[1..-1]
|
98
|
+
["##{i.succ}", user, system, total, real].each_with_index{|val, j| results[j] << val }
|
99
|
+
end
|
100
|
+
|
101
|
+
# Formatting benchmarking results
|
102
|
+
formatted_results = results.map do |rs|
|
103
|
+
width = rs.map(&:to_s).map(&:size).max
|
104
|
+
rs.map{|r| ' ' + r.ljust(width, ' ') }
|
105
|
+
end.transpose.map{|row| row.join }
|
106
|
+
|
107
|
+
# Showdown .. printout
|
108
|
+
line = '=' * ([title.size, formatted_results.map(&:size).max].max + 2)
|
109
|
+
puts [line, title, formatted_results.join("\n"), line].join("\n\n")
|
110
|
+
end
|
111
|
+
|