laser 0.7.0.pre1

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 (319) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +14 -0
  4. data/LICENSE +661 -0
  5. data/README.md +158 -0
  6. data/Rakefile +104 -0
  7. data/VERSION +1 -0
  8. data/bin/laser +7 -0
  9. data/design_docs/goals.md +57 -0
  10. data/design_docs/object_regex.md +426 -0
  11. data/design_docs/type_annotations.md +80 -0
  12. data/ext/laser/BasicBlock.cpp +572 -0
  13. data/ext/laser/BasicBlock.h +118 -0
  14. data/ext/laser/extconf.rb +3 -0
  15. data/features/laser.feature +25 -0
  16. data/features/step_definitions/laser_steps.rb +39 -0
  17. data/features/support/env.rb +14 -0
  18. data/features/support/testdata/1_input +1 -0
  19. data/features/support/testdata/1_output +1 -0
  20. data/features/support/testdata/2_input +4 -0
  21. data/features/support/testdata/2_output +4 -0
  22. data/features/support/testdata/3_input +8 -0
  23. data/features/support/testdata/3_output +11 -0
  24. data/features/support/testdata/4_input +5 -0
  25. data/features/support/testdata/4_output +5 -0
  26. data/features/support/testdata/5_input +13 -0
  27. data/laser.gemspec +382 -0
  28. data/lib/laser.rb +98 -0
  29. data/lib/laser/analysis/annotations.rb +95 -0
  30. data/lib/laser/analysis/annotations/annotation_config.yaml +3 -0
  31. data/lib/laser/analysis/annotations/comment_attachment_annotation.rb +66 -0
  32. data/lib/laser/analysis/annotations/node_pointers_annotation.rb +36 -0
  33. data/lib/laser/analysis/annotations/runtime_annotation.rb +55 -0
  34. data/lib/laser/analysis/argument_expansion.rb +132 -0
  35. data/lib/laser/analysis/arity.rb +34 -0
  36. data/lib/laser/analysis/bindings.rb +144 -0
  37. data/lib/laser/analysis/bootstrap/bootstrap.rb +298 -0
  38. data/lib/laser/analysis/bootstrap/laser_class.rb +106 -0
  39. data/lib/laser/analysis/bootstrap/laser_method.rb +255 -0
  40. data/lib/laser/analysis/bootstrap/laser_module.rb +403 -0
  41. data/lib/laser/analysis/bootstrap/laser_module_copy.rb +74 -0
  42. data/lib/laser/analysis/bootstrap/laser_object.rb +69 -0
  43. data/lib/laser/analysis/bootstrap/laser_proc.rb +150 -0
  44. data/lib/laser/analysis/bootstrap/laser_singleton_class.rb +44 -0
  45. data/lib/laser/analysis/comments.rb +35 -0
  46. data/lib/laser/analysis/control_flow.rb +28 -0
  47. data/lib/laser/analysis/control_flow/alias_analysis.rb +31 -0
  48. data/lib/laser/analysis/control_flow/basic_block.rb +105 -0
  49. data/lib/laser/analysis/control_flow/cfg_builder.rb +2505 -0
  50. data/lib/laser/analysis/control_flow/cfg_instruction.rb +190 -0
  51. data/lib/laser/analysis/control_flow/constant_propagation.rb +742 -0
  52. data/lib/laser/analysis/control_flow/control_flow_graph.rb +370 -0
  53. data/lib/laser/analysis/control_flow/lifetime_analysis.rb +91 -0
  54. data/lib/laser/analysis/control_flow/method_call_search.rb +26 -0
  55. data/lib/laser/analysis/control_flow/raise_properties.rb +25 -0
  56. data/lib/laser/analysis/control_flow/simulation.rb +385 -0
  57. data/lib/laser/analysis/control_flow/static_single_assignment.rb +185 -0
  58. data/lib/laser/analysis/control_flow/unreachability_analysis.rb +57 -0
  59. data/lib/laser/analysis/control_flow/unused_variables.rb +91 -0
  60. data/lib/laser/analysis/control_flow/yield_properties.rb +103 -0
  61. data/lib/laser/analysis/errors.rb +131 -0
  62. data/lib/laser/analysis/laser_utils.rb +18 -0
  63. data/lib/laser/analysis/lexical_analysis.rb +172 -0
  64. data/lib/laser/analysis/method_call.rb +68 -0
  65. data/lib/laser/analysis/protocol_registry.rb +30 -0
  66. data/lib/laser/analysis/scope.rb +118 -0
  67. data/lib/laser/analysis/sexp.rb +159 -0
  68. data/lib/laser/analysis/sexp_analysis.rb +40 -0
  69. data/lib/laser/analysis/sexp_extensions/constant_extraction.rb +115 -0
  70. data/lib/laser/analysis/sexp_extensions/source_location.rb +164 -0
  71. data/lib/laser/analysis/sexp_extensions/type_inference.rb +47 -0
  72. data/lib/laser/analysis/signature.rb +76 -0
  73. data/lib/laser/analysis/special_methods/send.rb +67 -0
  74. data/lib/laser/analysis/unused_methods.rb +21 -0
  75. data/lib/laser/analysis/visitor.rb +141 -0
  76. data/lib/laser/annotation_parser/annotations.treetop +126 -0
  77. data/lib/laser/annotation_parser/annotations_parser.rb +748 -0
  78. data/lib/laser/annotation_parser/class_annotations.treetop +82 -0
  79. data/lib/laser/annotation_parser/class_annotations_parser.rb +654 -0
  80. data/lib/laser/annotation_parser/overload.treetop +24 -0
  81. data/lib/laser/annotation_parser/overload_parser.rb +167 -0
  82. data/lib/laser/annotation_parser/parsers.rb +6 -0
  83. data/lib/laser/annotation_parser/structural.treetop +37 -0
  84. data/lib/laser/annotation_parser/structural_parser.rb +406 -0
  85. data/lib/laser/annotation_parser/useful_parsers.treetop +47 -0
  86. data/lib/laser/annotation_parser/useful_parsers_parser.rb +674 -0
  87. data/lib/laser/rake/task.rb +46 -0
  88. data/lib/laser/runner.rb +189 -0
  89. data/lib/laser/scanner.rb +169 -0
  90. data/lib/laser/standard_library/_thread.rb +110 -0
  91. data/lib/laser/standard_library/abbrev.rb +103 -0
  92. data/lib/laser/standard_library/array.rb +418 -0
  93. data/lib/laser/standard_library/base64.rb +91 -0
  94. data/lib/laser/standard_library/basic_object.rb +55 -0
  95. data/lib/laser/standard_library/benchmark.rb +556 -0
  96. data/lib/laser/standard_library/bignum.rb +185 -0
  97. data/lib/laser/standard_library/cgi.rb +275 -0
  98. data/lib/laser/standard_library/cgi/cookie.rb +147 -0
  99. data/lib/laser/standard_library/cgi/core.rb +791 -0
  100. data/lib/laser/standard_library/cgi/html.rb +1021 -0
  101. data/lib/laser/standard_library/cgi/session.rb +537 -0
  102. data/lib/laser/standard_library/cgi/session/pstore.rb +111 -0
  103. data/lib/laser/standard_library/cgi/util.rb +188 -0
  104. data/lib/laser/standard_library/class_definitions.rb +333 -0
  105. data/lib/laser/standard_library/comparable.rb +125 -0
  106. data/lib/laser/standard_library/complex.rb +162 -0
  107. data/lib/laser/standard_library/enumerable.rb +178 -0
  108. data/lib/laser/standard_library/exceptions.rb +135 -0
  109. data/lib/laser/standard_library/fixnum.rb +188 -0
  110. data/lib/laser/standard_library/float.rb +180 -0
  111. data/lib/laser/standard_library/hash.rb +237 -0
  112. data/lib/laser/standard_library/integer.rb +123 -0
  113. data/lib/laser/standard_library/laser_magic.rb +7 -0
  114. data/lib/laser/standard_library/nil_false_true.rb +113 -0
  115. data/lib/laser/standard_library/numbers.rb +192 -0
  116. data/lib/laser/standard_library/proc.rb +31 -0
  117. data/lib/laser/standard_library/set.rb +1348 -0
  118. data/lib/laser/standard_library/string.rb +666 -0
  119. data/lib/laser/standard_library/stringio.rb +2 -0
  120. data/lib/laser/standard_library/symbol.rb +125 -0
  121. data/lib/laser/standard_library/tsort.rb +242 -0
  122. data/lib/laser/support/acts_as_struct.rb +66 -0
  123. data/lib/laser/support/frequency.rb +55 -0
  124. data/lib/laser/support/inheritable_attributes.rb +145 -0
  125. data/lib/laser/support/module_extensions.rb +94 -0
  126. data/lib/laser/support/placeholder_object.rb +13 -0
  127. data/lib/laser/third_party/rgl/adjacency.rb +221 -0
  128. data/lib/laser/third_party/rgl/base.rb +228 -0
  129. data/lib/laser/third_party/rgl/bidirectional.rb +39 -0
  130. data/lib/laser/third_party/rgl/condensation.rb +47 -0
  131. data/lib/laser/third_party/rgl/connected_components.rb +138 -0
  132. data/lib/laser/third_party/rgl/control_flow.rb +170 -0
  133. data/lib/laser/third_party/rgl/depth_first_spanning_tree.rb +37 -0
  134. data/lib/laser/third_party/rgl/dominators.rb +124 -0
  135. data/lib/laser/third_party/rgl/dot.rb +93 -0
  136. data/lib/laser/third_party/rgl/graphxml.rb +51 -0
  137. data/lib/laser/third_party/rgl/implicit.rb +174 -0
  138. data/lib/laser/third_party/rgl/mutable.rb +117 -0
  139. data/lib/laser/third_party/rgl/rdot.rb +445 -0
  140. data/lib/laser/third_party/rgl/topsort.rb +72 -0
  141. data/lib/laser/third_party/rgl/transitivity.rb +180 -0
  142. data/lib/laser/third_party/rgl/traversal.rb +348 -0
  143. data/lib/laser/types/types.rb +433 -0
  144. data/lib/laser/version.rb +14 -0
  145. data/lib/laser/warning.rb +149 -0
  146. data/lib/laser/warning_sets/default.yml +13 -0
  147. data/lib/laser/warnings/assignment_in_condition.rb +20 -0
  148. data/lib/laser/warnings/comment_spacing.rb +31 -0
  149. data/lib/laser/warnings/extra_blank_lines.rb +30 -0
  150. data/lib/laser/warnings/extra_whitespace.rb +16 -0
  151. data/lib/laser/warnings/hash_symbol_18_warning.rb +63 -0
  152. data/lib/laser/warnings/hash_symbol_19_warning.rb +29 -0
  153. data/lib/laser/warnings/line_length.rb +115 -0
  154. data/lib/laser/warnings/misaligned_unindentation.rb +17 -0
  155. data/lib/laser/warnings/operator_spacing.rb +68 -0
  156. data/lib/laser/warnings/parens_on_declaration.rb +30 -0
  157. data/lib/laser/warnings/rescue_exception.rb +42 -0
  158. data/lib/laser/warnings/semicolon.rb +25 -0
  159. data/lib/laser/warnings/sexp_errors.rb +24 -0
  160. data/lib/laser/warnings/uncalled_method_warning.rb +7 -0
  161. data/lib/laser/warnings/useless_double_quotes.rb +38 -0
  162. data/spec/analysis_specs/annotations_spec.rb +47 -0
  163. data/spec/analysis_specs/annotations_specs/comment_attachment_spec.rb +68 -0
  164. data/spec/analysis_specs/annotations_specs/node_pointers_annotation_spec.rb +90 -0
  165. data/spec/analysis_specs/annotations_specs/runtime_annotation_spec.rb +135 -0
  166. data/spec/analysis_specs/annotations_specs/spec_helper.rb +33 -0
  167. data/spec/analysis_specs/argument_expansion_spec.rb +113 -0
  168. data/spec/analysis_specs/bindings_spec.rb +36 -0
  169. data/spec/analysis_specs/comment_spec.rb +93 -0
  170. data/spec/analysis_specs/control_flow_specs/cfg_instruction_spec.rb +111 -0
  171. data/spec/analysis_specs/control_flow_specs/constant_propagation_spec.rb +560 -0
  172. data/spec/analysis_specs/control_flow_specs/control_flow_graph_spec.rb +5 -0
  173. data/spec/analysis_specs/control_flow_specs/raise_properties_spec.rb +310 -0
  174. data/spec/analysis_specs/control_flow_specs/raise_type_inference_spec.rb +301 -0
  175. data/spec/analysis_specs/control_flow_specs/return_type_inference_spec.rb +431 -0
  176. data/spec/analysis_specs/control_flow_specs/simulation_spec.rb +158 -0
  177. data/spec/analysis_specs/control_flow_specs/spec_helper.rb +110 -0
  178. data/spec/analysis_specs/control_flow_specs/tuple_misuse_inference_spec.rb +125 -0
  179. data/spec/analysis_specs/control_flow_specs/unreachability_analysis_spec.rb +76 -0
  180. data/spec/analysis_specs/control_flow_specs/unused_variable_spec.rb +99 -0
  181. data/spec/analysis_specs/control_flow_specs/yield_properties_spec.rb +372 -0
  182. data/spec/analysis_specs/error_spec.rb +30 -0
  183. data/spec/analysis_specs/laser_class_spec.rb +322 -0
  184. data/spec/analysis_specs/lexical_analysis_spec.rb +184 -0
  185. data/spec/analysis_specs/protocol_registry_spec.rb +63 -0
  186. data/spec/analysis_specs/scope_annotation_spec.rb +1013 -0
  187. data/spec/analysis_specs/scope_spec.rb +126 -0
  188. data/spec/analysis_specs/sexp_analysis_spec.rb +30 -0
  189. data/spec/analysis_specs/sexp_extension_specs/constant_extraction_spec.rb +309 -0
  190. data/spec/analysis_specs/sexp_extension_specs/source_location_spec.rb +231 -0
  191. data/spec/analysis_specs/sexp_extension_specs/spec_helper.rb +1 -0
  192. data/spec/analysis_specs/sexp_extension_specs/type_inference_spec.rb +252 -0
  193. data/spec/analysis_specs/sexp_spec.rb +167 -0
  194. data/spec/analysis_specs/spec_helper.rb +27 -0
  195. data/spec/analysis_specs/unused_methods_spec.rb +65 -0
  196. data/spec/analysis_specs/visitor_spec.rb +64 -0
  197. data/spec/annotation_parser_specs/annotations_parser_spec.rb +89 -0
  198. data/spec/annotation_parser_specs/class_annotation_parser_spec.rb +120 -0
  199. data/spec/annotation_parser_specs/overload_parser_spec.rb +39 -0
  200. data/spec/annotation_parser_specs/parsers_spec.rb +14 -0
  201. data/spec/annotation_parser_specs/spec_helper.rb +1 -0
  202. data/spec/annotation_parser_specs/structural_parser_spec.rb +67 -0
  203. data/spec/laser_spec.rb +14 -0
  204. data/spec/rake_specs/spec_helper.rb +1 -0
  205. data/spec/rake_specs/task_spec.rb +67 -0
  206. data/spec/runner_spec.rb +207 -0
  207. data/spec/scanner_spec.rb +75 -0
  208. data/spec/spec_helper.rb +121 -0
  209. data/spec/standard_library/exceptions_spec.rb +19 -0
  210. data/spec/standard_library/globals_spec.rb +14 -0
  211. data/spec/standard_library/set_spec.rb +31 -0
  212. data/spec/standard_library/spec_helper.rb +1 -0
  213. data/spec/standard_library/standard_library_spec.rb +302 -0
  214. data/spec/support_specs/acts_as_struct_spec.rb +94 -0
  215. data/spec/support_specs/frequency_spec.rb +23 -0
  216. data/spec/support_specs/module_extensions_spec.rb +117 -0
  217. data/spec/support_specs/spec_helper.rb +1 -0
  218. data/spec/type_specs/spec_helper.rb +1 -0
  219. data/spec/type_specs/types_spec.rb +133 -0
  220. data/spec/warning_spec.rb +95 -0
  221. data/spec/warning_specs/assignment_in_condition_spec.rb +68 -0
  222. data/spec/warning_specs/comment_spacing_spec.rb +65 -0
  223. data/spec/warning_specs/extra_blank_lines_spec.rb +70 -0
  224. data/spec/warning_specs/extra_whitespace_spec.rb +33 -0
  225. data/spec/warning_specs/hash_symbol_18_warning_spec.rb +89 -0
  226. data/spec/warning_specs/hash_symbol_19_warning_spec.rb +63 -0
  227. data/spec/warning_specs/line_length_spec.rb +173 -0
  228. data/spec/warning_specs/misaligned_unindentation_spec.rb +35 -0
  229. data/spec/warning_specs/operator_spacing_spec.rb +104 -0
  230. data/spec/warning_specs/parens_on_declaration_spec.rb +57 -0
  231. data/spec/warning_specs/rescue_exception_spec.rb +105 -0
  232. data/spec/warning_specs/semicolon_spec.rb +58 -0
  233. data/spec/warning_specs/spec_helper.rb +1 -0
  234. data/spec/warning_specs/useless_double_quotes_spec.rb +74 -0
  235. data/status_reports/2010/12/2010-12-14.md +163 -0
  236. data/status_reports/2010/12/2010-12-23.md +298 -0
  237. data/status_reports/2010/12/2010-12-24.md +6 -0
  238. data/test/third_party_tests/rgl_tests/TestComponents.rb +65 -0
  239. data/test/third_party_tests/rgl_tests/TestCycles.rb +61 -0
  240. data/test/third_party_tests/rgl_tests/TestDirectedGraph.rb +125 -0
  241. data/test/third_party_tests/rgl_tests/TestDot.rb +18 -0
  242. data/test/third_party_tests/rgl_tests/TestEdge.rb +34 -0
  243. data/test/third_party_tests/rgl_tests/TestGraph.rb +71 -0
  244. data/test/third_party_tests/rgl_tests/TestGraphXML.rb +57 -0
  245. data/test/third_party_tests/rgl_tests/TestImplicit.rb +52 -0
  246. data/test/third_party_tests/rgl_tests/TestRdot.rb +863 -0
  247. data/test/third_party_tests/rgl_tests/TestTransitivity.rb +129 -0
  248. data/test/third_party_tests/rgl_tests/TestTraversal.rb +220 -0
  249. data/test/third_party_tests/rgl_tests/TestUnDirectedGraph.rb +102 -0
  250. data/test/third_party_tests/rgl_tests/examples/north/Graph.log +128 -0
  251. data/test/third_party_tests/rgl_tests/examples/north/g.10.0.graphml +28 -0
  252. data/test/third_party_tests/rgl_tests/examples/north/g.10.1.graphml +28 -0
  253. data/test/third_party_tests/rgl_tests/examples/north/g.10.11.graphml +31 -0
  254. data/test/third_party_tests/rgl_tests/examples/north/g.10.12.graphml +27 -0
  255. data/test/third_party_tests/rgl_tests/examples/north/g.10.13.graphml +27 -0
  256. data/test/third_party_tests/rgl_tests/examples/north/g.10.14.graphml +27 -0
  257. data/test/third_party_tests/rgl_tests/examples/north/g.10.15.graphml +26 -0
  258. data/test/third_party_tests/rgl_tests/examples/north/g.10.16.graphml +26 -0
  259. data/test/third_party_tests/rgl_tests/examples/north/g.10.17.graphml +26 -0
  260. data/test/third_party_tests/rgl_tests/examples/north/g.10.19.graphml +37 -0
  261. data/test/third_party_tests/rgl_tests/examples/north/g.10.2.graphml +28 -0
  262. data/test/third_party_tests/rgl_tests/examples/north/g.10.20.graphml +38 -0
  263. data/test/third_party_tests/rgl_tests/examples/north/g.10.22.graphml +43 -0
  264. data/test/third_party_tests/rgl_tests/examples/north/g.10.24.graphml +30 -0
  265. data/test/third_party_tests/rgl_tests/examples/north/g.10.25.graphml +45 -0
  266. data/test/third_party_tests/rgl_tests/examples/north/g.10.27.graphml +38 -0
  267. data/test/third_party_tests/rgl_tests/examples/north/g.10.28.graphml +30 -0
  268. data/test/third_party_tests/rgl_tests/examples/north/g.10.29.graphml +38 -0
  269. data/test/third_party_tests/rgl_tests/examples/north/g.10.3.graphml +26 -0
  270. data/test/third_party_tests/rgl_tests/examples/north/g.10.30.graphml +34 -0
  271. data/test/third_party_tests/rgl_tests/examples/north/g.10.31.graphml +42 -0
  272. data/test/third_party_tests/rgl_tests/examples/north/g.10.34.graphml +42 -0
  273. data/test/third_party_tests/rgl_tests/examples/north/g.10.37.graphml +28 -0
  274. data/test/third_party_tests/rgl_tests/examples/north/g.10.38.graphml +38 -0
  275. data/test/third_party_tests/rgl_tests/examples/north/g.10.39.graphml +36 -0
  276. data/test/third_party_tests/rgl_tests/examples/north/g.10.4.graphml +26 -0
  277. data/test/third_party_tests/rgl_tests/examples/north/g.10.40.graphml +37 -0
  278. data/test/third_party_tests/rgl_tests/examples/north/g.10.41.graphml +37 -0
  279. data/test/third_party_tests/rgl_tests/examples/north/g.10.42.graphml +26 -0
  280. data/test/third_party_tests/rgl_tests/examples/north/g.10.45.graphml +28 -0
  281. data/test/third_party_tests/rgl_tests/examples/north/g.10.46.graphml +32 -0
  282. data/test/third_party_tests/rgl_tests/examples/north/g.10.5.graphml +31 -0
  283. data/test/third_party_tests/rgl_tests/examples/north/g.10.50.graphml +30 -0
  284. data/test/third_party_tests/rgl_tests/examples/north/g.10.56.graphml +29 -0
  285. data/test/third_party_tests/rgl_tests/examples/north/g.10.57.graphml +32 -0
  286. data/test/third_party_tests/rgl_tests/examples/north/g.10.58.graphml +32 -0
  287. data/test/third_party_tests/rgl_tests/examples/north/g.10.6.graphml +26 -0
  288. data/test/third_party_tests/rgl_tests/examples/north/g.10.60.graphml +32 -0
  289. data/test/third_party_tests/rgl_tests/examples/north/g.10.61.graphml +34 -0
  290. data/test/third_party_tests/rgl_tests/examples/north/g.10.62.graphml +34 -0
  291. data/test/third_party_tests/rgl_tests/examples/north/g.10.68.graphml +30 -0
  292. data/test/third_party_tests/rgl_tests/examples/north/g.10.69.graphml +32 -0
  293. data/test/third_party_tests/rgl_tests/examples/north/g.10.7.graphml +29 -0
  294. data/test/third_party_tests/rgl_tests/examples/north/g.10.70.graphml +26 -0
  295. data/test/third_party_tests/rgl_tests/examples/north/g.10.71.graphml +27 -0
  296. data/test/third_party_tests/rgl_tests/examples/north/g.10.72.graphml +28 -0
  297. data/test/third_party_tests/rgl_tests/examples/north/g.10.74.graphml +29 -0
  298. data/test/third_party_tests/rgl_tests/examples/north/g.10.75.graphml +29 -0
  299. data/test/third_party_tests/rgl_tests/examples/north/g.10.78.graphml +27 -0
  300. data/test/third_party_tests/rgl_tests/examples/north/g.10.79.graphml +34 -0
  301. data/test/third_party_tests/rgl_tests/examples/north/g.10.8.graphml +29 -0
  302. data/test/third_party_tests/rgl_tests/examples/north/g.10.80.graphml +34 -0
  303. data/test/third_party_tests/rgl_tests/examples/north/g.10.82.graphml +35 -0
  304. data/test/third_party_tests/rgl_tests/examples/north/g.10.83.graphml +32 -0
  305. data/test/third_party_tests/rgl_tests/examples/north/g.10.85.graphml +34 -0
  306. data/test/third_party_tests/rgl_tests/examples/north/g.10.86.graphml +34 -0
  307. data/test/third_party_tests/rgl_tests/examples/north/g.10.88.graphml +37 -0
  308. data/test/third_party_tests/rgl_tests/examples/north/g.10.89.graphml +29 -0
  309. data/test/third_party_tests/rgl_tests/examples/north/g.10.9.graphml +26 -0
  310. data/test/third_party_tests/rgl_tests/examples/north/g.10.90.graphml +32 -0
  311. data/test/third_party_tests/rgl_tests/examples/north/g.10.91.graphml +31 -0
  312. data/test/third_party_tests/rgl_tests/examples/north/g.10.92.graphml +26 -0
  313. data/test/third_party_tests/rgl_tests/examples/north/g.10.93.graphml +32 -0
  314. data/test/third_party_tests/rgl_tests/examples/north/g.10.94.graphml +34 -0
  315. data/test/third_party_tests/rgl_tests/examples/north/g.12.8.graphml +40 -0
  316. data/test/third_party_tests/rgl_tests/examples/north/g.14.9.graphml +36 -0
  317. data/test/third_party_tests/rgl_tests/test_helper.rb +7 -0
  318. data/test/third_party_tests/test_inheritable_attributes.rb +187 -0
  319. metadata +470 -0
