Module: Jade::Codegen::Boundary::Specialized

Extended by:
Specialized
Included in:
Specialized
Defined in:
lib/jade/codegen/boundary/specialized.rb,
lib/jade/codegen/boundary/specialized/list.rb,
lib/jade/codegen/boundary/specialized/maybe.rb,
lib/jade/codegen/boundary/specialized/record.rb,
lib/jade/codegen/boundary/specialized/scalar.rb

Overview

Emits inline boundary code for known-shape types — scalars, ‘List(specializable)`, `Maybe(specializable)`, and structs whose fields are all specializable. Bypasses `Decode::Runner` and the descriptor cache.

This module is the dispatcher: each shape (‘Scalar`, `List`, `Maybe`, `Record`) lives in its own file under `specialized/`, exposing `decode` / `encode` / `specializable?` methods that the dispatcher tries in order. Shapes that contain other types (`List`, `Maybe`, `Record`) recurse back through the dispatcher.

Defined Under Namespace

Modules: List, Maybe, Record, Scalar

Instance Method Summary collapse

Instance Method Details

#args_of(type) ⇒ Object



83
84
85
86
87
88
89
# File 'lib/jade/codegen/boundary/specialized.rb', line 83

def args_of(type)
  case type
  in Type::Application(args:)         then args
  in Symbol::TypeApplication(args:)   then args
  else                                     nil
  end
end

#collect_helpers(body, registry) ⇒ Object



57
58
59
# File 'lib/jade/codegen/boundary/specialized.rb', line 57

def collect_helpers(body, registry)
  Record.collect_helpers(body, registry)
end

#decode_expr(type, input, registry) ⇒ Object

Ruby expression that validates ‘input` and yields the decoded value, or `nil` if `type` isn’t specializable.



24
25
26
27
28
29
# File 'lib/jade/codegen/boundary/specialized.rb', line 24

def decode_expr(type, input, registry)
  Scalar.decode(type, input) ||
    List.decode(type, input, registry) ||
    Maybe.decode(type, input, registry) ||
    Record.decode(type, input, registry)
end

#emit_helpers(structs, registry) ⇒ Object



61
62
63
# File 'lib/jade/codegen/boundary/specialized.rb', line 61

def emit_helpers(structs, registry)
  Record.emit_helpers(structs, registry)
end

#encode_expr(type, value_expr, registry) ⇒ Object

Ruby expression that encodes ‘value_expr` to the wire form, or `nil` if the encoder is identity (caller skips the wrap) or the type isn’t specializable (caller falls back to the cache).



34
35
36
37
38
# File 'lib/jade/codegen/boundary/specialized.rb', line 34

def encode_expr(type, value_expr, registry)
  Record.encode(type, value_expr, registry) ||
    List.encode(type, value_expr, registry) ||
    Maybe.encode(type, value_expr, registry)
end

#identity_encoder?(type) ⇒ Boolean

True when the encoder for ‘type` produces output equal to the input — the boundary wrapper can skip the encode call entirely. Recursive: `List(t)` is identity iff `t` is.

Returns:

  • (Boolean)


43
44
45
# File 'lib/jade/codegen/boundary/specialized.rb', line 43

def identity_encoder?(type)
  Scalar.identity_encoder?(type) || List.identity_encoder?(type)
end

#qname_of(type) ⇒ Object

Both ‘Type::Application` (from inferred boundary types) and `Symbol::TypeApplication` (from struct field declarations) carry the same constructor/args shape; normalize to a qname string.



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/jade/codegen/boundary/specialized.rb', line 70

def qname_of(type)
  case type
  in Type::Application(constructor: Type::Constructor(name:))
    name

  in Symbol::TypeApplication(constructor: Symbol::TypeRef(module_name:, name: n))
    "#{module_name}.#{n}"

  else
    nil
  end
end

#specializable_field?(type, registry, seen) ⇒ Boolean

Predicate used by ‘Record.specializable_struct` when checking field types. The `seen` set carries struct qnames we’re already inside, threaded through container shapes for cycle detection.

Returns:

  • (Boolean)


50
51
52
53
54
55
# File 'lib/jade/codegen/boundary/specialized.rb', line 50

def specializable_field?(type, registry, seen)
  Scalar.specializable?(type, registry, seen) ||
    List.specializable?(type, registry, seen) ||
    Maybe.specializable?(type, registry, seen) ||
    Record.specializable?(type, registry, seen)
end

#type_label(type) ⇒ Object

Human-readable label for error messages on container types.



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/jade/codegen/boundary/specialized.rb', line 92

def type_label(type)
  if (qname = Scalar.qname_for(type))
    Scalar::LABEL[qname]
  elsif (inner = List.inner_of(type))
    "List(#{type_label(inner)})"
  elsif (inner = Maybe.inner_of(type))
    "Maybe(#{type_label(inner)})"
  else
    (qname_of(type) || 'value').split('.').last
  end
end