Class: Rubycc::Front::InitializerResolver
- Inherits:
-
Object
- Object
- Rubycc::Front::InitializerResolver
- Defined in:
- lib/rubycc/front/initializer_resolver.rb
Overview
Resolves an initializer (6.7.9) against the object's type into a flat list of scalar/string placements plus a completed type. The whole current-object walk lives here — nested braces, brace elision (an aggregate subobject with no braces of its own keeps drawing from the enclosing list), designated initializers ("[i] = ", ".m = ", and chains such as ".a.b = "), the "0" idiom, unions (the first member by default, any member by designator) and transparent designation into an anonymous member — so both the local and the global lowering share one interpretation and neither re-implements it.
What it deliberately leaves out: it never evaluates a scalar's value (that is the caller's, since a constant fold and a run-time store differ), and it never type-checks a scalar against its slot (the caller applies the ordinary assignment conversion). It only diagnoses the structural errors — excess elements, a braced list for a scalar, an unknown member, an out-of-range index and an over-long char-array string — that depend on the shape alone.
Defined Under Namespace
Classes: Cursor
Class Method Summary collapse
-
.char_array?(type) ⇒ Boolean
An array of character type — the one aggregate a string literal may initialize as a whole (6.7.9p14).
-
.resolve(type, initializer, static_storage: false, type_of: nil) ⇒ Object
static_storagesays the object being initialized lives in .data/.bss (a file-scope definition or a block-scopestatic), which is the only place a trailing flexible array member may be initialized. -
.structural?(type, init) ⇒ Boolean
Whether
initinitializestypestructurally (needs this resolver) rather than as a plain scalar value: a brace list always does, and so does a bare string literal aimed at a char array.
Instance Method Summary collapse
Class Method Details
.char_array?(type) ⇒ Boolean
An array of character type — the one aggregate a string literal may
initialize as a whole (6.7.9p14). Any of the three character types
qualifies (plain char under either target signedness, signed char,
unsigned char), since the literal's bytes are copied in unchanged.
99 100 101 |
# File 'lib/rubycc/front/initializer_resolver.rb', line 99 def self.char_array?(type) type.array? && Type.character?(type.element) end |
.resolve(type, initializer, static_storage: false, type_of: nil) ⇒ Object
static_storage says the object being initialized lives in .data/.bss
(a file-scope definition or a block-scope static), which is the only
place a trailing flexible array member may be initialized.
type_of is how the caller lends this resolver its view of expression
types: a callable taking an expression node and answering its
Rubycc::Type, or nil when it cannot tell (see #single_expression_init?,
which is the only thing that asks). It must not emit code or evaluate
anything — the generator passes its #static_type inference, the parser
the smaller one it uses for parse-time sizeof. A caller with no type
table at all may leave it out, and every subobject then falls to brace
elision as it did before the hook existed.
115 116 117 |
# File 'lib/rubycc/front/initializer_resolver.rb', line 115 def self.resolve(type, initializer, static_storage: false, type_of: nil) new.resolve(type, initializer, static_storage: static_storage, type_of: type_of) end |
.structural?(type, init) ⇒ Boolean
Whether init initializes type structurally (needs this resolver)
rather than as a plain scalar value: a brace list always does, and so
does a bare string literal aimed at a char array. Both the parser (to
decide whether to fold or defer) and the generator consult this.
90 91 92 93 |
# File 'lib/rubycc/front/initializer_resolver.rb', line 90 def self.structural?(type, init) init.is_a?(AST::InitializerList) || (char_array?(type) && init.is_a?(AST::StringLit)) end |
Instance Method Details
#resolve(type, initializer, static_storage: false, type_of: nil) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/rubycc/front/initializer_resolver.rb', line 119 def resolve(type, initializer, static_storage: false, type_of: nil) @entries = [] @static_storage = static_storage @type_of = type_of @flexible_bytes = 0 # The first expression this run could not type against a struct # subobject, if any; #excess_elements_error reports against it. @untyped_struct_item = nil # Only the object's *own* trailing flexible array member may be # initialized; one reached through a nested struct is rejected, so # remember which struct owns the one initializer this run may fill. @flexible_owner = type.struct? ? type : nil final = init_top(type, initializer) ResolvedInitializer.new(final, @entries, @flexible_bytes) end |