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,98 @@
1
+ module Laser
2
+ VERSION = "0.5.0"
3
+ TESTS_ACTIVATED = false
4
+ ROOT = File.expand_path(File.dirname(__FILE__))
5
+ SETTINGS = {}
6
+ def self.debug_puts(*args)
7
+ puts *args if debug?
8
+ end
9
+ def self.debug_p(*args)
10
+ p *args if debug?
11
+ end
12
+ def self.debug_pp(*args)
13
+ pp *args if debug?
14
+ end
15
+ def self.debug_dotty(graph)
16
+ graph.dotty
17
+ end
18
+ def self.debug?
19
+ SETTINGS[:debug]
20
+ end
21
+ end
22
+ Laser::SETTINGS[:debug] = (ENV['LASER_DEBUG'] == 'true')
23
+
24
+ # Dependencies
25
+ require 'ripper'
26
+ require 'treetop'
27
+ require 'ripper-plus'
28
+ require 'axiom_of_choice'
29
+ require 'stream'
30
+ require 'object_regex'
31
+ require 'trollop'
32
+ $:.unshift(File.expand_path(File.dirname(__FILE__)))
33
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'ext'))
34
+ require 'laser/third_party/rgl/dot' # KILLME
35
+ require 'laser/third_party/rgl/bidirectional'
36
+ require 'laser/third_party/rgl/depth_first_spanning_tree'
37
+ require 'laser/third_party/rgl/control_flow'
38
+ require 'laser/support/placeholder_object'
39
+ require 'laser/support/inheritable_attributes'
40
+ require 'laser/support/acts_as_struct'
41
+ require 'laser/support/module_extensions'
42
+ require 'laser/support/frequency'
43
+ require 'laser/analysis/errors'
44
+ require 'laser/analysis/lexical_analysis'
45
+
46
+ require 'laser/analysis/sexp_extensions/type_inference'
47
+ require 'laser/analysis/sexp_extensions/constant_extraction'
48
+ require 'laser/analysis/sexp_extensions/source_location'
49
+
50
+ require 'laser/analysis/sexp'
51
+ require 'laser/analysis/sexp_analysis'
52
+
53
+ require 'laser/analysis/arity'
54
+ require 'laser/analysis/argument_expansion'
55
+ require 'laser/analysis/method_call'
56
+ require 'laser/analysis/bindings'
57
+ require 'laser/analysis/signature'
58
+ require 'laser/analysis/bootstrap/laser_object'
59
+ require 'laser/analysis/bootstrap/laser_module'
60
+ require 'laser/analysis/bootstrap/laser_class'
61
+ require 'laser/analysis/bootstrap/laser_module_copy'
62
+ require 'laser/analysis/bootstrap/laser_singleton_class'
63
+ require 'laser/analysis/bootstrap/laser_proc'
64
+ require 'laser/analysis/bootstrap/laser_method'
65
+ require 'laser/analysis/laser_utils.rb'
66
+ require 'laser/analysis/protocol_registry'
67
+ require 'laser/analysis/scope'
68
+ require 'laser/analysis/comments'
69
+ require 'laser/analysis/control_flow'
70
+ Dir[File.join(File.dirname(__FILE__), 'laser/analysis/special_methods/*.rb')].each do |file|
71
+ require file
72
+ end
73
+
74
+ require 'laser/analysis/bootstrap/bootstrap'
75
+ # Liftoff Instructions:
76
+ # 1. Tuck in your shirt
77
+ # 2. Remove spurs
78
+ # 3. Bend at the waist
79
+ # 4. PULL UP ON THEM BOOTSTRAPS!
80
+ Laser::Analysis::Bootstrap.bootstrap
81
+ # Load the type engine
82
+ require 'laser/types/types'
83
+ Laser::Analysis::Bootstrap.bootstrap_magic
84
+ require 'laser/annotation_parser/parsers'
85
+
86
+ require 'laser/analysis/visitor'
87
+ require 'laser/analysis/annotations'
88
+ require 'laser/analysis/unused_methods'
89
+ # Runners
90
+ require 'laser/runner'
91
+ require 'laser/rake/task'
92
+ # Program logic
93
+ require 'laser/warning'
94
+ require 'laser/scanner'
95
+
96
+ require 'laser/version'
97
+ # All methods created from the stdlib should never be marked as unused.
98
+ Laser::Analysis::Bootstrap.load_standard_library
@@ -0,0 +1,95 @@
1
+ require 'yaml'
2
+ module Laser
3
+ module Analysis
4
+ module Annotations
5
+ extend ModuleExtensions
6
+ # Global annotations are only run once, at the root.
7
+ cattr_accessor_with_default :global_annotations, []
8
+
9
+ # Performs full analysis on the given inputs.
10
+ def self.annotate_inputs(inputs, opts={})
11
+ inputs.map! do |filename, text|
12
+ [filename, text, Sexp.new(RipperPlus.sexp(text), filename, text)]
13
+ end
14
+ apply_inherited_attributes(inputs)
15
+ perform_load_time_analysis(inputs, opts)
16
+ inputs.map! { |filename, _, tree| [filename, tree] }
17
+ end
18
+
19
+ # Applies all the inherited attributes to the given inputs, in the
20
+ # order specified by annotation_config.yaml
21
+ def self.apply_inherited_attributes(inputs)
22
+ ordered_annotations.each do |annotator|
23
+ inputs.each do |filename, text, tree|
24
+ Scope::GlobalScope.lookup('$"').value.unshift(filename)
25
+ if SETTINGS[:profile]
26
+ time = Benchmark.realtime { annotator.annotate_with_text(tree, text) }
27
+ puts "Time spent running #{annotator.class} on #{filename}: #{time}"
28
+ else
29
+ annotator.annotate_with_text(tree, text)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ # Performs load-time analysis on the given inputs. Inherited attributes
36
+ # must be applied at this point.
37
+ def self.perform_load_time_analysis(inputs, opts={})
38
+ inputs.each do |filename, text, tree|
39
+ if SETTINGS[:profile]
40
+ time = Benchmark.realtime { annotator.annotate_with_text(tree, text) }
41
+ puts "Time spent running #{annotator.class} on #{filename}: #{time}"
42
+ else
43
+ ControlFlow.perform_cfg_analysis(tree, text, opts)
44
+ end
45
+ end
46
+ end
47
+
48
+ # Returns the order that annotations should be run.
49
+ def self.annotation_ordered
50
+ @order ||= YAML.load_file(File.join(File.dirname(__FILE__), 'annotations', 'annotation_config.yaml'))
51
+ end
52
+
53
+ # Returns the inherited attributes in the order they are intended
54
+ # to be run by the YAML file.
55
+ def self.ordered_annotations
56
+ annotation_ordered.map do |mod_name|
57
+ global_annotations.select { |annotation| annotation.class.name.include?(mod_name) }.first
58
+ end
59
+ end
60
+ end
61
+ # This is the base module for all annotations that can run on ASTs.
62
+ # It includes all other annotation modules to provide all the
63
+ # annotations to the Sexp class. These annotations are run at initialize
64
+ # time for the Sexps and have access to a node and all of its child nodes,
65
+ # all of which have been annotated. Synthesized attributes are fair game,
66
+ # and adding inherited attributes to subnodes is also fair game.
67
+ #
68
+ # All annotations add O(V) to the parser running time.
69
+ #
70
+ # This module also provides some helper methods to inject functionality into
71
+ # the Sexp class. Since that's what an annotation is, I don't consider
72
+ # this bad form!
73
+ class BasicAnnotation
74
+ extend ModuleExtensions
75
+ include Visitor
76
+ cattr_accessor_with_default :dependencies, []
77
+ def self.inherited(klass)
78
+ add_global_annotator klass
79
+ end
80
+ def self.add_global_annotator(*args)
81
+ Annotations.global_annotations.concat args.map(&:new)
82
+ end
83
+ def self.add_property(*args)
84
+ Analysis::Sexp.__send__(:attr_accessor, *args)
85
+ end
86
+ def self.add_computed_property(name, &blk)
87
+ Analysis::Sexp.__send__(:define_method, name, &blk)
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ Dir[File.expand_path(File.join(File.dirname(__FILE__), 'annotations', '**', '*.rb'))].each do |file|
94
+ load file
95
+ end
@@ -0,0 +1,3 @@
1
+ - NodePointersAnnotation
2
+ - RuntimeAnnotation
3
+ - CommentAttachmentAnnotation
@@ -0,0 +1,66 @@
1
+ module Laser
2
+ module Analysis
3
+ # This annotation attempts to attach each comment in the program to the
4
+ # first node in the AST that follows the comment, as well as all subnodes with
5
+ # the same source location.
6
+ #
7
+ # This annotation will NOT always succeed, as it relies on the SourceLocationAnnotator,
8
+ # which due to limitations in Ripper's output, cannot always succeed.
9
+ class CommentAttachmentAnnotation < BasicAnnotation
10
+ add_property :comment
11
+ def annotate_with_text(root, text)
12
+ comments = extract_comments(text)
13
+ # root[1] here to ignore the spurious :program node
14
+ dfs_enumerator = root.dfs_enumerator
15
+ # For each comment:
16
+ # find the first node, by DFS, that has a location *greater* than the
17
+ # comment's. However, not all nodes will have locations due to Ripper
18
+ # being kinda crappy.
19
+ # When the enumerator finishes (raises StopIteration): we can no longer
20
+ # annotate. So return.
21
+ comments.each do |comment|
22
+ begin
23
+ cur = dfs_for_useful_node(dfs_enumerator)
24
+ end while (cur.source_begin <=> comment.location) == -1
25
+ # if we're here, we found the first node after the comment.
26
+ cur.comment = comment
27
+ extend_annotation_to_equal_nodes(cur, dfs_enumerator)
28
+ end
29
+ rescue StopIteration
30
+ # do nothing – this signals the end of the algorithm. If has_next made sense
31
+ # for enumerators, we'd use it, but it doesn't, so we just catch and return.
32
+ end
33
+
34
+ # Runs the generator until we find a node we can use in the context of
35
+ # comment annotation: it must have a source_begin attribute (not all nodes
36
+ # can successfully resolve their source_begin) and it shouldn't be a mere
37
+ # Array, it should have an actual node type.
38
+ def dfs_for_useful_node(generator)
39
+ begin
40
+ cur = generator.next
41
+ end until cur.source_begin && (::Symbol === cur[0])
42
+ cur
43
+ end
44
+
45
+ # Many nodes in the tree will have the same source_begin value, and they
46
+ # must all share the comment. Otherwise, we'll have a lot of trouble making
47
+ # sure that the interesting nodes, often nested deeply, will be annotated.
48
+ def extend_annotation_to_equal_nodes(first, generator)
49
+ while generator.peek.source_begin.nil? || generator.peek.source_begin[0] <= first.source_begin[0]
50
+ generator.next.comment = first.comment
51
+ end
52
+ end
53
+
54
+ # Extracts the comments from the text with some straightforward lexical analysis.
55
+ def extract_comments(text)
56
+ tokens = Ripper.lex(text).map { |tok| LexicalAnalysis::Token.new(tok) }
57
+ comments = ObjectRegex.new('comment (sp? comment)*').all_matches(tokens).map do |token_list|
58
+ token_list.select { |token| token.type == :on_comment }
59
+ end.map do |token_list|
60
+ body = token_list.map { |comment_token| comment_token.body[1..-1] }.join.rstrip
61
+ Comment.new(body, token_list.first.line, token_list.first.col)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,36 @@
1
+ module Laser
2
+ module Analysis
3
+ # This is a simple inherited attribute applied to each node,
4
+ # giving a pointer to that node's parent. That way AST traversal
5
+ # is easier.
6
+ # This is the annotator for the parent annotation.
7
+ class NodePointersAnnotation < BasicAnnotation
8
+ add_property :parent, :next, :prev
9
+ add_computed_property :ancestors do
10
+ case parent
11
+ when nil then []
12
+ else parent.ancestors + [parent]
13
+ end
14
+ end
15
+ add_computed_property :root do
16
+ case parent
17
+ when nil then self
18
+ else parent.root
19
+ end
20
+ end
21
+
22
+ # Replaces the general node visit method with one that assigns
23
+ # the current scope to the visited node.
24
+ def default_visit(node)
25
+ children = node.children
26
+ children.each_with_index do |elt, idx|
27
+ next unless Analysis::Sexp === elt
28
+ elt.parent = node
29
+ elt.next = children[idx+1]
30
+ elt.prev = children[idx-1] if idx >= 1
31
+ end
32
+ visit_children(node)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,55 @@
1
+ module Laser
2
+ module Analysis
3
+ # This is a simple inherited attribute that specifies whether a given node
4
+ # will be executed when at load-time or at run-time. In short, method bodies
5
+ # and not-run blocks at the top-level are not run, and everything else is.
6
+ #
7
+ # The possible values of #runtime are :load, :run, or :unknown.
8
+ class RuntimeAnnotation < BasicAnnotation
9
+ add_property :runtime
10
+
11
+ def annotate!(root)
12
+ @current_runtime = :load
13
+ super
14
+ end
15
+
16
+ def default_visit(node)
17
+ node.runtime = @current_runtime
18
+ visit_children(node)
19
+ end
20
+
21
+ def visit_with_runtime(*nodes, new_runtime)
22
+ old_runtime, @current_runtime = @current_runtime, new_runtime
23
+ nodes.each { |node| visit node }
24
+ ensure
25
+ @current_runtime = old_runtime
26
+ end
27
+
28
+ add :def do |node, name, params, body|
29
+ default_visit(node)
30
+ default_visit(name)
31
+ visit_with_runtime(params, body, :run)
32
+ end
33
+
34
+ add :defs do |node, singleton, separator, name, params, body|
35
+ default_visit(node)
36
+ default_visit(singleton)
37
+ default_visit(name)
38
+ visit_with_runtime(params, body, :run)
39
+ end
40
+
41
+ add :method_add_block do |node, call, block|
42
+ # TODO(adgar): Check if call is resolved, and if so, check if the block is in fact
43
+ # executed immediately or stored. If we know the answer to that, we can specify :run
44
+ # or :load for the block instead of just :unknown.
45
+ default_visit(node)
46
+ default_visit(call)
47
+
48
+ if @current_runtime == :load
49
+ then visit_with_runtime(block, :unknown)
50
+ else default_visit block
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,132 @@
1
+ module Laser
2
+ module Analysis
3
+ # This class handles the interpretation and expansion of arguments being
4
+ # passed to a method call.
5
+ class ArgumentExpansion
6
+ attr_reader :node
7
+ # @node can end up either being nil, for no args at all, or an
8
+ # args_add_block node.
9
+ def initialize(node)
10
+ node = node[1] if !node.nil? && node.type == :arg_paren
11
+ @node = node
12
+ end
13
+
14
+ # Returns whether the node has a block argument. If it does, it
15
+ # returns the block argument's node.
16
+ def has_block?
17
+ if node.nil?
18
+ false
19
+ elsif node.type == :args_add_block
20
+ node[2]
21
+ end
22
+ end
23
+
24
+ # Returns the arity of the argument block being passed, as a range of
25
+ # possible values.
26
+ def arity
27
+ return Arity::EMPTY if node.nil?
28
+ Arity.new(arity_for_node(node))
29
+ end
30
+
31
+ # Are there no arguments being passed?
32
+ def empty?
33
+ arity == (0..0)
34
+ end
35
+
36
+ # Returns whether all arguments are constant.
37
+ def is_constant?
38
+ return true if node.nil?
39
+ node_is_constant?(node)
40
+ end
41
+
42
+ # Returns an array of constant values that are the arguments being passed.
43
+ #
44
+ # pre-contract: is_constant?.should be_true
45
+ def constant_values
46
+ return [] if node.nil?
47
+ node_constant_values(node)
48
+ end
49
+
50
+ # Returns the block argument (&blk) for the argument expansion.
51
+ def block_arg
52
+ return false if node.nil?
53
+ block_arg_for_node node
54
+ end
55
+
56
+ private
57
+
58
+ # Finds the arity of a given argument node.
59
+ def arity_for_node(node)
60
+ case node[0]
61
+ when Array
62
+ node.inject(0..0) { |acc, cur| range_add(acc, arity_for_node(cur)) }
63
+ when :args_add_block
64
+ arity_for_node(node[1])
65
+ when :args_add_star
66
+ initial = arity_for_node(node[1])
67
+ star_arity = arity_for_star(node[2])
68
+ extra = node.size > 3 ? arity_for_node(node[3..-1]) : (0..0)
69
+ range_add(range_add(initial, star_arity), extra)
70
+ else
71
+ 1..1
72
+ end
73
+ end
74
+
75
+ # Adds two ranges together.
76
+ def range_add(r1, r2)
77
+ (r1.begin + r2.begin)..(r1.end + r2.end)
78
+ end
79
+
80
+ # Finds the arity for a splatted argument. If it's a constant value, we can
81
+ # compute its value
82
+ def arity_for_star(node)
83
+ if node.is_constant
84
+ ary = node.constant_value.to_a rescue [node.constant_value]
85
+ size = ary.size
86
+ size..size
87
+ else
88
+ 0..Float::INFINITY
89
+ end
90
+ end
91
+
92
+ # Returns the node representing the argument's block argument.
93
+ def block_arg_for_node(node)
94
+ case node.type
95
+ when :method_add_arg then block_arg_for_node node[2]
96
+ when :args_add_block then node[2]
97
+ when :arg_paren then block_arg_for_node node[1]
98
+ end
99
+ end
100
+
101
+ # Determines whether a given arg AST node is constant.
102
+ def node_is_constant?(node)
103
+ case node[0]
104
+ when nil then true
105
+ when Array then node.all? { |child| node_is_constant?(child) }
106
+ when :args_add_block
107
+ node[2] ? node_is_constant?(node[1..2]) : node_is_constant?(node[1])
108
+ when :args_add_star then node.children.all? { |child| node_is_constant?(child) }
109
+ else node.is_constant
110
+ end
111
+ end
112
+
113
+ # Determines the constant values of all arguments being passed, expanding
114
+ # splats.
115
+ def node_constant_values(node)
116
+ case node[0]
117
+ when nil then []
118
+ when Array then node.map { |child| node_constant_values(child) }
119
+ when :args_add_block
120
+ node_constant_values(node[1])
121
+ when :args_add_star
122
+ pre_args = node_constant_values(node[1])
123
+ splat_arg = node_constant_values(node[2])
124
+ real_splat_ary = splat_arg.to_a rescue [splat_arg]
125
+ post_args = node_constant_values(node[3..-1])
126
+ pre_args + real_splat_ary + post_args
127
+ else node.constant_value
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end