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



87
88
89
90
91
92
93
# File 'lib/jade/codegen/boundary/specialized.rb', line 87

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



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

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



65
66
67
# File 'lib/jade/codegen/boundary/specialized.rb', line 65

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

#encode_expr(type, value_expr, registry) ⇒ Object

How to encode value_expr to the wire form:

String    inline expression
:identity the value is already wire-shaped; emit it unchanged
nil       not specializable; fall back to the cached encoder


36
37
38
39
40
41
42
# File 'lib/jade/codegen/boundary/specialized.rb', line 36

def encode_expr(type, value_expr, registry)
  return :identity if identity_encoder?(type)

  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)


47
48
49
# File 'lib/jade/codegen/boundary/specialized.rb', line 47

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.



74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/jade/codegen/boundary/specialized.rb', line 74

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)


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

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.



96
97
98
99
100
101
102
103
104
105
106
# File 'lib/jade/codegen/boundary/specialized.rb', line 96

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