ikra 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. checksums.yaml +7 -0
  2. data/lib/ast/builder.rb +100 -0
  3. data/lib/ast/lexical_variables_enumerator.rb +34 -0
  4. data/lib/ast/method_definition.rb +37 -0
  5. data/lib/ast/nodes.rb +208 -0
  6. data/lib/ast/printer.rb +99 -0
  7. data/lib/ast/translator.rb +264 -0
  8. data/lib/ast/visitor.rb +173 -0
  9. data/lib/config/configuration.rb +18 -0
  10. data/lib/config/os_configuration.rb +56 -0
  11. data/lib/entity.rb +11 -0
  12. data/lib/ikra.rb +7 -0
  13. data/lib/parsing.rb +32 -0
  14. data/lib/resources/cuda/block_function_head.cpp +1 -0
  15. data/lib/resources/cuda/env_builder_copy_array.cpp +4 -0
  16. data/lib/resources/cuda/header.cpp +46 -0
  17. data/lib/resources/cuda/kernel.cpp +8 -0
  18. data/lib/resources/cuda/kernel_launcher.cpp +28 -0
  19. data/lib/resources/cuda/soa_header.cpp +4 -0
  20. data/lib/scope.rb +166 -0
  21. data/lib/sourcify/Gemfile +10 -0
  22. data/lib/sourcify/HISTORY.txt +88 -0
  23. data/lib/sourcify/LICENSE +20 -0
  24. data/lib/sourcify/README.rdoc +352 -0
  25. data/lib/sourcify/Rakefile +111 -0
  26. data/lib/sourcify/lib/sourcify.rb +44 -0
  27. data/lib/sourcify/lib/sourcify/common/parser/converter.rb +29 -0
  28. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/comment.rb +23 -0
  29. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/counter.rb +43 -0
  30. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/dstring.rb +58 -0
  31. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/extensions.rb +140 -0
  32. data/lib/sourcify/lib/sourcify/common/parser/raw_scanner/heredoc.rb +26 -0
  33. data/lib/sourcify/lib/sourcify/common/parser/source_code.rb +45 -0
  34. data/lib/sourcify/lib/sourcify/common/ragel/common.rl +5 -0
  35. data/lib/sourcify/lib/sourcify/common/ragel/expressions.rl +38 -0
  36. data/lib/sourcify/lib/sourcify/common/ragel/machines.rl +317 -0
  37. data/lib/sourcify/lib/sourcify/errors.rb +4 -0
  38. data/lib/sourcify/lib/sourcify/method.rb +138 -0
  39. data/lib/sourcify/lib/sourcify/method/methods.rb +3 -0
  40. data/lib/sourcify/lib/sourcify/method/methods/to_raw_source.rb +30 -0
  41. data/lib/sourcify/lib/sourcify/method/methods/to_sexp.rb +30 -0
  42. data/lib/sourcify/lib/sourcify/method/methods/to_source.rb +30 -0
  43. data/lib/sourcify/lib/sourcify/method/parser.rb +110 -0
  44. data/lib/sourcify/lib/sourcify/method/parser/converter.rb +8 -0
  45. data/lib/sourcify/lib/sourcify/method/parser/raw_scanner.rb +2494 -0
  46. data/lib/sourcify/lib/sourcify/method/parser/raw_scanner.rl +144 -0
  47. data/lib/sourcify/lib/sourcify/method/parser/raw_scanner_extensions.rb +68 -0
  48. data/lib/sourcify/lib/sourcify/method/parser/scanner.rb +52 -0
  49. data/lib/sourcify/lib/sourcify/method/parser/source_code.rb +8 -0
  50. data/lib/sourcify/lib/sourcify/patches.rb +63 -0
  51. data/lib/sourcify/lib/sourcify/proc.rb +183 -0
  52. data/lib/sourcify/lib/sourcify/proc/methods.rb +3 -0
  53. data/lib/sourcify/lib/sourcify/proc/methods/source_location.rb +61 -0
  54. data/lib/sourcify/lib/sourcify/proc/methods/to_raw_source.rb +20 -0
  55. data/lib/sourcify/lib/sourcify/proc/methods/to_sexp.rb +40 -0
  56. data/lib/sourcify/lib/sourcify/proc/methods/to_source.rb +48 -0
  57. data/lib/sourcify/lib/sourcify/proc/parser.rb +51 -0
  58. data/lib/sourcify/lib/sourcify/proc/parser/converter.rb +8 -0
  59. data/lib/sourcify/lib/sourcify/proc/parser/normalizer.rb +43 -0
  60. data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner.rb +2498 -0
  61. data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner.rl +149 -0
  62. data/lib/sourcify/lib/sourcify/proc/parser/raw_scanner_extensions.rb +74 -0
  63. data/lib/sourcify/lib/sourcify/proc/parser/scanner.rb +49 -0
  64. data/lib/sourcify/lib/sourcify/proc/parser/source_code.rb +8 -0
  65. data/lib/sourcify/lib/sourcify/version.rb +3 -0
  66. data/lib/sourcify/sourcify.gemspec +31 -0
  67. data/lib/sourcify/spec/dump_object_space_procs.rb +84 -0
  68. data/lib/sourcify/spec/method/encoding_from_def_end_block_spec.rb +33 -0
  69. data/lib/sourcify/spec/method/encoding_from_define_method_spec.rb +37 -0
  70. data/lib/sourcify/spec/method/others_from_def_end_block_spec.rb +49 -0
  71. data/lib/sourcify/spec/method/others_from_define_method_spec.rb +63 -0
  72. data/lib/sourcify/spec/method/raw_scanner/block_comment_spec.rb +8 -0
  73. data/lib/sourcify/spec/method/raw_scanner/double_colons_spec.rb +8 -0
  74. data/lib/sourcify/spec/method/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
  75. data/lib/sourcify/spec/method/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
  76. data/lib/sourcify/spec/method/raw_scanner/heredoc_w_indent_spec.rb +8 -0
  77. data/lib/sourcify/spec/method/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
  78. data/lib/sourcify/spec/method/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
  79. data/lib/sourcify/spec/method/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
  80. data/lib/sourcify/spec/method/raw_scanner/per_line_comment_spec.rb +8 -0
  81. data/lib/sourcify/spec/method/raw_scanner/single_quote_str_spec.rb +8 -0
  82. data/lib/sourcify/spec/method/raw_scanner/slash_operator_spec.rb +8 -0
  83. data/lib/sourcify/spec/method/raw_scanner/spec_helper.rb +80 -0
  84. data/lib/sourcify/spec/method/spec_helper.rb +1 -0
  85. data/lib/sourcify/spec/method/to_raw_source_spec.rb +31 -0
  86. data/lib/sourcify/spec/method/to_raw_source_w_specified_strip_enclosure_spec.rb +148 -0
  87. data/lib/sourcify/spec/method/to_sexp_from_def_end_block_w_variables_spec.rb +46 -0
  88. data/lib/sourcify/spec/method/to_sexp_from_def_end_block_within_irb_spec.rb +38 -0
  89. data/lib/sourcify/spec/method/to_sexp_from_def_end_block_within_pry_spec.rb +38 -0
  90. data/lib/sourcify/spec/method/to_sexp_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +56 -0
  91. data/lib/sourcify/spec/method/to_sexp_from_define_method_w_variables_spec.rb +52 -0
  92. data/lib/sourcify/spec/method/to_sexp_from_define_method_within_irb_spec.rb +42 -0
  93. data/lib/sourcify/spec/method/to_sexp_from_define_method_within_pry_spec.rb +42 -0
  94. data/lib/sourcify/spec/method/to_sexp_w_specified_strip_enclosure_spec.rb +74 -0
  95. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_19_extras_spec.rb +23 -0
  96. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_begin_spec.rb +35 -0
  97. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_case_spec.rb +35 -0
  98. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_class_spec.rb +51 -0
  99. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_do_end_block_spec.rb +33 -0
  100. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_for_spec.rb +126 -0
  101. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_if_spec.rb +83 -0
  102. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_literal_keyword_spec.rb +141 -0
  103. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_method_spec.rb +33 -0
  104. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_module_spec.rb +59 -0
  105. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_unless_spec.rb +83 -0
  106. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_until_spec.rb +179 -0
  107. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_nested_while_spec.rb +179 -0
  108. data/lib/sourcify/spec/method/to_source_from_def_end_block_w_singleton_method_spec.rb +19 -0
  109. data/lib/sourcify/spec/method/to_source_from_def_end_block_within_irb_spec.rb +30 -0
  110. data/lib/sourcify/spec/method/to_source_from_def_end_block_within_pry_spec.rb +45 -0
  111. data/lib/sourcify/spec/method/to_source_from_def_end_w_multi_blocks_and_many_matches_spec.rb +30 -0
  112. data/lib/sourcify/spec/method/to_source_from_def_end_w_multi_blocks_and_single_match_spec.rb +36 -0
  113. data/lib/sourcify/spec/method/to_source_from_define_method_w_braced_block_spec.rb +113 -0
  114. data/lib/sourcify/spec/method/to_source_from_define_method_w_do_end_block_spec.rb +145 -0
  115. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_many_matches_spec.rb +56 -0
  116. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_single_match_spec.rb +73 -0
  117. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_many_matches_spec.rb +36 -0
  118. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_no_match_spec.rb +36 -0
  119. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_and_single_match_spec.rb +28 -0
  120. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_attached_to_spec.rb +103 -0
  121. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_many_matches_spec.rb +36 -0
  122. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_no_match_spec.rb +36 -0
  123. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_body_matcher_and_single_match_spec.rb +28 -0
  124. data/lib/sourcify/spec/method/to_source_from_define_method_w_multi_blocks_and_specified_ignore_nested_spec.rb +36 -0
  125. data/lib/sourcify/spec/method/to_source_from_define_method_within_irb_spec.rb +32 -0
  126. data/lib/sourcify/spec/method/to_source_from_define_method_within_pry_spec.rb +49 -0
  127. data/lib/sourcify/spec/method/to_source_magic_file_var_spec.rb +176 -0
  128. data/lib/sourcify/spec/method/to_source_magic_line_var_spec.rb +298 -0
  129. data/lib/sourcify/spec/method/to_source_w_specified_strip_enclosure_spec.rb +39 -0
  130. data/lib/sourcify/spec/no_method/unsupported_platform_spec.rb +26 -0
  131. data/lib/sourcify/spec/proc/19x_extras.rb +27 -0
  132. data/lib/sourcify/spec/proc/created_on_the_fly_proc_spec.rb +80 -0
  133. data/lib/sourcify/spec/proc/encoding_spec.rb +36 -0
  134. data/lib/sourcify/spec/proc/others_spec.rb +40 -0
  135. data/lib/sourcify/spec/proc/raw_scanner/block_comment_spec.rb +8 -0
  136. data/lib/sourcify/spec/proc/raw_scanner/double_colons_spec.rb +8 -0
  137. data/lib/sourcify/spec/proc/raw_scanner/double_quote_str_w_interpolation_spec.rb +8 -0
  138. data/lib/sourcify/spec/proc/raw_scanner/double_quote_str_wo_interpolation_spec.rb +8 -0
  139. data/lib/sourcify/spec/proc/raw_scanner/heredoc_w_indent_spec.rb +8 -0
  140. data/lib/sourcify/spec/proc/raw_scanner/heredoc_wo_indent_spec.rb +8 -0
  141. data/lib/sourcify/spec/proc/raw_scanner/kw_block_start_alias1_spec.rb +20 -0
  142. data/lib/sourcify/spec/proc/raw_scanner/kw_block_start_alias2_spec.rb +20 -0
  143. data/lib/sourcify/spec/proc/raw_scanner/per_line_comment_spec.rb +8 -0
  144. data/lib/sourcify/spec/proc/raw_scanner/single_quote_str_spec.rb +8 -0
  145. data/lib/sourcify/spec/proc/raw_scanner/slash_operator_spec.rb +8 -0
  146. data/lib/sourcify/spec/proc/raw_scanner/spec_helper.rb +63 -0
  147. data/lib/sourcify/spec/proc/readme +5 -0
  148. data/lib/sourcify/spec/proc/spec_helper.rb +1 -0
  149. data/lib/sourcify/spec/proc/to_raw_source_spec.rb +33 -0
  150. data/lib/sourcify/spec/proc/to_raw_source_w_specified_strip_enclosure_spec.rb +69 -0
  151. data/lib/sourcify/spec/proc/to_sexp_from_multi_blocks_w_specified_attached_to_spec.rb +46 -0
  152. data/lib/sourcify/spec/proc/to_sexp_variables_spec.rb +146 -0
  153. data/lib/sourcify/spec/proc/to_sexp_w_specified_strip_enclosure_spec.rb +60 -0
  154. data/lib/sourcify/spec/proc/to_sexp_within_irb_spec.rb +146 -0
  155. data/lib/sourcify/spec/proc/to_sexp_within_pry_spec.rb +149 -0
  156. data/lib/sourcify/spec/proc/to_source_from_braced_block_w_nested_braced_block_spec.rb +33 -0
  157. data/lib/sourcify/spec/proc/to_source_from_braced_block_w_nested_hash_spec.rb +82 -0
  158. data/lib/sourcify/spec/proc/to_source_from_braced_block_wo_nesting_complication_spec.rb +46 -0
  159. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_begin_spec.rb +35 -0
  160. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_case_spec.rb +35 -0
  161. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_class_spec.rb +89 -0
  162. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_do_end_block_spec.rb +33 -0
  163. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_for_spec.rb +132 -0
  164. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_if_spec.rb +87 -0
  165. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_literal_keyword_spec.rb +103 -0
  166. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_method_spec.rb +33 -0
  167. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_module_spec.rb +49 -0
  168. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_unless_spec.rb +87 -0
  169. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_until_spec.rb +189 -0
  170. data/lib/sourcify/spec/proc/to_source_from_do_end_block_w_nested_while_spec.rb +189 -0
  171. data/lib/sourcify/spec/proc/to_source_from_do_end_block_wo_nesting_complication_spec.rb +46 -0
  172. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_many_matches_spec.rb +43 -0
  173. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_single_match_spec.rb +20 -0
  174. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_many_matches_spec.rb +45 -0
  175. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_no_match_spec.rb +45 -0
  176. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_and_single_match_spec.rb +22 -0
  177. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_attached_to_spec.rb +84 -0
  178. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_many_matches_spec.rb +45 -0
  179. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_no_match_spec.rb +45 -0
  180. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_body_matcher_and_single_match_spec.rb +22 -0
  181. data/lib/sourcify/spec/proc/to_source_from_multi_blocks_w_specified_ignore_nested_spec.rb +43 -0
  182. data/lib/sourcify/spec/proc/to_source_from_multi_do_end_blocks_w_single_match_spec.rb +31 -0
  183. data/lib/sourcify/spec/proc/to_source_magic_file_var_spec.rb +127 -0
  184. data/lib/sourcify/spec/proc/to_source_magic_line_var_spec.rb +127 -0
  185. data/lib/sourcify/spec/proc/to_source_variables_spec.rb +29 -0
  186. data/lib/sourcify/spec/proc/to_source_w_specified_strip_enclosure_spec.rb +33 -0
  187. data/lib/sourcify/spec/proc/to_source_within_irb_spec.rb +38 -0
  188. data/lib/sourcify/spec/proc/to_source_within_pry_spec.rb +61 -0
  189. data/lib/sourcify/spec/raw_scanner/block_comment_shared_spec.rb +57 -0
  190. data/lib/sourcify/spec/raw_scanner/double_colons_shared_spec.rb +11 -0
  191. data/lib/sourcify/spec/raw_scanner/double_quote_str_w_interpolation_shared_spec.rb +60 -0
  192. data/lib/sourcify/spec/raw_scanner/double_quote_str_wo_interpolation_shared_spec.rb +86 -0
  193. data/lib/sourcify/spec/raw_scanner/heredoc_w_indent_shared_spec.rb +69 -0
  194. data/lib/sourcify/spec/raw_scanner/heredoc_wo_indent_shared_spec.rb +70 -0
  195. data/lib/sourcify/spec/raw_scanner/kw_block_start_alias1_shared_spec.rb +73 -0
  196. data/lib/sourcify/spec/raw_scanner/kw_block_start_alias2_shared_spec.rb +73 -0
  197. data/lib/sourcify/spec/raw_scanner/per_line_comment_shared_spec.rb +32 -0
  198. data/lib/sourcify/spec/raw_scanner/shared_specs.rb +3 -0
  199. data/lib/sourcify/spec/raw_scanner/single_quote_str_shared_spec.rb +79 -0
  200. data/lib/sourcify/spec/raw_scanner/slash_operator_shared_spec.rb +71 -0
  201. data/lib/sourcify/spec/run_build.sh +25 -0
  202. data/lib/sourcify/spec/spec_helper.rb +130 -0
  203. data/lib/symbolic/symbolic.rb +248 -0
  204. data/lib/symbolic/visitor.rb +51 -0
  205. data/lib/translator/block_translator.rb +123 -0
  206. data/lib/translator/command_translator.rb +421 -0
  207. data/lib/translator/last_returns_visitor.rb +57 -0
  208. data/lib/translator/local_variables_enumerator.rb +35 -0
  209. data/lib/translator/method_translator.rb +24 -0
  210. data/lib/translator/translator.rb +49 -0
  211. data/lib/type_aware_array.rb +71 -0
  212. data/lib/types/array_type.rb +51 -0
  213. data/lib/types/class_type.rb +128 -0
  214. data/lib/types/object_tracer.rb +162 -0
  215. data/lib/types/primitive_type.rb +73 -0
  216. data/lib/types/ruby_extension.rb +67 -0
  217. data/lib/types/ruby_type.rb +45 -0
  218. data/lib/types/type_inference.rb +382 -0
  219. data/lib/types/union_type.rb +155 -0
  220. 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
+