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,57 @@
1
+ module Laser
2
+ module Analysis
3
+ module ControlFlow
4
+ module UnreachabilityAnalysis
5
+ # Dead Code Discovery: O(|V| + |E|)!
6
+ IGNORED_DEAD_CODE_NODES = [:@ident, :@op, :void_stmt]
7
+ def unreachable_vertices(dfst = depth_first_spanning_tree(self.enter))
8
+ vertices - dfst.vertices
9
+ end
10
+
11
+ def perform_dead_code_discovery(delete_dead=false)
12
+ dfst = depth_first_spanning_tree(self.enter)
13
+
14
+ dead_verts = unreachable_vertices(dfst)
15
+
16
+ # then, go over all code in dead blocks, and mark potentially dead
17
+ # ast nodes.
18
+ # O(V)
19
+ dead_verts.each do |blk|
20
+ blk.instructions.each { |ins| ins.node.reachable = false if ins.node }
21
+ end
22
+
23
+ # run through all reachable statements and mark those nodes, and their
24
+ # parents, as partially executing.
25
+ #
26
+ # at most |V| nodes will have cur.reachable = true set.
27
+ # at most O(V) instructions will be visited total.
28
+ dfst.each_vertex do |blk|
29
+ blk.instructions.each do |ins|
30
+ cur = ins.node
31
+ while cur
32
+ cur.reachable = true
33
+ cur = cur.parent
34
+ end
35
+ end
36
+ end
37
+ dfs_for_dead_code self.root
38
+ dead_verts.each { |block| remove_vertex block } if delete_dead
39
+ end
40
+
41
+ # Performs a simple DFS, adding errors to any nodes that are still
42
+ # marked unreachable.
43
+ def dfs_for_dead_code(node)
44
+ if node.reachable
45
+ node.children.select { |x| Sexp === x }.reject do |child|
46
+ child == [] || child[0].is_a?(::Fixnum) || IGNORED_DEAD_CODE_NODES.include?(child.type)
47
+ end.each do |child|
48
+ dfs_for_dead_code(child)
49
+ end
50
+ else
51
+ node.add_error DeadCodeWarning.new('Dead code', node)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,91 @@
1
+ module Laser
2
+ module Analysis
3
+ module ControlFlow
4
+ # Finds unused variables in the control-flow graph. See thesis for
5
+ # the algorithm and proof of correctness.
6
+ module UnusedVariables
7
+ IGNORED_VARS = Set.new(%w(self t#current_exception t#current_block t#exit_exception t#exception_value $!))
8
+
9
+ # Adds unused variable warnings to all nodes which define a variable
10
+ # that is not used.
11
+ def add_unused_variable_warnings
12
+ unused_variables.reject { |var| var.name.start_with?('%') }.each do |temp|
13
+ # TODO(adgar): KILLMESOON
14
+ next unless temp.definition && temp.definition.node
15
+ next if IGNORED_VARS.include?(temp.non_ssa_name)
16
+ node = temp.definition.node
17
+ node.add_error(
18
+ UnusedVariableWarning.new("Variable defined but not used: #{temp.non_ssa_name}", node))
19
+ end
20
+ end
21
+
22
+ # Finds the simply-unused variables: those which are defined and never
23
+ # read.
24
+ def simple_unused
25
+ variables = self.all_variables
26
+ result = variables.dup
27
+ variables.each do |var|
28
+ defn = var.definition
29
+ if defn.node.nil? || defn.node.reachable
30
+ var.uses.each do |use|
31
+ if use.node.nil? || use.node.reachable
32
+ result.delete var
33
+ else
34
+ var.uses.delete use
35
+ end
36
+ end
37
+ else
38
+ var.uses.clear
39
+ end
40
+ end
41
+ result
42
+ end
43
+
44
+ # Gets the set of unused variables. After SSA transformation, any
45
+ # variable with no uses need not be assigned. If the definition of
46
+ # that variable can be killed, then we remove that definition as a
47
+ # use of all its operands. This may result in further dead variables!
48
+ # N = number of vars
49
+ # O(N)
50
+ def unused_variables
51
+ worklist = Set.new(simple_unused())
52
+ Laser.debug_puts('>>> Finished finding simple unused vars <<<')
53
+ all_unused = Set.new
54
+ while worklist.any?
55
+ var = worklist.pop
56
+ if all_unused.add?(var)
57
+ definition = var.definition
58
+ if killable_with_unused_target?(definition)
59
+ definition.operands.each do |op|
60
+ next if op.name == 'self'
61
+ use_set = op.uses
62
+ use_set = use_set - [definition]
63
+ worklist << op if use_set.empty?
64
+ end
65
+ end
66
+ end
67
+ end
68
+ all_unused
69
+ end
70
+
71
+ def killable_with_unused_target?(insn)
72
+ case insn.type
73
+ when :assign, :phi, :lambda
74
+ true
75
+ when :call, :call_vararg
76
+ recv = insn[2]
77
+ if Bindings::ConstantBinding === insn[2]
78
+ true
79
+ elsif insn[2].value == UNDEFINED
80
+ true
81
+ else
82
+ insn[2].expr_type.matching_methods(insn[3].to_s).all?(&:pure)
83
+ end
84
+ else
85
+ false
86
+ end
87
+ end
88
+ end
89
+ end # ControlFlow
90
+ end # Analysis
91
+ end #
@@ -0,0 +1,103 @@
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 YieldProperties
7
+ def find_yield_properties(opts)
8
+ kernel_method_to_fix = ClassRegistry['Kernel'].
9
+ instance_method(:block_given?)
10
+ proc_method_to_fix = ClassRegistry['Proc'].singleton_class.
11
+ instance_method(:new)
12
+ magic_method_to_fix = ClassRegistry['Laser#Magic'].singleton_class.
13
+ instance_method(:current_block)
14
+
15
+ # Calculate the "no block provided" case
16
+ without_yield = dup
17
+ without_yield.bind_block_type(Types::NILCLASS)
18
+ without_yield.perform_constant_propagation(opts.merge(
19
+ fixed_methods: { kernel_method_to_fix => false,
20
+ proc_method_to_fix => nil }))
21
+ without_yield.kill_unexecuted_edges
22
+
23
+ weak_without_calls = without_yield.potential_block_calls(opts)
24
+ yield_pd = without_yield.yield_fail_postdominator
25
+ has_yield_pd = yield_pd && yield_pd.real_predecessors.size > 0
26
+ return_pd = without_yield.return_postdominator
27
+ has_return_pd = return_pd && return_pd.real_predecessors.size > 0
28
+ yields_without_block = has_yield_pd || weak_without_calls.size > 0
29
+
30
+ # Calculate the "has block provided" case
31
+ with_yield = dup
32
+ with_yield.bind_block_type(Types::PROC)
33
+ fake_block = proc { |*args| }
34
+ with_yield.perform_constant_propagation(opts.merge(
35
+ fixed_methods: { kernel_method_to_fix => true,
36
+ magic_method_to_fix => fake_block,
37
+ proc_method_to_fix => fake_block}))
38
+ with_yield.kill_unexecuted_edges
39
+ weak_with_calls = with_yield.potential_block_calls(fake_block, opts)
40
+ yields_with_block = weak_with_calls.size > 0
41
+ # if the mere difference in block presence results in no exit path, then
42
+ # we consider this evidence of failure due to lack of block.
43
+ yields_without_block = true if yields_with_block && !has_return_pd
44
+
45
+ @yield_type = compute_yield_type(yields_with_block, yields_without_block)
46
+ @yield_arity = calculate_yield_arity(weak_with_calls)
47
+ end
48
+
49
+ def compute_yield_type(with_block, without_block)
50
+ case [with_block, without_block]
51
+ when [true, true] then :required
52
+ when [true, false] then :optional
53
+ when [false, true] then :foolish
54
+ when [false, false] then :ignored
55
+ end
56
+ end
57
+
58
+ def calculate_yield_arity(calls)
59
+ yield_arity = Set.new
60
+ calls.each do |call|
61
+ case call.type
62
+ when :call then yield_arity << (call.size - 5)
63
+ when :call_vararg then yield_arity << (0..Float::INFINITY)
64
+ end
65
+ end
66
+ yield_arity
67
+ end
68
+
69
+ def initial_block_aliases(opts)
70
+ proc_new_calls = find_method_calls(
71
+ ClassRegistry['Proc'].singleton_class.instance_method(:new), opts)
72
+ registers = proc_new_calls.map { |insn| insn[1] }
73
+ initial_aliases = Set.new(registers)
74
+ initial_aliases.add(block_register)
75
+ end
76
+
77
+ def potential_block_calls(block_value = nil, opts)
78
+ aliases = weak_local_aliases_for(initial_block_aliases(opts), block_value)
79
+ calls = []
80
+ reachable_vertices do |block|
81
+ block.instructions.each do |insn|
82
+ # consider runtime aliases, don't hardcode known ones
83
+ if (insn.type == :call || insn.type == :call_vararg) &&
84
+ (insn[3] == :call || insn[3] == :=== || insn[3] == :[]) && aliases.include?(insn[2])
85
+ calls << insn
86
+ elsif aliases.include?(insn.block_operand)
87
+ insn.possible_methods(opts).each do |method|
88
+ yield_type = method.yield_type
89
+ if block_value.nil? && (yield_type == :required || yield_type == :foolish) ||
90
+ !block_value.nil? && (yield_type == :required || yield_type == :optional)
91
+ calls << insn
92
+ break
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ calls
99
+ end
100
+ end
101
+ end # ControlFlow
102
+ end # Analysis
103
+ end #
@@ -0,0 +1,131 @@
1
+ module Laser
2
+ # Base class for all Laser errors. Has a few fields that are important for later
3
+ # referencing during error reporting.
4
+ class Error < StandardError
5
+ ADVISORY = 1
6
+ STYLE = 2
7
+ MINOR_WARNING = 3
8
+ WARNING = 4
9
+ MAJOR_WARNING = 5
10
+ SIMPLE_ERROR = 6
11
+ ERROR = 7
12
+ TRICKY_ERROR = 8
13
+ MAJOR_ERROR = 9
14
+ FUCKUP = 10
15
+
16
+ def self.severity(new_severity)
17
+ define_method :initialize do |msg, node|
18
+ super(msg, node, new_severity)
19
+ end
20
+ end
21
+
22
+ attr_accessor :ast_node, :severity
23
+ def initialize(message, ast_node, severity = 5)
24
+ super(message)
25
+ @ast_node, @severity = ast_node, severity
26
+ end
27
+
28
+ def ==(other)
29
+ other.class == self.class && other.message == self.message &&
30
+ other.ast_node == self.ast_node && self.severity == other.severity
31
+ end
32
+
33
+ def line_number
34
+ ast_node.line_number
35
+ end
36
+
37
+ def inspect
38
+ "#<#{self.class}: #{message} (#{ast_node.file_name}:#{ast_node.source_begin[0]})>"
39
+ end
40
+ end
41
+
42
+ class ReopenedClassAsModuleError < Laser::Error
43
+ severity MAJOR_ERROR
44
+ end
45
+
46
+ class ReopenedModuleAsClassError < Laser::Error
47
+ severity MAJOR_ERROR
48
+ end
49
+
50
+ class ConstantInForLoopError < Laser::Error
51
+ def initialize(const_name, ast)
52
+ super("The constant #{const_name} is a loop variable in a for loop.",
53
+ ast, MAJOR_ERROR)
54
+ end
55
+ end
56
+
57
+ class DoubleIncludeError < Laser::Error
58
+ severity MAJOR_WARNING
59
+ end
60
+
61
+ class DynamicSuperclassError < Laser::Error
62
+ severity MAJOR_ERROR
63
+ end
64
+
65
+ class NoSuchMethodError < Laser::Error
66
+ severity MAJOR_ERROR
67
+ end
68
+
69
+ class NotInMethodError < Laser::Error
70
+ severity FUCKUP
71
+ end
72
+
73
+ class IncompatibleArityError < Laser::Error
74
+ severity MAJOR_ERROR
75
+ end
76
+
77
+ class FailedAliasError < Laser::Error
78
+ severity MAJOR_ERROR
79
+ end
80
+
81
+ class SuperclassMismatchError < Laser::Error
82
+ severity TRICKY_ERROR
83
+ end
84
+
85
+ class DeadCodeWarning < Laser::Error
86
+ severity MAJOR_WARNING
87
+ def initialize(message, ast_node)
88
+ if ast_node.source_begin
89
+ super("Dead Code #{ast_node.source_begin[0]}:#{ast_node.source_begin[1]}", ast_node)
90
+ else
91
+ super("Dead Code", ast_node)
92
+ end
93
+ end
94
+ end
95
+
96
+ class UnusedVariableWarning < Laser::Error
97
+ severity WARNING
98
+ end
99
+
100
+ class TopLevelSimulationRaised < Laser::Error
101
+ attr_reader :error
102
+ def initialize(message, ast_node, detected_error)
103
+ super(message, ast_node, FUCKUP)
104
+ @error = detected_error
105
+ end
106
+ end
107
+
108
+ class NoMatchingTypeSignature < Laser::Error
109
+ severity MAJOR_ERROR
110
+ end
111
+
112
+ class MissingBlockError < Laser::Error
113
+ severity TRICKY_ERROR
114
+ end
115
+
116
+ class UnnecessaryBlockError < Laser::Error
117
+ severity TRICKY_ERROR
118
+ end
119
+
120
+ class ImproperOverloadTypeError < Laser::Error
121
+ severity TRICKY_ERROR
122
+ end
123
+
124
+ class DiscardedRHSError < Laser::Error
125
+ severity SIMPLE_ERROR
126
+ end
127
+
128
+ class UnassignedLHSError < Laser::Error
129
+ severity SIMPLE_ERROR
130
+ end
131
+ end
@@ -0,0 +1,18 @@
1
+ module Laser
2
+ module Analysis
3
+ module Utilities
4
+ module_function
5
+ def klass_for(arg)
6
+ LaserObject === arg ? arg.singleton_class : SingletonClassFactory.create_for(arg)
7
+ end
8
+
9
+ def type_for(arg, variance=:invariant)
10
+ Types::ClassObjectType.new(klass_for(arg))
11
+ end
12
+
13
+ def normal_class_for(arg)
14
+ LaserObject === arg ? arg.normal_class : ClassRegistry[arg.class.name]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,172 @@
1
+ module Laser
2
+ # This is a set of methods that get provided to Warnings so they can perform
3
+ # lexical analysis of their bodies. This module handles tokenizing only - not
4
+ # parse-trees.
5
+ module LexicalAnalysis
6
+ # This is a wrapper class around the tokens returned by Ripper. Since the
7
+ # tokens are just arrays, this class lets us use nice mnemonics with almost zero
8
+ # runtime overhead.
9
+ Token = Struct.new(:type, :body, :line, :col) do
10
+ # Unpacks the token from Ripper and breaks it into its separate components.
11
+ #
12
+ # @param [Array<Array<Integer, Integer>, Symbol, String>] token the token
13
+ # from Ripper that we're wrapping
14
+ def initialize(token)
15
+ (self.line, self.col), self.type, self.body = token
16
+ end
17
+
18
+ def reg_desc
19
+ type.to_s.gsub(/^on_/, '')
20
+ end
21
+ end
22
+
23
+ # Lexes the given text.
24
+ #
25
+ # @param [String] body (self.body) The text to lex
26
+ # @return [Array<Array<Integer, Integer>, Symbol, String>] A set of tokens
27
+ # in Ripper's result format. Each token is an array of the form:
28
+ # [[1, token_position], token_type, token_text]. I'm not exactly clear on
29
+ # why the 1 is always there. At any rate - the result is an array of those
30
+ # tokens.
31
+ def lex(body = self.body, token_class = Token)
32
+ return [] if body =~ /^#.*encoding.*/
33
+ Ripper.lex(body).map {|token| token_class.new(token) }
34
+ end
35
+
36
+ # Returns the text between two token positions. The token positions are
37
+ # in [line, column] format. The body, left, and right tokens must be provided,
38
+ # and optionally, you can override the inclusiveness of the text-between operation.
39
+ # It defaults to :none, for including neither the left nor right tokens in the
40
+ # result. You can pass :none, :left, :right, or :both.
41
+ #
42
+ # @param [String] body (self.body) The first parameter is optional: the text
43
+ # to search. This defaults to the full text.
44
+ # @param [Token] left the left token to get the text between
45
+ # @param [Token] right the right token to get the text between
46
+ # @param [Symbol] inclusive should the :left, :right, :both, or :none tokens
47
+ # be included in the resulting text?
48
+ # @return the text between the two tokens within the text. This is necessary
49
+ # because the lexer provides [line, column] coordinates which is quite
50
+ # unfortunate.
51
+ def text_between_token_positions(text, left, right, inclusive = :none)
52
+ result = ""
53
+ lines = text.lines.to_a
54
+ left.line.upto(right.line) do |cur_line|
55
+ line = lines[cur_line - 1]
56
+ result << left.body if cur_line == left.line && (inclusive == :both || inclusive == :left)
57
+ left_bound = cur_line == left.line ? left.col + left.body.size : 0
58
+ right_bound = cur_line == right.line ? right.col - 1 : -1
59
+ result << line[left_bound..right_bound]
60
+ result << right.body if cur_line == right.line && (inclusive == :both || inclusive == :right)
61
+ end
62
+ result
63
+ end
64
+
65
+ # Searches for the given token using standard [body], target symbols syntax.
66
+ # Yields for each token found that matches the query, and returns all those
67
+ # who match.
68
+ #
69
+ # @param [String] body (self.body) The first parameter is optional: the text
70
+ # to search. This defaults to the full text.
71
+ # @param [Symbol] token The rest of the arguments are tokens to search
72
+ # for. Any number of tokens may be specified.
73
+ # @return [Array<Array>] All the matching tokens for the query
74
+ # @deprecated
75
+ #
76
+ # def select_token(*args)
77
+ # body, list = _extract_token_search_args(args)
78
+ # result = []
79
+ # while (token = find_token(body, *list)) && token != nil
80
+ # result << token if yield(*token)
81
+ # _, body = split_on_token(body, *list)
82
+ # body = body[token.body.size..-1]
83
+ # end
84
+ # return result
85
+ # end
86
+
87
+ # Finds the first instance of a set of keywords in the body. If no text is
88
+ # given to scan, then the full content is scanned.
89
+ #
90
+ # @param [String] body (self.body) The first parameter is optional: the text
91
+ # to search. This defaults to the full text.
92
+ # @param [Symbol] keyword The rest of the arguments are keywords to search
93
+ # for. Any number of keywords may be specified.
94
+ # @return [Array] the token in the form returned by Ripper. See #lex.
95
+ def find_keyword(*args)
96
+ body, list = _extract_token_search_args(args)
97
+ list.map! {|x| x.to_s}
98
+ lexed = lex(body)
99
+ lexed.find.with_index do |tok, idx|
100
+ is_keyword = tok.type == :on_kw && list.include?(tok.body)
101
+ is_not_symbol = idx == 0 || lexed[idx-1].type != :on_symbeg
102
+ is_keyword && is_not_symbol
103
+ end
104
+ end
105
+
106
+ # Finds the first instance of a set of tokens in the body. If no text is
107
+ # given to scan, then the full content is scanned.
108
+ #
109
+ # @param [String] body (self.body) The first parameter is optional: the text
110
+ # to search. This defaults to the full text.
111
+ # @param [Symbol] token The rest of the arguments are tokens to search
112
+ # for. Any number of tokens may be specified.
113
+ # @return [Array] the token in the form returned by Ripper. See #lex.
114
+ def find_token(*args)
115
+ body, list = _extract_token_search_args(args)
116
+ # grr match comment with encoding in it
117
+ lexed = lex(body)
118
+ lexed.find.with_index do |tok, idx|
119
+ is_token = list.include?(tok.type)
120
+ is_not_symbol = idx == 0 || lexed[idx-1].type != :on_symbeg
121
+ is_token && is_not_symbol
122
+ end
123
+ end
124
+
125
+ # Splits the body into two halfs based on the first appearance of a keyword.
126
+ #
127
+ # @example
128
+ # split_on_keyword('x = 5 unless y == 2', :unless)
129
+ # # => ['x = 5 ', 'unless y == 2']
130
+ # @param [String] body (self.body) The first parameter is optional: the text
131
+ # to search. This defaults to the full text.
132
+ # @param [Symbol] token The rest of the arguments are keywords to search
133
+ # for. Any number of keywords may be specified.
134
+ # @return [Array<String, String>] The body split by the keyword.
135
+ def split_on_keyword(*args)
136
+ body, keywords = _extract_token_search_args(args)
137
+ token = find_keyword(body, *keywords)
138
+ return _split_body_with_raw_token(body, token)
139
+ end
140
+
141
+ # Splits the body into two halfs based on the first appearance of a token.
142
+ #
143
+ # @example
144
+ # split_on_token('x = 5 unless y == 2', :on_kw)
145
+ # # => ['x = 5 ', 'unless y == 2']
146
+ # @param [String] body (self.body) The first parameter is optional: the text
147
+ # to search. This defaults to the full text.
148
+ # @param [Symbol] token The rest of the arguments are tokens to search
149
+ # for. Any number of tokens may be specified.
150
+ # @return [Array<String, String>] The body split by the token.
151
+ def split_on_token(*args)
152
+ body, tokens = _extract_token_search_args(args)
153
+ token = find_token(body, *tokens)
154
+ return _split_body_with_raw_token(body, token)
155
+ end
156
+
157
+ private
158
+
159
+ def _extract_token_search_args(args)
160
+ if args.first.is_a?(String)
161
+ return args[0], args[1..-1]
162
+ else
163
+ return self.body, args
164
+ end
165
+ end
166
+
167
+ def _split_body_with_raw_token(body, token)
168
+ max = token ? [0, token.col].max : body.size
169
+ return body[0,max], body[max..-1]
170
+ end
171
+ end
172
+ end