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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +14 -0
- data/LICENSE +661 -0
- data/README.md +158 -0
- data/Rakefile +104 -0
- data/VERSION +1 -0
- data/bin/laser +7 -0
- data/design_docs/goals.md +57 -0
- data/design_docs/object_regex.md +426 -0
- data/design_docs/type_annotations.md +80 -0
- data/ext/laser/BasicBlock.cpp +572 -0
- data/ext/laser/BasicBlock.h +118 -0
- data/ext/laser/extconf.rb +3 -0
- data/features/laser.feature +25 -0
- data/features/step_definitions/laser_steps.rb +39 -0
- data/features/support/env.rb +14 -0
- data/features/support/testdata/1_input +1 -0
- data/features/support/testdata/1_output +1 -0
- data/features/support/testdata/2_input +4 -0
- data/features/support/testdata/2_output +4 -0
- data/features/support/testdata/3_input +8 -0
- data/features/support/testdata/3_output +11 -0
- data/features/support/testdata/4_input +5 -0
- data/features/support/testdata/4_output +5 -0
- data/features/support/testdata/5_input +13 -0
- data/laser.gemspec +382 -0
- data/lib/laser.rb +98 -0
- data/lib/laser/analysis/annotations.rb +95 -0
- data/lib/laser/analysis/annotations/annotation_config.yaml +3 -0
- data/lib/laser/analysis/annotations/comment_attachment_annotation.rb +66 -0
- data/lib/laser/analysis/annotations/node_pointers_annotation.rb +36 -0
- data/lib/laser/analysis/annotations/runtime_annotation.rb +55 -0
- data/lib/laser/analysis/argument_expansion.rb +132 -0
- data/lib/laser/analysis/arity.rb +34 -0
- data/lib/laser/analysis/bindings.rb +144 -0
- data/lib/laser/analysis/bootstrap/bootstrap.rb +298 -0
- data/lib/laser/analysis/bootstrap/laser_class.rb +106 -0
- data/lib/laser/analysis/bootstrap/laser_method.rb +255 -0
- data/lib/laser/analysis/bootstrap/laser_module.rb +403 -0
- data/lib/laser/analysis/bootstrap/laser_module_copy.rb +74 -0
- data/lib/laser/analysis/bootstrap/laser_object.rb +69 -0
- data/lib/laser/analysis/bootstrap/laser_proc.rb +150 -0
- data/lib/laser/analysis/bootstrap/laser_singleton_class.rb +44 -0
- data/lib/laser/analysis/comments.rb +35 -0
- data/lib/laser/analysis/control_flow.rb +28 -0
- data/lib/laser/analysis/control_flow/alias_analysis.rb +31 -0
- data/lib/laser/analysis/control_flow/basic_block.rb +105 -0
- data/lib/laser/analysis/control_flow/cfg_builder.rb +2505 -0
- data/lib/laser/analysis/control_flow/cfg_instruction.rb +190 -0
- data/lib/laser/analysis/control_flow/constant_propagation.rb +742 -0
- data/lib/laser/analysis/control_flow/control_flow_graph.rb +370 -0
- data/lib/laser/analysis/control_flow/lifetime_analysis.rb +91 -0
- data/lib/laser/analysis/control_flow/method_call_search.rb +26 -0
- data/lib/laser/analysis/control_flow/raise_properties.rb +25 -0
- data/lib/laser/analysis/control_flow/simulation.rb +385 -0
- data/lib/laser/analysis/control_flow/static_single_assignment.rb +185 -0
- data/lib/laser/analysis/control_flow/unreachability_analysis.rb +57 -0
- data/lib/laser/analysis/control_flow/unused_variables.rb +91 -0
- data/lib/laser/analysis/control_flow/yield_properties.rb +103 -0
- data/lib/laser/analysis/errors.rb +131 -0
- data/lib/laser/analysis/laser_utils.rb +18 -0
- data/lib/laser/analysis/lexical_analysis.rb +172 -0
- data/lib/laser/analysis/method_call.rb +68 -0
- data/lib/laser/analysis/protocol_registry.rb +30 -0
- data/lib/laser/analysis/scope.rb +118 -0
- data/lib/laser/analysis/sexp.rb +159 -0
- data/lib/laser/analysis/sexp_analysis.rb +40 -0
- data/lib/laser/analysis/sexp_extensions/constant_extraction.rb +115 -0
- data/lib/laser/analysis/sexp_extensions/source_location.rb +164 -0
- data/lib/laser/analysis/sexp_extensions/type_inference.rb +47 -0
- data/lib/laser/analysis/signature.rb +76 -0
- data/lib/laser/analysis/special_methods/send.rb +67 -0
- data/lib/laser/analysis/unused_methods.rb +21 -0
- data/lib/laser/analysis/visitor.rb +141 -0
- data/lib/laser/annotation_parser/annotations.treetop +126 -0
- data/lib/laser/annotation_parser/annotations_parser.rb +748 -0
- data/lib/laser/annotation_parser/class_annotations.treetop +82 -0
- data/lib/laser/annotation_parser/class_annotations_parser.rb +654 -0
- data/lib/laser/annotation_parser/overload.treetop +24 -0
- data/lib/laser/annotation_parser/overload_parser.rb +167 -0
- data/lib/laser/annotation_parser/parsers.rb +6 -0
- data/lib/laser/annotation_parser/structural.treetop +37 -0
- data/lib/laser/annotation_parser/structural_parser.rb +406 -0
- data/lib/laser/annotation_parser/useful_parsers.treetop +47 -0
- data/lib/laser/annotation_parser/useful_parsers_parser.rb +674 -0
- data/lib/laser/rake/task.rb +46 -0
- data/lib/laser/runner.rb +189 -0
- data/lib/laser/scanner.rb +169 -0
- data/lib/laser/standard_library/_thread.rb +110 -0
- data/lib/laser/standard_library/abbrev.rb +103 -0
- data/lib/laser/standard_library/array.rb +418 -0
- data/lib/laser/standard_library/base64.rb +91 -0
- data/lib/laser/standard_library/basic_object.rb +55 -0
- data/lib/laser/standard_library/benchmark.rb +556 -0
- data/lib/laser/standard_library/bignum.rb +185 -0
- data/lib/laser/standard_library/cgi.rb +275 -0
- data/lib/laser/standard_library/cgi/cookie.rb +147 -0
- data/lib/laser/standard_library/cgi/core.rb +791 -0
- data/lib/laser/standard_library/cgi/html.rb +1021 -0
- data/lib/laser/standard_library/cgi/session.rb +537 -0
- data/lib/laser/standard_library/cgi/session/pstore.rb +111 -0
- data/lib/laser/standard_library/cgi/util.rb +188 -0
- data/lib/laser/standard_library/class_definitions.rb +333 -0
- data/lib/laser/standard_library/comparable.rb +125 -0
- data/lib/laser/standard_library/complex.rb +162 -0
- data/lib/laser/standard_library/enumerable.rb +178 -0
- data/lib/laser/standard_library/exceptions.rb +135 -0
- data/lib/laser/standard_library/fixnum.rb +188 -0
- data/lib/laser/standard_library/float.rb +180 -0
- data/lib/laser/standard_library/hash.rb +237 -0
- data/lib/laser/standard_library/integer.rb +123 -0
- data/lib/laser/standard_library/laser_magic.rb +7 -0
- data/lib/laser/standard_library/nil_false_true.rb +113 -0
- data/lib/laser/standard_library/numbers.rb +192 -0
- data/lib/laser/standard_library/proc.rb +31 -0
- data/lib/laser/standard_library/set.rb +1348 -0
- data/lib/laser/standard_library/string.rb +666 -0
- data/lib/laser/standard_library/stringio.rb +2 -0
- data/lib/laser/standard_library/symbol.rb +125 -0
- data/lib/laser/standard_library/tsort.rb +242 -0
- data/lib/laser/support/acts_as_struct.rb +66 -0
- data/lib/laser/support/frequency.rb +55 -0
- data/lib/laser/support/inheritable_attributes.rb +145 -0
- data/lib/laser/support/module_extensions.rb +94 -0
- data/lib/laser/support/placeholder_object.rb +13 -0
- data/lib/laser/third_party/rgl/adjacency.rb +221 -0
- data/lib/laser/third_party/rgl/base.rb +228 -0
- data/lib/laser/third_party/rgl/bidirectional.rb +39 -0
- data/lib/laser/third_party/rgl/condensation.rb +47 -0
- data/lib/laser/third_party/rgl/connected_components.rb +138 -0
- data/lib/laser/third_party/rgl/control_flow.rb +170 -0
- data/lib/laser/third_party/rgl/depth_first_spanning_tree.rb +37 -0
- data/lib/laser/third_party/rgl/dominators.rb +124 -0
- data/lib/laser/third_party/rgl/dot.rb +93 -0
- data/lib/laser/third_party/rgl/graphxml.rb +51 -0
- data/lib/laser/third_party/rgl/implicit.rb +174 -0
- data/lib/laser/third_party/rgl/mutable.rb +117 -0
- data/lib/laser/third_party/rgl/rdot.rb +445 -0
- data/lib/laser/third_party/rgl/topsort.rb +72 -0
- data/lib/laser/third_party/rgl/transitivity.rb +180 -0
- data/lib/laser/third_party/rgl/traversal.rb +348 -0
- data/lib/laser/types/types.rb +433 -0
- data/lib/laser/version.rb +14 -0
- data/lib/laser/warning.rb +149 -0
- data/lib/laser/warning_sets/default.yml +13 -0
- data/lib/laser/warnings/assignment_in_condition.rb +20 -0
- data/lib/laser/warnings/comment_spacing.rb +31 -0
- data/lib/laser/warnings/extra_blank_lines.rb +30 -0
- data/lib/laser/warnings/extra_whitespace.rb +16 -0
- data/lib/laser/warnings/hash_symbol_18_warning.rb +63 -0
- data/lib/laser/warnings/hash_symbol_19_warning.rb +29 -0
- data/lib/laser/warnings/line_length.rb +115 -0
- data/lib/laser/warnings/misaligned_unindentation.rb +17 -0
- data/lib/laser/warnings/operator_spacing.rb +68 -0
- data/lib/laser/warnings/parens_on_declaration.rb +30 -0
- data/lib/laser/warnings/rescue_exception.rb +42 -0
- data/lib/laser/warnings/semicolon.rb +25 -0
- data/lib/laser/warnings/sexp_errors.rb +24 -0
- data/lib/laser/warnings/uncalled_method_warning.rb +7 -0
- data/lib/laser/warnings/useless_double_quotes.rb +38 -0
- data/spec/analysis_specs/annotations_spec.rb +47 -0
- data/spec/analysis_specs/annotations_specs/comment_attachment_spec.rb +68 -0
- data/spec/analysis_specs/annotations_specs/node_pointers_annotation_spec.rb +90 -0
- data/spec/analysis_specs/annotations_specs/runtime_annotation_spec.rb +135 -0
- data/spec/analysis_specs/annotations_specs/spec_helper.rb +33 -0
- data/spec/analysis_specs/argument_expansion_spec.rb +113 -0
- data/spec/analysis_specs/bindings_spec.rb +36 -0
- data/spec/analysis_specs/comment_spec.rb +93 -0
- data/spec/analysis_specs/control_flow_specs/cfg_instruction_spec.rb +111 -0
- data/spec/analysis_specs/control_flow_specs/constant_propagation_spec.rb +560 -0
- data/spec/analysis_specs/control_flow_specs/control_flow_graph_spec.rb +5 -0
- data/spec/analysis_specs/control_flow_specs/raise_properties_spec.rb +310 -0
- data/spec/analysis_specs/control_flow_specs/raise_type_inference_spec.rb +301 -0
- data/spec/analysis_specs/control_flow_specs/return_type_inference_spec.rb +431 -0
- data/spec/analysis_specs/control_flow_specs/simulation_spec.rb +158 -0
- data/spec/analysis_specs/control_flow_specs/spec_helper.rb +110 -0
- data/spec/analysis_specs/control_flow_specs/tuple_misuse_inference_spec.rb +125 -0
- data/spec/analysis_specs/control_flow_specs/unreachability_analysis_spec.rb +76 -0
- data/spec/analysis_specs/control_flow_specs/unused_variable_spec.rb +99 -0
- data/spec/analysis_specs/control_flow_specs/yield_properties_spec.rb +372 -0
- data/spec/analysis_specs/error_spec.rb +30 -0
- data/spec/analysis_specs/laser_class_spec.rb +322 -0
- data/spec/analysis_specs/lexical_analysis_spec.rb +184 -0
- data/spec/analysis_specs/protocol_registry_spec.rb +63 -0
- data/spec/analysis_specs/scope_annotation_spec.rb +1013 -0
- data/spec/analysis_specs/scope_spec.rb +126 -0
- data/spec/analysis_specs/sexp_analysis_spec.rb +30 -0
- data/spec/analysis_specs/sexp_extension_specs/constant_extraction_spec.rb +309 -0
- data/spec/analysis_specs/sexp_extension_specs/source_location_spec.rb +231 -0
- data/spec/analysis_specs/sexp_extension_specs/spec_helper.rb +1 -0
- data/spec/analysis_specs/sexp_extension_specs/type_inference_spec.rb +252 -0
- data/spec/analysis_specs/sexp_spec.rb +167 -0
- data/spec/analysis_specs/spec_helper.rb +27 -0
- data/spec/analysis_specs/unused_methods_spec.rb +65 -0
- data/spec/analysis_specs/visitor_spec.rb +64 -0
- data/spec/annotation_parser_specs/annotations_parser_spec.rb +89 -0
- data/spec/annotation_parser_specs/class_annotation_parser_spec.rb +120 -0
- data/spec/annotation_parser_specs/overload_parser_spec.rb +39 -0
- data/spec/annotation_parser_specs/parsers_spec.rb +14 -0
- data/spec/annotation_parser_specs/spec_helper.rb +1 -0
- data/spec/annotation_parser_specs/structural_parser_spec.rb +67 -0
- data/spec/laser_spec.rb +14 -0
- data/spec/rake_specs/spec_helper.rb +1 -0
- data/spec/rake_specs/task_spec.rb +67 -0
- data/spec/runner_spec.rb +207 -0
- data/spec/scanner_spec.rb +75 -0
- data/spec/spec_helper.rb +121 -0
- data/spec/standard_library/exceptions_spec.rb +19 -0
- data/spec/standard_library/globals_spec.rb +14 -0
- data/spec/standard_library/set_spec.rb +31 -0
- data/spec/standard_library/spec_helper.rb +1 -0
- data/spec/standard_library/standard_library_spec.rb +302 -0
- data/spec/support_specs/acts_as_struct_spec.rb +94 -0
- data/spec/support_specs/frequency_spec.rb +23 -0
- data/spec/support_specs/module_extensions_spec.rb +117 -0
- data/spec/support_specs/spec_helper.rb +1 -0
- data/spec/type_specs/spec_helper.rb +1 -0
- data/spec/type_specs/types_spec.rb +133 -0
- data/spec/warning_spec.rb +95 -0
- data/spec/warning_specs/assignment_in_condition_spec.rb +68 -0
- data/spec/warning_specs/comment_spacing_spec.rb +65 -0
- data/spec/warning_specs/extra_blank_lines_spec.rb +70 -0
- data/spec/warning_specs/extra_whitespace_spec.rb +33 -0
- data/spec/warning_specs/hash_symbol_18_warning_spec.rb +89 -0
- data/spec/warning_specs/hash_symbol_19_warning_spec.rb +63 -0
- data/spec/warning_specs/line_length_spec.rb +173 -0
- data/spec/warning_specs/misaligned_unindentation_spec.rb +35 -0
- data/spec/warning_specs/operator_spacing_spec.rb +104 -0
- data/spec/warning_specs/parens_on_declaration_spec.rb +57 -0
- data/spec/warning_specs/rescue_exception_spec.rb +105 -0
- data/spec/warning_specs/semicolon_spec.rb +58 -0
- data/spec/warning_specs/spec_helper.rb +1 -0
- data/spec/warning_specs/useless_double_quotes_spec.rb +74 -0
- data/status_reports/2010/12/2010-12-14.md +163 -0
- data/status_reports/2010/12/2010-12-23.md +298 -0
- data/status_reports/2010/12/2010-12-24.md +6 -0
- data/test/third_party_tests/rgl_tests/TestComponents.rb +65 -0
- data/test/third_party_tests/rgl_tests/TestCycles.rb +61 -0
- data/test/third_party_tests/rgl_tests/TestDirectedGraph.rb +125 -0
- data/test/third_party_tests/rgl_tests/TestDot.rb +18 -0
- data/test/third_party_tests/rgl_tests/TestEdge.rb +34 -0
- data/test/third_party_tests/rgl_tests/TestGraph.rb +71 -0
- data/test/third_party_tests/rgl_tests/TestGraphXML.rb +57 -0
- data/test/third_party_tests/rgl_tests/TestImplicit.rb +52 -0
- data/test/third_party_tests/rgl_tests/TestRdot.rb +863 -0
- data/test/third_party_tests/rgl_tests/TestTransitivity.rb +129 -0
- data/test/third_party_tests/rgl_tests/TestTraversal.rb +220 -0
- data/test/third_party_tests/rgl_tests/TestUnDirectedGraph.rb +102 -0
- data/test/third_party_tests/rgl_tests/examples/north/Graph.log +128 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.0.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.1.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.11.graphml +31 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.12.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.13.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.14.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.15.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.16.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.17.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.19.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.2.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.20.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.22.graphml +43 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.24.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.25.graphml +45 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.27.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.28.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.29.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.3.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.30.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.31.graphml +42 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.34.graphml +42 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.37.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.38.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.39.graphml +36 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.4.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.40.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.41.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.42.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.45.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.46.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.5.graphml +31 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.50.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.56.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.57.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.58.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.6.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.60.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.61.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.62.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.68.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.69.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.7.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.70.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.71.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.72.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.74.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.75.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.78.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.79.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.8.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.80.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.82.graphml +35 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.83.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.85.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.86.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.88.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.89.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.9.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.90.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.91.graphml +31 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.92.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.93.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.94.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.12.8.graphml +40 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.14.9.graphml +36 -0
- data/test/third_party_tests/rgl_tests/test_helper.rb +7 -0
- data/test/third_party_tests/test_inheritable_attributes.rb +187 -0
- 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
|