ikra 0.0.1

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.
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
+