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,68 @@
|
|
|
1
|
+
module Laser
|
|
2
|
+
module Analysis
|
|
3
|
+
class MethodCall
|
|
4
|
+
attr_reader :node
|
|
5
|
+
|
|
6
|
+
def initialize(node)
|
|
7
|
+
@node = node
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def implicit_receiver?
|
|
11
|
+
case node.type
|
|
12
|
+
when :call, :aref, :unary, :binary, :super, :zsuper then false
|
|
13
|
+
when :fcall, :command, :command_call, :var_ref, :vcall then true
|
|
14
|
+
when :method_add_block, :method_add_arg then node[1].method_call.implicit_receiver?
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Calculates the name of the method this method call represents.
|
|
19
|
+
#
|
|
20
|
+
# returns: String
|
|
21
|
+
def method_name
|
|
22
|
+
case node.type
|
|
23
|
+
when :super, :zsuper then 'super'
|
|
24
|
+
when :aref then :[]
|
|
25
|
+
when :unary then node[1]
|
|
26
|
+
when :binary then node[2]
|
|
27
|
+
when :fcall, :command, :vcall then node[1].expanded_identifier.to_sym
|
|
28
|
+
when :call, :command_call then node[3].expanded_identifier.to_sym
|
|
29
|
+
when :var_ref then node.expanded_identifier.to_sym
|
|
30
|
+
when :method_add_block, :method_add_arg then node[1].method_call.method_name
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# The receiver node is the node representing the explicit receiver.
|
|
35
|
+
# If nil, then the implicit receiver, self, is used.
|
|
36
|
+
#
|
|
37
|
+
# return: Sexp | NilClass
|
|
38
|
+
def receiver_node
|
|
39
|
+
case node.type
|
|
40
|
+
when :method_add_arg, :method_add_block then node[1].method_call.receiver_node
|
|
41
|
+
when :var_ref, :vcall, :command, :fcall, :super, :zsuper, :unary then nil
|
|
42
|
+
when :call, :command_call, :binary, :aref then node[1]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns an ArgumentExpansion representation of the arguments of this
|
|
47
|
+
# method call.
|
|
48
|
+
def arguments
|
|
49
|
+
ArgumentExpansion.new(arg_node)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns a node, if any, representing the arguments to this method call.
|
|
53
|
+
#
|
|
54
|
+
# returns: Sexp
|
|
55
|
+
def arg_node
|
|
56
|
+
case node.type
|
|
57
|
+
when :command, :aref then node[2][1]
|
|
58
|
+
when :method_add_arg then (node[2][1] ? node[2][1] : nil)
|
|
59
|
+
when :method_add_block then node[1].method_call.arg_node
|
|
60
|
+
when :call, :var_ref, :vcall, :command_call, :zsuper then nil
|
|
61
|
+
when :command_call then node[4][1]
|
|
62
|
+
when :super
|
|
63
|
+
node[1].type == :arg_paren ? node[1][1] : node[1]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Laser
|
|
2
|
+
module Analysis
|
|
3
|
+
# The ProtocolRegistry module handles negotiating instantiated protocols at
|
|
4
|
+
# compile-time, such as the automatically-generated protocols created by a
|
|
5
|
+
# class creation (as each class has a corresponding protocol, though some
|
|
6
|
+
# distinct classes may have equivalent protocols).
|
|
7
|
+
module ProtocolRegistry
|
|
8
|
+
extend ModuleExtensions
|
|
9
|
+
cattr_accessor_with_default :class_protocols, {}
|
|
10
|
+
|
|
11
|
+
def self.add_class(klass)
|
|
12
|
+
self.class_protocols[klass.path] = klass
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.[](class_name)
|
|
16
|
+
result = self.class_protocols[class_name.gsub(/^::/, '')]
|
|
17
|
+
result ? [result] : []
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module ClassRegistry
|
|
22
|
+
def self.[](class_name)
|
|
23
|
+
if ProtocolRegistry[class_name].any?
|
|
24
|
+
then ProtocolRegistry[class_name].first
|
|
25
|
+
else raise ArgumentError.new("No class found with the path #{class_name}.")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module Laser
|
|
2
|
+
module Analysis
|
|
3
|
+
# This class models a scope in Ruby. It has a constant table,
|
|
4
|
+
# a self pointer, and a parent pointer to the enclosing scope.
|
|
5
|
+
# It also has a local variable table.
|
|
6
|
+
class Scope
|
|
7
|
+
class ScopeLookupFailure < Error
|
|
8
|
+
attr_accessor :scope, :query
|
|
9
|
+
def initialize(scope, query)
|
|
10
|
+
@scope, @query = scope, query
|
|
11
|
+
super("Scope does not contain #{query.inspect}", nil, MAJOR_ERROR)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# lexical_target = cref in YARV terms
|
|
16
|
+
attr_accessor :constants, :parent, :locals, :method, :lexical_target
|
|
17
|
+
def initialize(parent, self_ptr, constants={}, locals={})
|
|
18
|
+
unless respond_to?(:lookup_local)
|
|
19
|
+
raise NotImplementedError.new(
|
|
20
|
+
'must create OpenScope or ClosedScope. Not just Scope.')
|
|
21
|
+
end
|
|
22
|
+
@parent, @constants, @locals = parent, constants, locals
|
|
23
|
+
@locals['self'] = Bindings::LocalVariableBinding.new('self', self_ptr)
|
|
24
|
+
if self_ptr && Bindings::Base === self_ptr
|
|
25
|
+
self_ptr.self_owner = self
|
|
26
|
+
end
|
|
27
|
+
@lexical_target = self_ptr
|
|
28
|
+
@method = nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def initialize_copy(other)
|
|
32
|
+
@locals = other.locals.dup
|
|
33
|
+
@constants = other.constants.dup
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self_ptr
|
|
37
|
+
@locals['self'].value
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self_ptr=(other)
|
|
41
|
+
@locals['self'] = Bindings::LocalVariableBinding.new('self', other)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_binding!(new_binding)
|
|
45
|
+
case new_binding.name[0,1]
|
|
46
|
+
when /[A-Z]/
|
|
47
|
+
constants[new_binding.name] = new_binding
|
|
48
|
+
else
|
|
49
|
+
locals[new_binding.name] = new_binding
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def path
|
|
54
|
+
self_ptr.path
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def lookup_or_create_local(var_name)
|
|
58
|
+
lookup_local(var_name)
|
|
59
|
+
rescue ScopeLookupFailure
|
|
60
|
+
binding = Bindings::LocalVariableBinding.new(var_name, nil)
|
|
61
|
+
add_binding!(binding)
|
|
62
|
+
binding
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Proper variable lookup. The old ones were hacks.
|
|
66
|
+
def lookup(str)
|
|
67
|
+
if str[0,2] == '::'
|
|
68
|
+
Scope::GlobalScope.lookup(str[2..-1])
|
|
69
|
+
elsif str.include?('::')
|
|
70
|
+
parts = str.split('::')
|
|
71
|
+
final_scope = parts[0..-2].inject(self) { |scope, part| scope.lookup(part).scope }
|
|
72
|
+
final_scope.lookup(parts.last)
|
|
73
|
+
elsif str =~ /^\$/ then lookup_global(str)
|
|
74
|
+
elsif str =~ /^@/ then lookup_ivar(str)
|
|
75
|
+
elsif str =~ /^@@/ then lookup_cvar(str)
|
|
76
|
+
else lookup_local(str)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Looks up a global binding. Defers to the global scope and creates on-demand.
|
|
81
|
+
def lookup_global(str)
|
|
82
|
+
Scope::GlobalScope.locals[str] ||=
|
|
83
|
+
Bindings::GlobalVariableBinding.new(str, nil)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Looks up an instance variable binding. Defers to the current value of self's
|
|
87
|
+
# class,
|
|
88
|
+
def lookup_ivar(str)
|
|
89
|
+
unless (result = self_ptr.klass.instance_variables[str])
|
|
90
|
+
result = Bindings::InstanceVariableBinding.new(str, LaserObject.new)
|
|
91
|
+
self_ptr.klass.add_instance_variable!(result)
|
|
92
|
+
end
|
|
93
|
+
result
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Does this scope see the given variable name?
|
|
97
|
+
def sees_var?(var)
|
|
98
|
+
lookup(var) rescue false
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class OpenScope < Scope
|
|
103
|
+
def lookup_local(str)
|
|
104
|
+
if locals[str]
|
|
105
|
+
then locals[str]
|
|
106
|
+
elsif parent then parent.lookup_local(str)
|
|
107
|
+
else raise ScopeLookupFailure.new(self, str)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
class ClosedScope < Scope
|
|
113
|
+
def lookup_local(str)
|
|
114
|
+
locals[str] or raise ScopeLookupFailure.new(self, str)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
module Laser
|
|
2
|
+
module Analysis
|
|
3
|
+
# Replaces the ParseTree Sexps by adding a few handy-dandy methods.
|
|
4
|
+
class Sexp < Array
|
|
5
|
+
include SexpExtensions::ConstantExtraction
|
|
6
|
+
include SexpExtensions::SourceLocation
|
|
7
|
+
include SexpExtensions::TypeInference
|
|
8
|
+
|
|
9
|
+
extend ModuleExtensions
|
|
10
|
+
attr_accessor :errors, :binding, :file_name, :file_source, :scope
|
|
11
|
+
attr_accessor :reachable
|
|
12
|
+
|
|
13
|
+
# Initializes the Sexp with the contents of the array returned by Ripper.
|
|
14
|
+
#
|
|
15
|
+
# @param [Array<Object>] other the other
|
|
16
|
+
def initialize(other, file_name=nil, file_source=nil)
|
|
17
|
+
@reachable = true
|
|
18
|
+
@expr_type = nil
|
|
19
|
+
@errors = []
|
|
20
|
+
@file_name = file_name
|
|
21
|
+
@file_source = file_source
|
|
22
|
+
replace other
|
|
23
|
+
replace_children!
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @return [Array<Object>] the children of the node.
|
|
27
|
+
def children
|
|
28
|
+
@children ||= ((Array === self[0] ? self : self[1..-1]) || [])
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Symbol] the type of the node.
|
|
32
|
+
def type
|
|
33
|
+
self[0]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def add_error(error)
|
|
37
|
+
errors << error unless errors.include?(error)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# is the given object a sexp?
|
|
41
|
+
#
|
|
42
|
+
# @return Boolean
|
|
43
|
+
def is_sexp?(sexp)
|
|
44
|
+
Analysis::Sexp === sexp
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def lines
|
|
48
|
+
@file_source.lines.to_a
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def find_type(type)
|
|
52
|
+
deep_find { |node| node.type == type }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Same as #find for Enumerable, only recursively. Useful for "jumping"
|
|
56
|
+
# past useless parser nodes.
|
|
57
|
+
def deep_find
|
|
58
|
+
([self] + all_subtrees.to_a).each do |node|
|
|
59
|
+
return node if yield(node)
|
|
60
|
+
end
|
|
61
|
+
nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def all_subtrees
|
|
65
|
+
to_visit = self.children.dup
|
|
66
|
+
visited = Set.new
|
|
67
|
+
while to_visit.any?
|
|
68
|
+
todo = to_visit.shift
|
|
69
|
+
next unless is_sexp?(todo)
|
|
70
|
+
|
|
71
|
+
case todo[0]
|
|
72
|
+
when Array
|
|
73
|
+
to_visit.concat todo
|
|
74
|
+
when ::Symbol
|
|
75
|
+
to_visit.concat todo.children
|
|
76
|
+
visited << todo
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
visited
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Returns an enumerator that iterates over each subnode of this node
|
|
83
|
+
# in DFS order.
|
|
84
|
+
def dfs_enumerator
|
|
85
|
+
Enumerator.new do |g|
|
|
86
|
+
dfs do |node|
|
|
87
|
+
g.yield node
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Returns all errors in this subtree, in DFS order.
|
|
93
|
+
# returns: [Error]
|
|
94
|
+
def all_errors
|
|
95
|
+
dfs_enumerator.map(&:errors).flatten
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Performs a DFS on the node, yielding each subnode (including the given node)
|
|
99
|
+
# in DFS order.
|
|
100
|
+
def dfs
|
|
101
|
+
yield self
|
|
102
|
+
self.children.each do |child|
|
|
103
|
+
next unless is_sexp?(child)
|
|
104
|
+
case child[0]
|
|
105
|
+
when Array
|
|
106
|
+
child.each { |x| x.dfs { |y| yield y}}
|
|
107
|
+
when ::Symbol
|
|
108
|
+
child.dfs { |y| yield y }
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Replaces the children with Sexp versions of them
|
|
114
|
+
def replace_children!
|
|
115
|
+
replace(map do |x|
|
|
116
|
+
case x
|
|
117
|
+
when Array
|
|
118
|
+
self.class.new(x, @file_name, @file_source)
|
|
119
|
+
else x
|
|
120
|
+
end
|
|
121
|
+
end)
|
|
122
|
+
end
|
|
123
|
+
private :replace_children!
|
|
124
|
+
|
|
125
|
+
# Returns the text of the identifier, assuming this node identifies something.
|
|
126
|
+
def expanded_identifier
|
|
127
|
+
case type
|
|
128
|
+
when :@ident, :@const, :@gvar, :@cvar, :@ivar, :@kw, :@op
|
|
129
|
+
self[1]
|
|
130
|
+
when :var_ref, :var_field, :const_ref, :symbol
|
|
131
|
+
self[1].expanded_identifier
|
|
132
|
+
when :top_const_ref, :top_const_field
|
|
133
|
+
"::#{self[1].expanded_identifier}"
|
|
134
|
+
when :const_path_ref, :const_path_field
|
|
135
|
+
lhs, rhs = children
|
|
136
|
+
"#{lhs.expanded_identifier}::#{rhs.expanded_identifier}"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def is_method_call?
|
|
141
|
+
[:command, :method_add_arg, :method_add_block, :vcall, :var_ref, :call,
|
|
142
|
+
:fcall, :command_call, :binary, :unary, :super, :zsuper, :aref].include?(type)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Returns the MethodCall wrapping up all the method call information about this
|
|
146
|
+
# node.
|
|
147
|
+
#
|
|
148
|
+
# raises: TypeError
|
|
149
|
+
# return: MethodCall
|
|
150
|
+
def method_call
|
|
151
|
+
unless is_method_call?
|
|
152
|
+
raise TypeError.new("Only method call nodes define #method_call. "+
|
|
153
|
+
"This node is of type #{type}.")
|
|
154
|
+
end
|
|
155
|
+
MethodCall.new(self)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Laser
|
|
2
|
+
# This is a set of methods that get provided to Warnings so they can perform
|
|
3
|
+
# parse-tree analysis of their bodies.
|
|
4
|
+
module Analysis
|
|
5
|
+
extend ModuleExtensions
|
|
6
|
+
|
|
7
|
+
# inputs: Array<(String, String)>
|
|
8
|
+
# Array of (filename, body) tuples.
|
|
9
|
+
def self.analyze_inputs(inputs)
|
|
10
|
+
Annotations.annotate_inputs(inputs)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
PARSING_CACHE = {}
|
|
14
|
+
|
|
15
|
+
# Parses the given text.
|
|
16
|
+
#
|
|
17
|
+
# @param [String] body (self.body) The text to parse
|
|
18
|
+
# @return [Sexp, NilClass] the sexp representing the input text.
|
|
19
|
+
def parse(body = self.body)
|
|
20
|
+
return PARSING_CACHE[body] if PARSING_CACHE[body]
|
|
21
|
+
pairs = Analysis.analyze_inputs([['(stdin)', body]])
|
|
22
|
+
PARSING_CACHE[body] = pairs[0][1]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Finds all sexps of the given type in the given Sexp tree.
|
|
26
|
+
#
|
|
27
|
+
# @param [Symbol] type the type of sexp to search for
|
|
28
|
+
# @param [Sexp] tree (self.parse(self.body)) The tree to search in. Leave
|
|
29
|
+
# blank to search the entire body.
|
|
30
|
+
# @return [Array<Sexp>] all sexps in the input tree (or whole body) that
|
|
31
|
+
# are of the given type.
|
|
32
|
+
def find_sexps(type, tree = self.parse(self.body))
|
|
33
|
+
result = tree[0] == type ? [tree] : []
|
|
34
|
+
tree.each do |node|
|
|
35
|
+
result.concat find_sexps(type, node) if node.is_a?(Array)
|
|
36
|
+
end
|
|
37
|
+
result
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
module Laser::Analysis
|
|
2
|
+
module SexpExtensions
|
|
3
|
+
module ConstantExtraction
|
|
4
|
+
|
|
5
|
+
# Is this node of constant value? This might be known statically (because
|
|
6
|
+
# it is a literal) or it might be because it's been proven through analysis.
|
|
7
|
+
def is_constant
|
|
8
|
+
case self.type
|
|
9
|
+
when :@CHAR, :@tstring_content, :@int, :@float, :@regexp_end, :symbol, :@label
|
|
10
|
+
true
|
|
11
|
+
when :string_content, :string_literal, :assoc_new, :symbol_literal, :dot2, :dot3
|
|
12
|
+
children.all?(&:is_constant)
|
|
13
|
+
when :hash
|
|
14
|
+
self[1].nil? || self[1].is_constant
|
|
15
|
+
when :array, :regexp_literal, :assoclist_from_args, :bare_assoc_hash, :dyna_symbol
|
|
16
|
+
self[1].nil? || self[1].all?(&:is_constant)
|
|
17
|
+
when :var_ref, :const_ref, :const_path_ref, :var_field
|
|
18
|
+
if self[1].type == :@kw
|
|
19
|
+
%w(nil true false self __LINE__ __FILE__).include?(expanded_identifier)
|
|
20
|
+
elsif !self.binding.nil?
|
|
21
|
+
Bindings::ConstantBinding === scope.lookup(expanded_identifier)
|
|
22
|
+
end
|
|
23
|
+
when :paren
|
|
24
|
+
self[1].type != :params && self[1].all?(&:is_constant)
|
|
25
|
+
else
|
|
26
|
+
false
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# What is this node's constant value? This might be known statically (because
|
|
31
|
+
# it is a literal) or it might be because it's been proven through analysis.
|
|
32
|
+
def constant_value
|
|
33
|
+
unless is_constant
|
|
34
|
+
return :none
|
|
35
|
+
end
|
|
36
|
+
case type
|
|
37
|
+
when :@CHAR
|
|
38
|
+
char_part = self[1][1..-1]
|
|
39
|
+
if char_part.size == 1
|
|
40
|
+
char_part
|
|
41
|
+
else
|
|
42
|
+
eval(%Q{"#{char_part}"})
|
|
43
|
+
end
|
|
44
|
+
when :@tstring_content
|
|
45
|
+
str = self[1]
|
|
46
|
+
pos = self.parent.parent.source_begin
|
|
47
|
+
first_two = lines[pos[0]-1][pos[1],2]
|
|
48
|
+
if first_two[0,1] == '"' || first_two == '%Q'
|
|
49
|
+
eval(%Q{"#{str}"})
|
|
50
|
+
else
|
|
51
|
+
str
|
|
52
|
+
end
|
|
53
|
+
when :string_content
|
|
54
|
+
children.map(&:constant_value).join
|
|
55
|
+
when :string_literal, :symbol_literal
|
|
56
|
+
self[1].constant_value
|
|
57
|
+
when :@int
|
|
58
|
+
Integer(self[1])
|
|
59
|
+
when :@float
|
|
60
|
+
Float(self[1])
|
|
61
|
+
when :@regexp_end
|
|
62
|
+
str = self[1]
|
|
63
|
+
result = 0
|
|
64
|
+
result |= Regexp::IGNORECASE if str.include?('i')
|
|
65
|
+
result |= Regexp::MULTILINE if str.include?('m')
|
|
66
|
+
result |= Regexp::EXTENDED if str.include?('x')
|
|
67
|
+
result
|
|
68
|
+
when :regexp_literal
|
|
69
|
+
parts, options = children
|
|
70
|
+
Regexp.new(parts.map(&:constant_value).join, options.constant_value)
|
|
71
|
+
when :assoc_new
|
|
72
|
+
children.map(&:constant_value)
|
|
73
|
+
when :assoclist_from_args, :bare_assoc_hash
|
|
74
|
+
parts = self[1]
|
|
75
|
+
Hash[*parts.map(&:constant_value).flatten]
|
|
76
|
+
when :hash
|
|
77
|
+
part = self[1]
|
|
78
|
+
part.nil? ? {} : part.constant_value
|
|
79
|
+
when :symbol
|
|
80
|
+
self[1][1].to_sym
|
|
81
|
+
when :dyna_symbol
|
|
82
|
+
parts = self[1]
|
|
83
|
+
parts.map(&:constant_value).join.to_sym
|
|
84
|
+
when :@label
|
|
85
|
+
self[1][0..-2].to_sym
|
|
86
|
+
when :array
|
|
87
|
+
parts = self[1]
|
|
88
|
+
parts.nil? ? [] : parts.map(&:constant_value)
|
|
89
|
+
when :var_ref, :const_path_ref, :const_ref, :var_field
|
|
90
|
+
case self[1].type
|
|
91
|
+
when :@kw
|
|
92
|
+
case self[1][1]
|
|
93
|
+
when 'self' then scope.self_ptr
|
|
94
|
+
when 'nil' then nil
|
|
95
|
+
when 'true' then true
|
|
96
|
+
when 'false' then false
|
|
97
|
+
when '__LINE__' then self[1][2][0]
|
|
98
|
+
when '__FILE__' then @file_name
|
|
99
|
+
end
|
|
100
|
+
else
|
|
101
|
+
scope.lookup(expanded_identifier).value
|
|
102
|
+
end
|
|
103
|
+
when :dot2
|
|
104
|
+
lhs, rhs = children
|
|
105
|
+
(lhs.constant_value)..(rhs.constant_value)
|
|
106
|
+
when :dot3
|
|
107
|
+
lhs, rhs = children
|
|
108
|
+
(lhs.constant_value)...(rhs.constant_value)
|
|
109
|
+
when :paren
|
|
110
|
+
self[1].last.constant_value
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|