Class: Audition::Static::LiteralClassifier
- Inherits:
-
Object
- Object
- Audition::Static::LiteralClassifier
- Defined in:
- lib/audition/static/literal_classifier.rb
Overview
Classifies a Prism expression node by Ractor shareability:
:shareable proven deeply shareable
:mutable_string unfrozen String literal
:mutable_container Array/Hash/Set literal or constructor
:mutable_call unfrozen String, Regexp, or sentinel
Object returned by a call (`.tr`,
`format`, `Regexp.new`, `Object.new`)
:shallow_freeze frozen container with mutable elements
:sync_primitive Mutex/Queue/... constructor
:proc lambda or proc
:default_proc Hash.new with a block; the block
survives .freeze and stays unshareable
:unknown cannot tell statically
Constant Summary collapse
- SYNC_PRIMITIVES =
%w[ Mutex Monitor Queue SizedQueue ConditionVariable Thread::Mutex Thread::Queue Thread::SizedQueue Thread::ConditionVariable ].freeze
- SHAREABLE_FACTORIES =
%w[Struct Class Module].freeze
- SENTINEL_FACTORIES =
Sentinels:
NOT_GIVEN = Object.newraises when read from a worker until frozen, and a frozen bare Object is shareable (verified on Ruby 4.0.6). BasicObject has no #freeze. %w[Object BasicObject].freeze
- UNFREEZABLE_COLLECTIONS =
Concurrent::Map defines no #freeze, so make_shareable raises NoMethodError on it; a constant holding one can never be shared (verified on 4.0.6 with concurrent-ruby).
%w[Concurrent::Map].freeze
- STRING_ONLY_METHODS =
Calls returning a fresh, unfrozen String or Regexp;
# frozen_string_literal: truecovers literals only. Both shapes (.trandRegexp.new) turn up in constants in the wild. These names belong to String alone in core, so any receiver qualifies. %i[ tr tr_s gsub sub squeeze strip lstrip rstrip chomp chop center ljust rjust encode scrub unicode_normalize ].freeze
- STRING_LITERAL_METHODS =
Unambiguous only on a String literal receiver: Symbols and numbers define these too and return shareable values.
%i[ + * % upcase downcase capitalize swapcase reverse dup succ next ].freeze
- FORMATTERS =
%i[format sprintf].freeze
- REGEXP_FACTORIES =
%i[new union compile].freeze
Instance Method Summary collapse
-
#classify(node) ⇒ Symbol
Classification, see class docs.
-
#const_name(node) ⇒ Object
::MutexandMutexare the same constant for matching purposes; the leading colons are stripped. -
#frozen_kind(value) ⇒ Object
What
value.freezewould classify as, for the check to choose a plain.freezeover a deep wrap: :shareable when every element is provably shareable, :shallow_freeze when one is provably mutable, :unknown otherwise. -
#initialize(frozen_string_literal:) ⇒ LiteralClassifier
constructor
A new instance of LiteralClassifier.
Constructor Details
#initialize(frozen_string_literal:) ⇒ LiteralClassifier
Returns a new instance of LiteralClassifier.
57 58 59 |
# File 'lib/audition/static/literal_classifier.rb', line 57 def initialize(frozen_string_literal:) @frozen_string_literal = frozen_string_literal end |
Instance Method Details
#classify(node) ⇒ Symbol
Returns classification, see class docs.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/audition/static/literal_classifier.rb', line 63 def classify(node) case node when Prism::IntegerNode, Prism::FloatNode, Prism::RationalNode, Prism::ImaginaryNode, Prism::SymbolNode, Prism::InterpolatedSymbolNode, Prism::TrueNode, Prism::FalseNode, Prism::NilNode, Prism::RegularExpressionNode, Prism::InterpolatedRegularExpressionNode :shareable when Prism::StringNode @frozen_string_literal ? :shareable : :mutable_string when Prism::InterpolatedStringNode classify_interpolated_string(node) when Prism::ArrayNode, Prism::HashNode, Prism::KeywordHashNode container_kind(node) when Prism::RangeNode ends = [node.left, node.right].compact if ends.all? { |n| classify(n) == :shareable } :shareable else :unknown end when Prism::LambdaNode :proc when Prism::CallNode classify_call(node) when Prism::IfNode ternary_kind(node) else :unknown end end |
#const_name(node) ⇒ Object
::Mutex and Mutex are the same constant for matching
purposes; the leading colons are stripped.
99 100 101 102 103 104 105 106 |
# File 'lib/audition/static/literal_classifier.rb', line 99 def const_name(node) case node when Prism::ConstantReadNode node.name.to_s when Prism::ConstantPathNode node.location.slice.delete_prefix("::") end end |
#frozen_kind(value) ⇒ Object
What value.freeze would classify as, for the check to
choose a plain .freeze over a deep wrap: :shareable
when every element is provably shareable, :shallow_freeze
when one is provably mutable, :unknown otherwise.
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/audition/static/literal_classifier.rb', line 112 def frozen_kind(value) case value when Prism::ArrayNode, Prism::HashNode, Prism::KeywordHashNode deep_classify(value.elements) when Prism::CallNode elements = set_elements(value) elements ? deep_classify(elements) : :unknown else :unknown end end |