Class: Hecks::Bluebook::Assembly::Contract

Inherits:
Struct
  • Object
show all
Defined in:
lib/hecks/bluebook/assembly/contract.rb

Overview

WHAT A CONSTRUCT NEEDS THAT THE LANGUAGE CANNOT SAY, and how a claim that a field needs no assembling is CHECKED.

derived: used to be a list of names, and a list of names is a promise with nobody holding it. The coverage gate only asked whether a field was accounted for — so writing derived: %i[version] would have satisfied it while dropping a chapter's version in silence, which is the exact shape of every defect this arc has found. Naming a field derived is a CLAIM, and a claim needs a kind:

:parent            the containment tree supplies it — a `*_id`, or one of
                 the named pointers below. Checked against the name.
:children          it is assembled as child constructs. Checked against the
                 language: a category must exist whose parent is this one.
[:computed, :m]    the holder works it out. Checked: it must answer to `m`.
[:folded, keys]    several language fields are one thing in the IR, or one
                 is spread across several. Checked: every key must appear
                 in a real reconstructed declaration.
:elsewhere         not a fact about this construct at all. Allow-listed one
                 by one, because it is the kind with no other check.

Every one of those can FAIL. That is the whole difference.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#derivedObject

Returns the value of attribute derived

Returns:

  • (Object)

    the current value of derived



25
26
27
# File 'lib/hecks/bluebook/assembly/contract.rb', line 25

def derived
  @derived
end

#fieldsObject

Returns the value of attribute fields

Returns:

  • (Object)

    the current value of fields



25
26
27
# File 'lib/hecks/bluebook/assembly/contract.rb', line 25

def fields
  @fields
end

#holderObject

Returns the value of attribute holder

Returns:

  • (Object)

    the current value of holder



25
26
27
# File 'lib/hecks/bluebook/assembly/contract.rb', line 25

def holder
  @holder
end

#makeObject

Returns the value of attribute make

Returns:

  • (Object)

    the current value of make



25
26
27
# File 'lib/hecks/bluebook/assembly/contract.rb', line 25

def make
  @make
end

#readsObject

Returns the value of attribute reads

Returns:

  • (Object)

    the current value of reads



25
26
27
# File 'lib/hecks/bluebook/assembly/contract.rb', line 25

def reads
  @reads
end

#rowsObject

Returns the value of attribute rows

Returns:

  • (Object)

    the current value of rows



25
26
27
# File 'lib/hecks/bluebook/assembly/contract.rb', line 25

def rows
  @rows
end

Instance Method Details

#accepts?(keyword) ⇒ Boolean

Returns:

  • (Boolean)


84
85
86
87
88
# File 'lib/hecks/bluebook/assembly/contract.rb', line 84

def accepts?(keyword)
  builder = make == :declare ? holder.method(:declare) : holder.instance_method(:initialize)

  builder.parameters.any? { |kind, name| %i[key keyreq].include?(kind) && name == keyword }
end

#answers?(method) ⇒ Boolean

Returns:

  • (Boolean)


80
81
82
# File 'lib/hecks/bluebook/assembly/contract.rb', line 80

def answers?(method)
  make == :declare ? holder.respond_to?(method) : holder.instance_methods.include?(method)
end

#computes?(method) ⇒ Boolean

COMPUTED means worked out, not merely answerable.

Asking only whether the holder responds was too weak, and measurably so: [:computed, :version] passed, because Bluebook does answer to version — it just answers with what the constructor was handed. A field the constructor TAKES is stored, and calling it computed is how a chapter's version would have gone missing while the gate said yes.

So a computed field is one the holder answers AND the constructor does not accept. query_name qualifies (Naming.snake(name)) ; version cannot.

Returns:

  • (Boolean)


73
74
75
76
77
78
# File 'lib/hecks/bluebook/assembly/contract.rb', line 73

def computes?(method)
  return false unless holder
  return false unless answers?(method)

  !accepts?(method)
end

#declares?(field) ⇒ Boolean

Returns:

  • (Boolean)


40
# File 'lib/hecks/bluebook/assembly/contract.rb', line 40

def declares?(field) = fields.key?(field) || derived.key?(field)

#folded(field) ⇒ Object

WHERE A FOLDED FIELD ACTUALLY LIVES, as [object, member].

[:folded, :lifecycle, :field] says the language's state_field is the field of the IR's one Lifecycle. That is the same fact Readings used to state a second time as node.lifecycle&.field — so saying it once here drives BOTH directions: the walk reads the member on the way in, and the reconstruction gathers the members back into the object on the way out.

A nil member means the fold has no single member to name — rows is a count of what closed_set and members hold between them, and options spreads across eight keys. Those keep their own code, and the gate still checks the object they name is real.



56
57
58
59
60
61
# File 'lib/hecks/bluebook/assembly/contract.rb', line 56

def folded(field)
  kind = derived[field]
  return nil unless kind.is_a?(Array) && kind.first == :folded

  [kind[1], kind[2]]
end

#kind_of(field) ⇒ Object



42
# File 'lib/hecks/bluebook/assembly/contract.rb', line 42

def kind_of(field) = derived[field]

#reader(key) ⇒ Object

How a declaration key is read back off a ROW. Absent means the default — text(row[key]), a single cell — which is most of them ; present names the shape, because a list needs a reader per element and a folded field is gathered rather than fetched. Same pattern as rows, in the other direction: declare the exceptions, default the rest.



31
# File 'lib/hecks/bluebook/assembly/contract.rb', line 31

def reader(key) = Hash(reads)[key.to_sym]

#shaper(list) ⇒ Object

How an appendable LIST becomes rows the walk can offer. A list absent from here reads straight off the node ; one that is present names the shaper, because the IR keeps a shape the language does not — a transition whose from is a list is several rows, an append binds several fields at once, an open map is one row per entry.



38
# File 'lib/hecks/bluebook/assembly/contract.rb', line 38

def shaper(list) = Hash(rows)[list.to_sym]