Module: Jade::Frontend::TypeChecking::Constraints

Extended by:
Constraints
Included in:
Constraints
Defined in:
lib/jade/frontend/type_checking/constraints.rb,
lib/jade/frontend/type_checking/constraints/deriving.rb,
lib/jade/frontend/type_checking/constraints/deriving/eq.rb,
lib/jade/frontend/type_checking/constraints/deriving/helpers.rb,
lib/jade/frontend/type_checking/constraints/deriving/decodable.rb,
lib/jade/frontend/type_checking/constraints/deriving/encodable.rb

Defined Under Namespace

Modules: Deriving

Instance Method Summary collapse

Instance Method Details

#attach_dictionary(constraint, impl) ⇒ Object

An origin’s dictionaries can be touched by multiple inference frames: the call’s own callee constraints attach here, and outer frames also attach when args bubble up concretely. Var-typed markers’ ids may chain further as inference proceeds; the finalize-time canonicalize pass walks the AST and rewrites them to their final form so codegen can read marker.type.id directly.



52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/jade/frontend/type_checking/constraints.rb', line 52

def attach_dictionary(constraint, impl)
  constraint => Type::Constraint(
    origin: { dictionaries: dicts },
    index:,
  )

  fail "constraint missing index: #{constraint}" if index == :unindex

  return if dicts[index].is_a?(Symbol::Implementation) &&
            impl.is_a?(Type::Constraint)

  dicts[index] = impl
end

#resolve(constraint, registry, entry_name) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/jade/frontend/type_checking/constraints.rb', line 9

def resolve(constraint, registry, entry_name)
  if constraint.type in Type::Var
    Error::UnresolvedConstraint
      .new(entry_name, constraint.origin&.range, constraint:)
      .then { return Err[it] }
  end

  if impl = lookup(constraint, registry)
    impl
      .extends
      .map do |iface_ref|
        Type
          .constraint(
            iface_ref.qualified_name,
            constraint.type,
            constraint.origin,
          )
        .then { resolve(it, registry, entry_name) } => Ok[resolved]

        resolved
      end
      .then { impl.deps + it }
      .then { impl.with(deps: it) }
      .then { return Ok[it] }
  end

  if Deriving.derivable?(constraint.interface)
    Deriving
      .derive(constraint, registry, entry_name) { resolve(it, registry, entry_name) }
      .then { return it }
  end

  constraint.origin.range
    .then { Error::MissingImplementation.new(entry_name, it, constraint:) }
    .then { Err[it] }
end

#solve_at_call_site(constraint, registry, entry_name) ⇒ Object



74
75
76
77
78
79
80
# File 'lib/jade/frontend/type_checking/constraints.rb', line 74

def solve_at_call_site(constraint, registry, entry_name)
  resolve(constraint, registry, entry_name)
    .map { |impl| attach_dictionary(constraint, impl); [] }
    .on_err(Error::MissingImplementation) { Ok[[it]] }
    .on_err(Error::DerivationFailed) { Ok[[it]] }
    .with_default([])
end

#solve_at_finalize(constraint, registry, entry_name) ⇒ Object



66
67
68
69
70
71
72
# File 'lib/jade/frontend/type_checking/constraints.rb', line 66

def solve_at_finalize(constraint, registry, entry_name)
  resolve(constraint, registry, entry_name)
    .map { |impl| attach_dictionary(constraint, impl); [] }
    .on_err(Error::UnresolvedConstraint) { Ok[[]] }
    .on_err { Ok[[it]] }
    .with_default([])
end