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,106 @@
|
|
|
1
|
+
module Laser
|
|
2
|
+
module Analysis
|
|
3
|
+
# Laser representation of a class. I named it LaserClass so it wouldn't
|
|
4
|
+
# clash with regular Class. This links the class to its protocol.
|
|
5
|
+
# It inherits from LaserModule to pull in everything but superclasses.
|
|
6
|
+
class LaserClass < LaserModule
|
|
7
|
+
attr_reader :subclasses
|
|
8
|
+
|
|
9
|
+
def initialize(klass = ClassRegistry['Class'], scope = Scope::GlobalScope,
|
|
10
|
+
full_path=(@name_set = :no; "#{klass.path}:Anonymous:#{object_id.to_s(16)}"))
|
|
11
|
+
@subclasses ||= []
|
|
12
|
+
# bootstrapping exception
|
|
13
|
+
unless ['Class', 'Module', 'Object', 'BasicObject'].include?(full_path)
|
|
14
|
+
@superclass = ClassRegistry['Object']
|
|
15
|
+
end
|
|
16
|
+
super # can yield, so must come last
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def normal_class
|
|
20
|
+
return ClassRegistry['Class']
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def singleton_class
|
|
24
|
+
return @singleton_class if @singleton_class
|
|
25
|
+
new_scope = ClosedScope.new(self.scope, nil)
|
|
26
|
+
@singleton_class = LaserSingletonClass.new(
|
|
27
|
+
ClassRegistry['Class'], new_scope, "Class:#{name}", self) do |new_singleton_class|
|
|
28
|
+
if superclass
|
|
29
|
+
new_singleton_class.superclass = superclass.singleton_class
|
|
30
|
+
else
|
|
31
|
+
new_singleton_class.superclass = ClassRegistry['Class']
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
@klass = @singleton_class
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Adds a subclass.
|
|
38
|
+
def add_subclass!(other)
|
|
39
|
+
subclasses << other
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Removes a subclass.
|
|
43
|
+
def remove_subclass!(other)
|
|
44
|
+
subclasses.delete other
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def parent
|
|
48
|
+
@superclass
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def superclass
|
|
52
|
+
current = @superclass
|
|
53
|
+
while current
|
|
54
|
+
if LaserModuleCopy === current
|
|
55
|
+
current = current.superclass
|
|
56
|
+
else
|
|
57
|
+
return current
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Sets the superclass, which handles registering/unregistering subclass
|
|
63
|
+
# ownership elsewhere in the inheritance tree
|
|
64
|
+
def superclass=(other)
|
|
65
|
+
if LaserModuleCopy === other # || LaserSingletonClass === self
|
|
66
|
+
@superclass = other
|
|
67
|
+
else
|
|
68
|
+
superclass.remove_subclass! self if superclass
|
|
69
|
+
@superclass = other
|
|
70
|
+
superclass.add_subclass! self
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# The set of all superclasses (including the class itself). Excludes modules.
|
|
75
|
+
def superset
|
|
76
|
+
if superclass.nil?
|
|
77
|
+
then [self]
|
|
78
|
+
else [self] + superclass.superset
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# The set of all superclasses (excluding the class itself)
|
|
83
|
+
def proper_superset
|
|
84
|
+
superset - [self]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# The set of all subclasses (including the class itself)
|
|
88
|
+
def subset
|
|
89
|
+
[self] + subclasses.map(&:subset).flatten
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# The set of all subclasses (excluding the class itself)
|
|
93
|
+
def proper_subset
|
|
94
|
+
subset - [self]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def class_name
|
|
98
|
+
'Class'
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def inspect
|
|
102
|
+
"#<LaserClass: #{path} superclass=#{superclass.inspect}>"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
module Laser
|
|
2
|
+
module Analysis
|
|
3
|
+
# Laser representation of a method. This name is tweaked so it doesn't
|
|
4
|
+
# collide with ::Method.
|
|
5
|
+
class LaserMethod
|
|
6
|
+
extend ModuleExtensions
|
|
7
|
+
cattr_accessor_with_default :default_dispatched, true
|
|
8
|
+
attr_reader :name, :proc, :arglist
|
|
9
|
+
alias arguments arglist
|
|
10
|
+
attr_accessor :owner, :arity
|
|
11
|
+
|
|
12
|
+
def initialize(name, base_proc)
|
|
13
|
+
@name = name
|
|
14
|
+
@type_instantiations = {}
|
|
15
|
+
@proc = base_proc
|
|
16
|
+
@argument_annotations = nil
|
|
17
|
+
@dispatched = LaserMethod.default_dispatched
|
|
18
|
+
if base_proc # always true except some ugly test cases
|
|
19
|
+
@arglist = base_proc.arguments
|
|
20
|
+
@arity = Arity.for_arglist(@arglist)
|
|
21
|
+
else
|
|
22
|
+
@arglist = []
|
|
23
|
+
@arity = nil
|
|
24
|
+
end
|
|
25
|
+
yield self if block_given?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
################## Potentially Annotated Properties ######################
|
|
29
|
+
|
|
30
|
+
%w(special pure builtin predictable mutation annotated_return annotated_yield_usage
|
|
31
|
+
overloads annotated_raise_frequency raises).each do |attr|
|
|
32
|
+
define_method(attr) do
|
|
33
|
+
instance_variable_get("@#{attr}") || (self.proc ? self.proc.send(attr) : nil)
|
|
34
|
+
end
|
|
35
|
+
define_method("#{attr}=") do |val|
|
|
36
|
+
instance_variable_set("@#{attr}", val)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def overloads
|
|
41
|
+
@overloads || (self.proc ? self.proc.overloads : {})
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def predictable
|
|
45
|
+
@predictable || (self.proc ? self.proc.predictable : true)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Gets all annotations with the same name as an argument.
|
|
49
|
+
def argument_annotations
|
|
50
|
+
@argument_annotations ||=
|
|
51
|
+
if @proc
|
|
52
|
+
arguments.map do |arg|
|
|
53
|
+
@proc.annotations[arg.name] if @proc.annotations.has_key?(arg.name)
|
|
54
|
+
end.compact
|
|
55
|
+
else
|
|
56
|
+
[]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def yield_type
|
|
61
|
+
return annotated_yield_usage if annotated_yield_usage
|
|
62
|
+
return @yield_type if @yield_type
|
|
63
|
+
if builtin
|
|
64
|
+
:ignored
|
|
65
|
+
else
|
|
66
|
+
master_cfg.analyze(method: self)
|
|
67
|
+
@yield_type = master_cfg.yield_type
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def yield_arity
|
|
72
|
+
return @yield_arity if @yield_arity
|
|
73
|
+
master_cfg.analyze(method: self)
|
|
74
|
+
@yield_arity = master_cfg.yield_arity
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def raise_frequency_for_types(self_type, arg_types = [], block_type = nil)
|
|
78
|
+
block_type ||= Types::NILCLASS
|
|
79
|
+
unless arg_types_unify_with_annotations?(arg_types)
|
|
80
|
+
return Frequency::ALWAYS
|
|
81
|
+
end
|
|
82
|
+
return annotated_raise_frequency if annotated_raise_frequency
|
|
83
|
+
return Frequency::MAYBE if builtin || special
|
|
84
|
+
cfg_for_types(self_type, arg_types, block_type).raise_frequency
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def raise_type_for_types(self_type, arg_types = [], block_type = nil)
|
|
88
|
+
block_type ||= Types::NILCLASS
|
|
89
|
+
Laser.debug_puts("Calculating raise type for #{owner.name}##{name} with types "+
|
|
90
|
+
"#{self_type.inspect} #{arg_types.inspect} #{block_type.inspect}")
|
|
91
|
+
unless arg_types_unify_with_annotations?(arg_types)
|
|
92
|
+
return ClassRegistry['TypeError'].as_type # needs parameterization later
|
|
93
|
+
end
|
|
94
|
+
if raises
|
|
95
|
+
Laser.debug_puts("Raise type is annotated: #{self.raises.inspect}")
|
|
96
|
+
return self.raises
|
|
97
|
+
end
|
|
98
|
+
if builtin || special
|
|
99
|
+
if annotated_raise_frequency == Frequency::NEVER
|
|
100
|
+
self.raises = Types::EMPTY
|
|
101
|
+
Laser.debug_puts("Raise type is annotated: #{self.raises.inspect}")
|
|
102
|
+
return self.raises
|
|
103
|
+
end
|
|
104
|
+
Laser.debug_puts("Builtin/special: Types::TOP")
|
|
105
|
+
return Types::TOP
|
|
106
|
+
end
|
|
107
|
+
cfg_for_types(self_type, arg_types, block_type).raise_type
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def return_type_for_types(self_type, arg_types = [], block_type = nil)
|
|
111
|
+
block_type ||= Types::NILCLASS
|
|
112
|
+
return annotated_return if annotated_return
|
|
113
|
+
unless overloads.empty?
|
|
114
|
+
return overload_for_arg_types(arg_types)
|
|
115
|
+
end
|
|
116
|
+
if builtin || special
|
|
117
|
+
return Types::TOP
|
|
118
|
+
end
|
|
119
|
+
result = cfg_for_types(self_type, arg_types, block_type).return_type
|
|
120
|
+
check_return_type_against_expectations(result)
|
|
121
|
+
result
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def valid_arity?(num_args)
|
|
125
|
+
@arity ? @arity.include?(num_args) : true
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def overload_for_arg_types(arg_types)
|
|
129
|
+
overloads.each do |overload_args, proc_type|
|
|
130
|
+
# compatible arg count
|
|
131
|
+
if overload_args.size == arg_types.size
|
|
132
|
+
# all types unify?
|
|
133
|
+
if overload_args.zip(arg_types).all? { |spec, concrete| Types.subtype?(concrete, spec) }
|
|
134
|
+
return proc_type.subtypes[1]
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
raise TypeError.new("No overload found for #{self.inspect} with arg types #{arg_types.inspect}")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Checks if the given argument types correctly unify with any
|
|
142
|
+
# user-requested restrictions.
|
|
143
|
+
def arg_types_unify_with_annotations?(arg_types)
|
|
144
|
+
if argument_annotations.any?
|
|
145
|
+
# Match actual arguments against formal arguments
|
|
146
|
+
formal_assignments = assign_formals(arg_types)
|
|
147
|
+
# Check annotations for formals against actual types
|
|
148
|
+
argument_annotations.each do |note_list|
|
|
149
|
+
note_list.each do |type_annotation|
|
|
150
|
+
expected = type_annotation.type
|
|
151
|
+
given = formal_assignments[type_annotation.name]
|
|
152
|
+
# no given -> optional arg that's left out.
|
|
153
|
+
return false if given && !Types.subtype?(given, expected)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
true
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def check_return_type_against_expectations(return_type)
|
|
161
|
+
if (expectation = Types::EXPECTATIONS[self.name]) &&
|
|
162
|
+
!Types.subtype?(return_type, expectation)
|
|
163
|
+
@proc.ast_node.add_error(ImproperOverloadTypeError.new(
|
|
164
|
+
"All methods named #{self.name} should return a subtype of #{expectation.inspect}",
|
|
165
|
+
@proc.ast_node))
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def dispatched?
|
|
170
|
+
@dispatched
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def been_used!
|
|
174
|
+
@dispatched = true
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def master_cfg
|
|
178
|
+
@master_cfg ||= @proc.ssa_cfg.tap do |cfg|
|
|
179
|
+
cfg.bind_self_type(Types::ClassType.new(owner.path, :covariant))
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def cfg_for_types(self_type, arg_types = [], block_type = nil)
|
|
184
|
+
block_type ||= Types::NILCLASS
|
|
185
|
+
Laser.debug_puts("Calculating CFG(#{owner.name}##{name}, #{self_type.inspect}, #{arg_types.inspect}, #{block_type.inspect})")
|
|
186
|
+
@type_instantiations[[self_type, *arg_types, block_type]] ||= master_cfg.dup.tap do |cfg|
|
|
187
|
+
cfg.bind_self_type(self_type)
|
|
188
|
+
cfg.bind_formal_types(arg_types)
|
|
189
|
+
cfg.bind_block_type(block_type)
|
|
190
|
+
cfg.analyze(method: self)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def simulate_with_args(new_self, args, block, opts)
|
|
195
|
+
self_type = Utilities.type_for(new_self)
|
|
196
|
+
formal_types = args.map { |arg| Utilities.type_for(arg) }
|
|
197
|
+
block_type = Utilities.type_for(block)
|
|
198
|
+
cfg_for_types(self_type, formal_types, block_type).dup.simulate(
|
|
199
|
+
args, opts.merge(self: new_self,
|
|
200
|
+
method: self,
|
|
201
|
+
block: block,
|
|
202
|
+
start_block: @proc.start_block))
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Maps a sequence of objects (one per actual argument) to
|
|
206
|
+
# the corresponding formal argument.
|
|
207
|
+
def assign_formals(actual_objs)
|
|
208
|
+
args = arguments
|
|
209
|
+
result_array = []
|
|
210
|
+
num_required = args.count { |arg| arg.kind == :positional }
|
|
211
|
+
num_optional = actual_objs.size - num_required
|
|
212
|
+
current_arg = 0
|
|
213
|
+
current_actual = 0
|
|
214
|
+
rest = []
|
|
215
|
+
while num_required > 0 || num_optional > 0
|
|
216
|
+
next_arg = args[current_arg]
|
|
217
|
+
if next_arg.kind == :positional
|
|
218
|
+
result_array << [next_arg.name, actual_objs[current_actual]]
|
|
219
|
+
num_required -= 1
|
|
220
|
+
current_actual += 1
|
|
221
|
+
current_arg += 1
|
|
222
|
+
elsif next_arg.kind == :optional && num_optional > 0
|
|
223
|
+
result_array << [next_arg.name, actual_objs[current_actual]]
|
|
224
|
+
num_optional -= 1
|
|
225
|
+
current_actual += 1
|
|
226
|
+
current_arg += 1
|
|
227
|
+
elsif next_arg.kind == :optional && num_optional == 0
|
|
228
|
+
current_arg += 1
|
|
229
|
+
elsif next_arg.kind == :rest && num_optional > 0
|
|
230
|
+
rest << actual_objs[current_actual]
|
|
231
|
+
current_actual += 1
|
|
232
|
+
num_optional -= 1
|
|
233
|
+
elsif next_arg.kind == :rest
|
|
234
|
+
result_array << [next_arg.name, rest]
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
Hash[*result_array.flatten(1)]
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def dup
|
|
241
|
+
result = LaserMethod.new(name, proc)
|
|
242
|
+
result.owner = self.owner
|
|
243
|
+
result.arity = self.arity
|
|
244
|
+
result
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def refine_arity(new_arity)
|
|
248
|
+
return new_arity if @arity.nil?
|
|
249
|
+
new_begin = [new_arity.begin, @arity.begin].min
|
|
250
|
+
new_end = [new_arity.end, @arity.end].max
|
|
251
|
+
new_begin..new_end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
module Laser
|
|
2
|
+
module Analysis
|
|
3
|
+
# Laser representation of a module. Named LaserModule to avoid naming
|
|
4
|
+
# conflicts. It has lists of methods, instance variables, and so on.
|
|
5
|
+
class LaserModule < LaserObject
|
|
6
|
+
attr_reader :binding, :superclass
|
|
7
|
+
attr_accessor :path
|
|
8
|
+
cattr_accessor_with_default :all_modules, []
|
|
9
|
+
|
|
10
|
+
def initialize(klass = ClassRegistry['Module'], scope = Scope::GlobalScope,
|
|
11
|
+
full_path=(@name_set = :no; "#{klass.path}:Anonymous:#{object_id.to_s(16)}"))
|
|
12
|
+
super(klass, scope, full_path.split('::').last)
|
|
13
|
+
full_path = submodule_path(full_path) if scope && scope.parent
|
|
14
|
+
validate_module_path!(full_path) unless LaserSingletonClass === self
|
|
15
|
+
|
|
16
|
+
@name_set = :yes unless @name_set == :no
|
|
17
|
+
@path = full_path
|
|
18
|
+
@instance_methods = {}
|
|
19
|
+
@visibility_table = {}
|
|
20
|
+
@constant_table = {}
|
|
21
|
+
@scope = scope
|
|
22
|
+
@ivar_types = {}
|
|
23
|
+
@superclass ||= nil
|
|
24
|
+
initialize_protocol
|
|
25
|
+
@binding = Bindings::ConstantBinding.new(name, self)
|
|
26
|
+
initialize_scope
|
|
27
|
+
yield self if block_given?
|
|
28
|
+
LaserModule.all_modules << self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def <=>(other)
|
|
32
|
+
if self == other
|
|
33
|
+
return 0
|
|
34
|
+
elsif ancestors.include?(other)
|
|
35
|
+
return -1
|
|
36
|
+
elsif other.ancestors.include?(self)
|
|
37
|
+
return 1
|
|
38
|
+
else
|
|
39
|
+
return nil
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# including Comparable is having issues due to override of include. Do it
|
|
44
|
+
# ourselves.
|
|
45
|
+
%w(< <= >= >).each do |op|
|
|
46
|
+
class_eval %Q{
|
|
47
|
+
def #{op}(other)
|
|
48
|
+
cmp = self <=> other
|
|
49
|
+
cmp && cmp #{op} 0
|
|
50
|
+
end
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def as_type
|
|
55
|
+
Types::ClassObjectType.new(self)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def name_set?
|
|
59
|
+
@name_set == :yes
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def set_name(new_path)
|
|
63
|
+
@path = new_path
|
|
64
|
+
ProtocolRegistry.add_class(self)
|
|
65
|
+
@name_set = :yes
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Returns the canonical path for a (soon-to-be-created) submodule of the given
|
|
69
|
+
# scope. This is computed before creating the module.
|
|
70
|
+
def submodule_path(new_mod_name)
|
|
71
|
+
scope = self.scope.parent
|
|
72
|
+
new_mod_full_path = scope.parent.nil? ? '' : scope.path
|
|
73
|
+
new_mod_full_path += '::' unless new_mod_full_path.empty?
|
|
74
|
+
new_mod_full_path += new_mod_name
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def validate_module_path!(path)
|
|
78
|
+
path.split('::').each do |component|
|
|
79
|
+
if !component.empty? && component[0,1] !~ /[A-Z]/
|
|
80
|
+
raise ArgumentError.new("Path component #{component} in #{path}" +
|
|
81
|
+
' does not start with a capital letter, A-Z.')
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def class_name
|
|
87
|
+
'Module'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# If this is a new, custom module, we can update the constant
|
|
91
|
+
# table and perform module initialization.
|
|
92
|
+
def initialize_scope
|
|
93
|
+
if @scope && !(@scope.parent.nil?)
|
|
94
|
+
@scope.parent.constants[name] = self.binding if @scope.parent
|
|
95
|
+
@scope.locals['self'] = Bindings::LocalVariableBinding.new('self', self)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Initializes the protocol for this LaserClass.
|
|
100
|
+
def initialize_protocol
|
|
101
|
+
if ProtocolRegistry[path].any? && !TESTS_ACTIVATED
|
|
102
|
+
$stderr.puts "Warning: creating new instance of #{class_name} #{path}"
|
|
103
|
+
else
|
|
104
|
+
ProtocolRegistry.add_class(self)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def name
|
|
109
|
+
self.path.split('::').last
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def add_instance_method!(method)
|
|
113
|
+
@instance_methods[method.name.to_sym] = method
|
|
114
|
+
@visibility_table[method.name.to_sym] = :public
|
|
115
|
+
method.owner = self
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def instance_method(name)
|
|
119
|
+
lookup = name.to_sym
|
|
120
|
+
if @instance_methods.has_key?(lookup)
|
|
121
|
+
then @instance_methods[lookup]
|
|
122
|
+
else @superclass && @superclass.instance_method(lookup)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def method_defined?(name)
|
|
127
|
+
instance_method(name) && visibility_for(name) != :private
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def public_instance_method(name)
|
|
131
|
+
result = instance_method(name)
|
|
132
|
+
visibility_for(name) == :public ? result : nil
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def __all_instance_methods(include_super = true)
|
|
136
|
+
mine = @instance_methods.keys
|
|
137
|
+
if include_super && @superclass
|
|
138
|
+
then @superclass.instance_methods | mine
|
|
139
|
+
else mine
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def __instance_methods_with_privacy(include_super, *allowed)
|
|
144
|
+
methods = __all_instance_methods(include_super)
|
|
145
|
+
table = visibility_table
|
|
146
|
+
methods.select { |name| allowed.include?(table[name.to_sym]) }
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def instance_methods(include_super = true)
|
|
150
|
+
__instance_methods_with_privacy(include_super, :public, :protected)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def public_instance_methods(include_super = true)
|
|
154
|
+
__instance_methods_with_privacy(include_super, :public)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def protected_instance_methods(include_super = true)
|
|
158
|
+
__instance_methods_with_privacy(include_super, :protected)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def protected_method_defined?(name)
|
|
162
|
+
!!__instance_methods_with_privacy(include_super, :protected)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def private_instance_methods(include_super = true)
|
|
166
|
+
__instance_methods_with_privacy(include_super, :private)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def ivar_type(name)
|
|
170
|
+
@ivar_types[name] || (@superclass && @superclass.ivar_type(name)) || Types::NILCLASS
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def set_ivar_type(name, type)
|
|
174
|
+
@ivar_types[name] = type
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def instance_variable(name)
|
|
178
|
+
@instance_variables[name] || (@superclass && @superclass.instance_variable(name))
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def instance_variables
|
|
182
|
+
if @superclass.nil?
|
|
183
|
+
then @instance_variables
|
|
184
|
+
else @instance_variables.merge(@superclass.instance_variables)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def add_instance_variable!(binding)
|
|
189
|
+
@instance_variables[binding.name] = binding
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def visibility_for(method)
|
|
193
|
+
lookup = method.to_sym
|
|
194
|
+
return @visibility_table[lookup] ||
|
|
195
|
+
(@superclass && @superclass.visibility_for(lookup))
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def visibility_table
|
|
199
|
+
if @superclass
|
|
200
|
+
then @superclass.visibility_table.merge(@visibility_table)
|
|
201
|
+
else @visibility_table
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def set_visibility!(method, visibility)
|
|
206
|
+
@visibility_table[method] = visibility
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def superclass=(new_superclass)
|
|
210
|
+
@superclass = new_superclass
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# The set of all superclasses (including the class itself)
|
|
214
|
+
def ancestors
|
|
215
|
+
if @superclass.nil?
|
|
216
|
+
then [self]
|
|
217
|
+
else [self] + @superclass.ancestors
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def subset
|
|
222
|
+
[self]
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def classes_including
|
|
226
|
+
@classes_including ||= []
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def included_modules
|
|
230
|
+
ancestors.select { |mod| LaserModuleCopy === mod }
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Directly translated from MRI's C implementation in class.c:650
|
|
234
|
+
def include_module(mod)
|
|
235
|
+
if mod.klass == ClassRegistry['Class']
|
|
236
|
+
raise ArgumentError.new("Tried to include #{mod.name}, which should "+
|
|
237
|
+
" be a Module or Module subclass, not a " +
|
|
238
|
+
"#{mod.klass.name}.")
|
|
239
|
+
end
|
|
240
|
+
original_mod = mod
|
|
241
|
+
any_changes = false
|
|
242
|
+
current = self
|
|
243
|
+
while mod
|
|
244
|
+
superclass_seen = false
|
|
245
|
+
should_change = true
|
|
246
|
+
if mod == self
|
|
247
|
+
raise ArgumentError.new("Cyclic module inclusion: #{mod} mixed into #{self}")
|
|
248
|
+
end
|
|
249
|
+
ancestors.each do |parent|
|
|
250
|
+
case parent
|
|
251
|
+
when LaserModuleCopy
|
|
252
|
+
if parent == mod
|
|
253
|
+
current = parent unless superclass_seen
|
|
254
|
+
should_change = false
|
|
255
|
+
break
|
|
256
|
+
end
|
|
257
|
+
when LaserClass
|
|
258
|
+
superclass_seen = true
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
if should_change
|
|
262
|
+
new_super = (current.superclass = LaserModuleCopy.new(mod, current.ancestors[1]))
|
|
263
|
+
mod.classes_including << current
|
|
264
|
+
current = new_super
|
|
265
|
+
any_changes = true
|
|
266
|
+
end
|
|
267
|
+
mod = mod.superclass
|
|
268
|
+
end
|
|
269
|
+
unless any_changes
|
|
270
|
+
raise DoubleIncludeError.new("Included #{original_mod.path} into #{self.path}"+
|
|
271
|
+
" but it was already included.", nil)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def inspect
|
|
276
|
+
"#<LaserModule: #{path}>"
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# simulation methods
|
|
280
|
+
def ===(other)
|
|
281
|
+
klass = (LaserObject === other ? other.klass : ClassRegistry[other.class.name])
|
|
282
|
+
klass.ancestors.include?(self)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def const_set(string, value)
|
|
286
|
+
@constant_table[string] = value
|
|
287
|
+
if LaserModule === value && !value.name_set?
|
|
288
|
+
if self == ClassRegistry['Object']
|
|
289
|
+
value.set_name(string)
|
|
290
|
+
else
|
|
291
|
+
value.set_name("#{@path}::#{string}")
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def const_get(constant, inherit=true)
|
|
297
|
+
if inherit && superclass
|
|
298
|
+
@constant_table[constant] || superclass.const_get(constant, true)
|
|
299
|
+
elsif LaserClass === self
|
|
300
|
+
@constant_table[constant] or raise ArgumentError.new("Class #{@path} has no constant #{constant}")
|
|
301
|
+
else
|
|
302
|
+
(@constant_table[constant] || ClassRegistry['Object'].const_get(constant, false)) or
|
|
303
|
+
raise ArgumentError.new("Class #{@path} has no constant #{constant}")
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Fuck you, that's why
|
|
308
|
+
def const_defined?(constant, inherit=true)
|
|
309
|
+
!!const_get(constant, inherit)
|
|
310
|
+
rescue
|
|
311
|
+
false
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def remove_const(sym)
|
|
315
|
+
@constant_table.delete(sym)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def define_method(name, proc)
|
|
319
|
+
str_name = name.to_s
|
|
320
|
+
name = name.to_sym
|
|
321
|
+
new_method = LaserMethod.new(str_name, proc)
|
|
322
|
+
new_method.owner = self
|
|
323
|
+
@instance_methods[name] = new_method
|
|
324
|
+
if Bootstrap::VISIBILITY_STACK.value.last == :module_function
|
|
325
|
+
__make_module_function__(name)
|
|
326
|
+
else
|
|
327
|
+
@visibility_table[name] = Bootstrap::VISIBILITY_STACK.value.last
|
|
328
|
+
end
|
|
329
|
+
new_method
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def define_method_with_annotations(name, proc, opts={})
|
|
333
|
+
method = define_method(name, proc)
|
|
334
|
+
opts.each { |name, value| method.send("#{name}=", value) }
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def undef_method(symbol)
|
|
338
|
+
sym = symbol.to_sym
|
|
339
|
+
@instance_methods[sym] = nil
|
|
340
|
+
@visibility_table[sym] = :undefined
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def remove_method(symbol)
|
|
344
|
+
sym = symbol.to_sym
|
|
345
|
+
@instance_methods.delete(sym)
|
|
346
|
+
@visibility_table.delete(sym)
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def alias_method(new, old)
|
|
350
|
+
newsym = new.to_sym
|
|
351
|
+
oldsym = old.to_sym
|
|
352
|
+
@instance_methods[newsym] = @instance_methods[oldsym]
|
|
353
|
+
@visibility_table[newsym] = @visibility_table[oldsym]
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def include(*mods)
|
|
357
|
+
mods.reverse.each { |mod| include_module(mod) }
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def extend(*mods)
|
|
361
|
+
singleton_class.include(*mods)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def __visibility_modifier__(args, kind)
|
|
365
|
+
if args.empty?
|
|
366
|
+
Bootstrap::VISIBILITY_STACK.value[-1] = kind
|
|
367
|
+
else
|
|
368
|
+
args.each { |method| set_visibility!(method.to_sym, kind) }
|
|
369
|
+
end
|
|
370
|
+
self
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def __make_module_function__(method_name)
|
|
374
|
+
set_visibility!(method_name, :private)
|
|
375
|
+
found_method = instance_method(method_name).dup
|
|
376
|
+
singleton_class.add_instance_method!(found_method)
|
|
377
|
+
singleton_class.set_visibility!(method_name, :public)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def public(*args)
|
|
381
|
+
__visibility_modifier__(args, :public)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def protected(*args)
|
|
385
|
+
__visibility_modifier__(args, :protected)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def private(*args)
|
|
389
|
+
__visibility_modifier__(args, :private)
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def module_function(*args)
|
|
393
|
+
if args.any?
|
|
394
|
+
args.each do |method|
|
|
395
|
+
__make_module_function__(method.to_sym)
|
|
396
|
+
end
|
|
397
|
+
else
|
|
398
|
+
Bootstrap::VISIBILITY_STACK.value[-1] = :module_function
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
end
|