@@ -0,0 +1,74 @@
1
+ require 'delegate'
2
+ module Laser
3
+ module Analysis
4
+
5
+ # When you include a module in Ruby, it uses inheritance to model the
6
+ # relationship with the included module. This is how Ruby achieves
7
+ # multiple inheritance. However, to avoid destroying the tree shape of
8
+ # the inheritance hierarchy, when you include a module, it is *copied*
9
+ # and inserted between the current module/class and its superclass.
10
+ # It is marked as a T_ICLASS instead of a T_CLASS because it is an
11
+ # "internal", invisible class: it shouldn't show up when you use #superclass.
12
+ #
13
+ # Yes, that means even modules have superclasses. There's just no method
14
+ # to expose them because a module only ever has a null superclass or a
15
+ # copied-module superclass.
16
+ class LaserModuleCopy < DelegateClass(LaserClass)
17
+ attr_reader :delegated
18
+ def initialize(module_to_copy, with_super)
19
+ super(module_to_copy)
20
+ case module_to_copy
21
+ when LaserModuleCopy then @delegated = module_to_copy.delegated
22
+ else @delegated = module_to_copy
23
+ end
24
+ @superclass = with_super
25
+ end
26
+
27
+ def superclass
28
+ @superclass
29
+ end
30
+
31
+ def superclass=(other)
32
+ @superclass = other
33
+ end
34
+
35
+ def ==(other)
36
+ case other
37
+ when LaserModuleCopy then @delegated == other.delegated
38
+ else @delegated == other
39
+ end
40
+ end
41
+
42
+ # Redefined because otherwise it'll get delegated. Meh.
43
+ # TODO(adgar): Find a better solution than just copy-pasting this method.
44
+ def ancestors
45
+ if @superclass.nil?
46
+ then [self]
47
+ else [self] + @superclass.ancestors
48
+ end
49
+ end
50
+
51
+ def instance_variables
52
+ @delegated.instance_variables
53
+ end
54
+
55
+ def instance_method(name)
56
+ sym = name.to_sym
57
+ return @delegated.instance_method(sym) ||
58
+ (@superclass && @superclass.instance_method(sym))
59
+ end
60
+
61
+ def visibility_for(method)
62
+ return @delegated.visibility_for(method) ||
63
+ (@superclass && @superclass.visibility_for(method))
64
+ end
65
+
66
+ def instance_methods(include_superclass = true)
67
+ if include_superclass && @superclass
68
+ then @superclass.instance_methods | @delegated.instance_methods
69
+ else @delegated.instance_methods
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,69 @@
1
+ module Laser
2
+ module Analysis
3
+ # Catch all representation of an object. Should never have klass <: Module.
4
+ class LaserObject
5
+ extend ModuleExtensions
6
+ attr_reader :scope, :klass, :name
7
+ attr_writer :singleton_class
8
+ def initialize(klass = ClassRegistry['Object'], scope = Scope::GlobalScope,
9
+ name = "#<#{klass.path}:#{object_id.to_s(16)}>")
10
+ @klass = klass
11
+ @scope = scope
12
+ @name = name
13
+ @instance_variables = Hash.new do |h, k|
14
+ h[k] = Bindings::InstanceVariableBinding.new(k, nil)
15
+ end
16
+ end
17
+
18
+ def add_instance_method!(method)
19
+ singleton_class.add_instance_method!(method)
20
+ end
21
+
22
+ def inspect
23
+ return 'main' if self == Scope::GlobalScope.self_ptr
24
+ super
25
+ end
26
+
27
+ alias path name
28
+
29
+ def normal_class
30
+ if @singleton_class
31
+ return @singleton_class.superclass
32
+ else
33
+ return @klass
34
+ end
35
+ end
36
+
37
+ def singleton_class
38
+ return @singleton_class if @singleton_class
39
+ new_scope = ClosedScope.new(self.scope, nil)
40
+ @singleton_class = LaserSingletonClass.new(
41
+ ClassRegistry['Class'], new_scope, "Class:#{name}", self) do |new_singleton_class|
42
+ new_singleton_class.superclass = self.klass
43
+ end
44
+ @klass = @singleton_class
45
+ end
46
+
47
+ def laser_simulate(method, args, opts={})
48
+ opts = {self: self, mutation: false}.merge(opts)
49
+ method = klass.instance_method(method)
50
+ method.master_cfg.dup.simulate(args, opts.merge(method: method))
51
+ end
52
+
53
+ def instance_variable_defined?(var)
54
+ @instance_variables.has_key?(var)
55
+ end
56
+
57
+ def instance_variable_get(var)
58
+ @instance_variables[var].value
59
+ end
60
+
61
+ def instance_variable_set(var, value)
62
+ normal_class.instance_variable(var).inferred_type =
63
+ Types::UnionType.new([normal_class.instance_variable(var).expr_type,
64
+ Utilities.normal_class_for(value).as_type])
65
+ @instance_variables[var].bind!(value)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,150 @@
1
+ module Laser
2
+ module Analysis
3
+
4
+ class LaserProc < LaserObject
5
+ attr_accessor :ast_node, :arguments, :cfg, :exit_block, :lexical_self
6
+ attr_accessor :annotations
7
+ def initialize(arguments, ast_node, cfg = nil, callsite_block = nil)
8
+ @ast_node = ast_node
9
+ @arguments = arguments
10
+ @cfg = cfg
11
+ @callsite_block = callsite_block
12
+ @lexical_self = @exit_block = nil
13
+ @annotations = Hash.new { |h, k| h[k] = [] }
14
+ end
15
+
16
+ def start_block
17
+ @callsite_block && @callsite_block.block_taken_successors.first
18
+ end
19
+
20
+ def inspect
21
+ desc_part = "Proc:0x#{object_id.to_s(16)}@#{ast_node.file_name}"
22
+ arg_part = "(#{arguments.map(&:name).join(', ')})"
23
+ if ast_node.source_begin
24
+ "#<#{desc_part}:#{ast_node.line_number}*#{arg_part}>"
25
+ else
26
+ "#<#{desc_part}*#{arg_part}>"
27
+ end
28
+ end
29
+ alias name inspect
30
+
31
+ def compiled_cfg
32
+ return @cfg if @cfg
33
+ # since this is lazily compiling, we should update cref to reflect the runtime
34
+ # value before compiling. hackish.
35
+ if @ast_node.scope.self_ptr != Scope::GlobalScope.self_ptr
36
+ @ast_node.scope.lexical_target = @ast_node.scope.self_ptr.value.binding
37
+ end
38
+ builder = ControlFlow::GraphBuilder.new(@ast_node, @arguments, @ast_node.scope)
39
+ @cfg = builder.build
40
+ end
41
+
42
+ def simulate(args, block, opts={})
43
+ update_cfg_edges(opts) if opts[:invocation_sites]
44
+ self_to_use = opts[:self] || @lexical_self
45
+ cfg.simulate(args, opts.merge({self: self_to_use, block: block, start_block: start_block}))
46
+ end
47
+
48
+ def update_cfg_edges(opts)
49
+ opts[:invocation_sites][self].each do |callsite|
50
+ opts[:invocation_counts][self][callsite] += 1
51
+ callsite_succ = callsite.successors.find do |b|
52
+ b.name == start_block.name || b.name.include?("SSA-FIX-#{start_block.name}")
53
+ end
54
+ if !callsite.has_flag?(callsite_succ, RGL::ControlFlowGraph::EDGE_EXECUTABLE)
55
+ callsite.add_flag(callsite_succ, RGL::ControlFlowGraph::EDGE_EXECUTABLE)
56
+ else
57
+ exit_succ = exit_block.successors.find do |b|
58
+ b.name == start_block.name || b.name.include?("SSA-FIX-#{start_block.name}")
59
+ end
60
+ exit_block.add_flag(exit_succ, RGL::ControlFlowGraph::EDGE_EXECUTABLE)
61
+ end
62
+ end
63
+ end
64
+
65
+ def to_proc
66
+ self
67
+ end
68
+
69
+ def call(*args, &blk)
70
+
71
+ end
72
+
73
+ def ssa_cfg
74
+ @ssa_cfg ||= compiled_cfg.static_single_assignment_form
75
+ end
76
+
77
+ def klass
78
+ ClassRegistry['Proc']
79
+ end
80
+
81
+ %w(special pure builtin predictable mutation).each do |attr|
82
+ define_method(attr) do
83
+ default = attr == 'predictable'
84
+ note = self.annotations[attr]
85
+ which_value = note && note.first(&:literal?)
86
+ which_value ? which_value.literal : default
87
+ end
88
+ end
89
+
90
+ def annotated_return
91
+ notes = annotations['returns']
92
+ if notes.any?
93
+ if notes.size > 1
94
+ raise ArgumentError.new("Cannot have more than one 'returns' annotation")
95
+ end
96
+ return_type = notes.first
97
+ if return_type.type?
98
+ return_type.type
99
+ else
100
+ raise NotImplementedError.new('Literal annotated return types not implemented')
101
+ end
102
+ end
103
+ end
104
+
105
+ def annotated_yield_usage
106
+ notes = annotations['yield_usage']
107
+ if notes.any?
108
+ if notes.size > 1
109
+ raise ArgumentError.new("Cannot have more than one 'yield_usage' annotation")
110
+ end
111
+ yield_usage = notes.first
112
+ if yield_usage.type?
113
+ raise ArgumentError.new('yield_usage requires a literal yield usage category')
114
+ else
115
+ yield_usage.literal
116
+ end
117
+ end
118
+ end
119
+
120
+ def overloads
121
+ Hash[*(annotations['overload'].map do |overload|
122
+ raise ArgumentError.new('overload must be a type') unless overload.type?
123
+ proc_type = overload.type
124
+ unless Types::GenericType === proc_type && proc_type.base_type == Types::PROC
125
+ raise ArgumentError.new('overload must be a function type')
126
+ end
127
+ [proc_type.subtypes[0].element_types, proc_type]
128
+ end.flatten(1))]
129
+ end
130
+
131
+ def annotated_raise_frequency
132
+ if annotations['raises'].any?
133
+ annotations['raises'].select(&:literal?).map(&:literal).each do |literal|
134
+ return Frequency[literal] if !literal || Symbol === literal
135
+ end
136
+ nil
137
+ end
138
+ end
139
+
140
+ def raises
141
+ if annotations['raises'].any?
142
+ types = annotations['raises'].select(&:type?)
143
+ if types.any?
144
+ Types::UnionType.new(types.map { |note| note.type })
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,44 @@
1
+ module Laser
2
+ module Analysis
3
+ module SingletonClassFactory
4
+ def self.create_for(ruby_obj)
5
+ if nil == ruby_obj
6
+ return ClassRegistry['NilClass']
7
+ elsif true == ruby_obj
8
+ return ClassRegistry['TrueClass']
9
+ elsif false == ruby_obj
10
+ return ClassRegistry['FalseClass']
11
+ else
12
+ name = "Instance:#{ruby_obj.inspect}"
13
+ existing = ProtocolRegistry[name].first
14
+ existing || LaserSingletonClass.new(
15
+ ClassRegistry['Class'], Scope::GlobalScope, name, ruby_obj) do |new_singleton_class|
16
+ new_singleton_class.superclass = ClassRegistry[ruby_obj.class.name]
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ # Singleton classes are important to model separately: they only have one
23
+ # instance! Plus, the built-in classes have some oddities: TrueClass is
24
+ # actually a singleton class, not a normal class. true is its singleton
25
+ # object.
26
+ class LaserSingletonClass < LaserClass
27
+ attr_reader :singleton_instance
28
+ def initialize(klass, scope, path, instance_or_name)
29
+ super(klass, scope, path)
30
+ # Dirty hook for the magic singletons: nil, true, false.
31
+ if String === instance_or_name
32
+ result = LaserObject.new(self, scope, instance_or_name)
33
+ result.singleton_class = self
34
+ @singleton_instance = result
35
+ else
36
+ @singleton_instance = instance_or_name
37
+ end
38
+ end
39
+ def get_instance(scope=nil)
40
+ singleton_instance
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,35 @@
1
+ module Laser
2
+ # Comment class: basic class representing a comment extracted from the tokens
3
+ # in a Ruby token stream.
4
+ Comment = Struct.new(:body, :line, :col) do
5
+ def initialize(*args)
6
+ super
7
+ @features = nil
8
+ @map = nil
9
+ end
10
+
11
+ def location
12
+ [line, col]
13
+ end
14
+
15
+ def features
16
+ @features ||= body.gsub(/^#+\s?/, '').scan(/^\s*.*(?:\n\s{3,}.*)*/).map(&:strip)
17
+ end
18
+
19
+ def attribute(name)
20
+ feature = features.find { |part| part.lstrip.start_with?("#{name}:") }
21
+ feature.lstrip[(name.size + 1) .. -1].strip if feature
22
+ end
23
+
24
+ def annotations
25
+ parser = Parsers::AnnotationParser.new
26
+ features.map { |feature| parser.parse(feature) }.compact
27
+ end
28
+
29
+ def annotation_map
30
+ return @map if @map
31
+ initial = Hash.new { |h, k| h[k] = [] }
32
+ @map = annotations.inject(initial) { |acc, note| acc[note.name] << note; acc }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ require 'laser/BasicBlock'
2
+ require 'laser/analysis/control_flow/basic_block'
3
+ require 'laser/analysis/control_flow/cfg_instruction'
4
+ require 'laser/analysis/control_flow/unused_variables'
5
+ require 'laser/analysis/control_flow/unreachability_analysis'
6
+ require 'laser/analysis/control_flow/constant_propagation'
7
+ require 'laser/analysis/control_flow/simulation'
8
+ require 'laser/analysis/control_flow/lifetime_analysis'
9
+ require 'laser/analysis/control_flow/static_single_assignment'
10
+ require 'laser/analysis/control_flow/alias_analysis'
11
+ require 'laser/analysis/control_flow/yield_properties'
12
+ require 'laser/analysis/control_flow/method_call_search'
13
+ require 'laser/analysis/control_flow/alias_analysis'
14
+ require 'laser/analysis/control_flow/raise_properties'
15
+ require 'laser/analysis/control_flow/cfg_builder'
16
+ require 'laser/analysis/control_flow/control_flow_graph'
17
+
18
+ module Laser
19
+ module Analysis
20
+ module ControlFlow
21
+ def self.perform_cfg_analysis(tree, text, opts={})
22
+ graph = GraphBuilder.new(tree).build
23
+ graph.analyze(opts)
24
+ graph
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ module Laser
2
+ module Analysis
3
+ module ControlFlow
4
+ # Finds the properties of how the code yields to a block argument.
5
+ # Should not be used on top-level code, naturally.
6
+ module AliasAnalysis
7
+ def weak_local_aliases_for(initial, value_to_match = nil)
8
+ good_blocks = reachable_vertices
9
+ aliases = initial
10
+ aliases.merge(value_aliases(value_to_match))
11
+ worklist = aliases.map(&:uses).inject(:|)
12
+ until worklist.empty?
13
+ use = worklist.pop
14
+ if use[1] && good_blocks.include?(use.block)
15
+ if use[1] != :alias && aliases.add?(use[1])
16
+ worklist.merge(use[1].uses)
17
+ elsif use[1] == :alias && aliases.add?(use[2])
18
+ worklist.merge(use[2].uses)
19
+ end
20
+ end
21
+ end
22
+ aliases
23
+ end
24
+
25
+ def value_aliases(value_to_match)
26
+ value_to_match ? all_variables.select { |var| var.value == value_to_match} : []
27
+ end
28
+ end
29
+ end # ControlFlow
30
+ end # Analysis
31
+ end #
@@ -0,0 +1,105 @@
1
+ require 'enumerator'
2
+ require 'set'
3
+ module Laser
4
+ module Analysis
5
+ module ControlFlow
6
+ # Can't use the < DelegateClass(Array) syntax because of code reloading.
7
+ class BasicBlock
8
+ def duplicate_for_graph_copy(temp_lookup, insn_lookup)
9
+ result = BasicBlock.new(name)
10
+ instructions.each do |insn|
11
+ copy = insn.deep_dup(temp_lookup, block: result)
12
+ insn_lookup[insn] = copy
13
+ result.instructions << copy
14
+ copy
15
+ end
16
+ # successors/predecessors will be inserted by graph copy.
17
+ result
18
+ end
19
+
20
+ def is_fake?(dest)
21
+ has_flag?(dest, RGL::ControlFlowGraph::EDGE_FAKE)
22
+ end
23
+
24
+ def is_executable?(dest)
25
+ has_flag?(dest, RGL::ControlFlowGraph::EDGE_EXECUTABLE)
26
+ end
27
+
28
+ def real_successors
29
+ successors.reject { |dest| has_flag?(dest, RGL::ControlFlowGraph::EDGE_FAKE) }
30
+ end
31
+
32
+ def normal_successors
33
+ successors.reject { |dest| has_flag?(dest, RGL::ControlFlowGraph::EDGE_ABNORMAL) }
34
+ end
35
+
36
+ def variables
37
+ Set.new(instructions.map(&:explicit_targets).inject(:|))
38
+ end
39
+
40
+ # Gets all SSA Phi nodes that are in the block.
41
+ def phi_nodes
42
+ instructions.select { |ins| :phi == ins[0] }
43
+ end
44
+
45
+ def natural_instructions
46
+ instructions.reject { |ins| :phi == ins[0] }
47
+ end
48
+
49
+ def fall_through_block?
50
+ instructions.empty?
51
+ end
52
+
53
+ alias_method :disconnect_without_fixup, :disconnect
54
+
55
+ def disconnect(dest)
56
+ last_insn = instructions.last
57
+ if last_insn.type == :branch
58
+ which_to_keep = last_insn[3] == dest.name ? last_insn[2] : last_insn[3]
59
+ last_insn[1].uses.delete last_insn
60
+ last_insn.body.replace([:jump, which_to_keep])
61
+ end
62
+ # must update phi nodes.
63
+ unless dest.phi_nodes.empty?
64
+ which_phi_arg = dest.predecessors.to_a.index(self) + 2
65
+ dest.phi_nodes.each do |node|
66
+ node.delete_at(which_phi_arg)
67
+ if node.size == 3
68
+ node.replace([:assign, node[1], node[2]])
69
+ end
70
+ end
71
+ end
72
+ disconnect_without_fixup(dest)
73
+ end
74
+
75
+ # Formats the block all pretty-like for Graphviz. Horrible formatting for
76
+ # stdout.
77
+ def to_s
78
+ " | #{name} | \\n" + instructions.map do |ins|
79
+ opcode = ins.first.to_s
80
+ if ins.method_call? && Hash === ins.last
81
+ then range = 1..-2
82
+ else range = 1..-1
83
+ end
84
+ args = ins[range].map do |arg|
85
+ if Bindings::Base === arg
86
+ then arg.name
87
+ else arg.inspect
88
+ end
89
+ end
90
+ if ::Hash === ins.last && ins.last[:block]
91
+ args << {block: ins.last[:block]}
92
+ end
93
+ [opcode, *args].join(', ')
94
+ end.join('\\n')
95
+ end
96
+ end
97
+
98
+ class TerminalBasicBlock < BasicBlock
99
+ def instructions
100
+ []
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end