jade-lang 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +78 -0
  3. data/README.md +1 -0
  4. data/docs/json.md +34 -3
  5. data/lib/jade/ast.rb +15 -3
  6. data/lib/jade/cli/init.rb +86 -0
  7. data/lib/jade/cli.rb +2 -0
  8. data/lib/jade/codegen/function_call.rb +25 -10
  9. data/lib/jade/codegen/function_declaration.rb +2 -10
  10. data/lib/jade/codegen/helpers.rb +42 -0
  11. data/lib/jade/codegen/implementation.rb +33 -8
  12. data/lib/jade/formatter/leaves.rb +12 -1
  13. data/lib/jade/formatter/type.rb +3 -5
  14. data/lib/jade/frontend/forward_declaration/interface_declaration.rb +16 -3
  15. data/lib/jade/frontend/type_checking/error/cross_module_requirement.rb +36 -0
  16. data/lib/jade/frontend/type_checking/error/implementation_function_constraint.rb +36 -0
  17. data/lib/jade/frontend/type_checking/error/record_update_type_mismatch.rb +21 -0
  18. data/lib/jade/frontend/type_checking/error/undeclared_requirement.rb +35 -0
  19. data/lib/jade/frontend/type_checking/error.rb +4 -0
  20. data/lib/jade/frontend/type_checking/inference/function_declaration.rb +0 -5
  21. data/lib/jade/frontend/type_checking/inference/helpers.rb +9 -0
  22. data/lib/jade/frontend/type_checking/inference/implementation.rb +93 -16
  23. data/lib/jade/frontend/type_checking/inference/qualified_access.rb +1 -0
  24. data/lib/jade/frontend/type_checking/inference/record_update.rb +8 -1
  25. data/lib/jade/frontend/type_checking/inference/variable_reference.rb +1 -0
  26. data/lib/jade/frontend/type_checking/requirements.rb +115 -0
  27. data/lib/jade/frontend/type_checking/state.rb +10 -2
  28. data/lib/jade/frontend/type_checking.rb +9 -3
  29. data/lib/jade/parsing/type.rb +1 -1
  30. data/lib/jade/parsing.rb +14 -1
  31. data/lib/jade/stdlib/decode.rb +11 -0
  32. data/lib/jade/symbol/interface_function.rb +2 -1
  33. data/lib/jade/symbol/stdlib_function.rb +1 -1
  34. data/lib/jade/symbol.rb +2 -2
  35. data/lib/jade/type/function.rb +12 -13
  36. data/lib/jade/type.rb +12 -3
  37. data/lib/jade/version.rb +1 -1
  38. metadata +8 -2
@@ -0,0 +1,21 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ # An update produces a record of its own, which then has to be the
6
+ # record the surrounding code wanted. Changing a field's type is the
7
+ # usual way to break that, and any other disagreement lands here too.
8
+ class RecordUpdateTypeMismatch < TypeMismatch
9
+ def message
10
+ "This update produces #{naming.annotated(@actual)}, " \
11
+ "but #{naming.annotated(@expected)} was expected"
12
+ end
13
+
14
+ def label
15
+ "produces #{naming[@actual]}, expected #{naming[@expected]}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class UndeclaredRequirement < Jade::Error
6
+ def initialize(entry, span, interface:, fn_name:, constraint:, declared:)
7
+ super(entry:, span:)
8
+ @interface = interface
9
+ @fn_name = fn_name
10
+ @constraint = constraint
11
+ @declared = declared
12
+ end
13
+
14
+ def message
15
+ "Implementation of #{@interface}.#{@fn_name} requires #{@constraint}, " \
16
+ "which #{@interface} does not declare. It declares #{@declared}"
17
+ end
18
+
19
+ def label
20
+ "requires #{@constraint}"
21
+ end
22
+
23
+ def notes
24
+ [
25
+ Jade::Diagnostics::Annotation[
26
+ :help,
27
+ "add it to the method: `#{@fn_name} : ... with #{@constraint}`",
28
+ ],
29
+ ]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -19,6 +19,10 @@ require 'jade/frontend/type_checking/error/pattern_type_mismatch'
19
19
  require 'jade/frontend/type_checking/error/empty_range_pattern'
20
20
  require 'jade/frontend/type_checking/error/range_pattern_type'
21
21
  require 'jade/frontend/type_checking/error/record_access_type_mismatch'
22
+ require 'jade/frontend/type_checking/error/record_update_type_mismatch'
22
23
  require 'jade/frontend/type_checking/error/unresolved_constraint'
23
24
  require 'jade/frontend/type_checking/error/implementation_type_mismatch'
25
+ require 'jade/frontend/type_checking/error/implementation_function_constraint'
26
+ require 'jade/frontend/type_checking/error/cross_module_requirement'
27
+ require 'jade/frontend/type_checking/error/undeclared_requirement'
24
28
  require 'jade/frontend/type_checking/error/missing_implementation'
@@ -48,11 +48,6 @@ module Jade
48
48
  .map { st.env.substitution.apply(it) }
49
49
  .uniq { it.type.is_a?(Type::Var) ? [it.interface, it.type] : it }
50
50
 
51
- # TODO: for impl function declarations, unresolved constraints here
52
- # (e.g. Eq(a) when the body calls == on a field of type a) should
53
- # be stored as impl-level constraints, not function-level ones.
54
- # The impl finalization pass (see TypeChecking.finalize) should then
55
- # promote them into deps when the impl is instantiated for a concrete type.
56
51
  st.bind(
57
52
  symbol.qualified_name,
58
53
  Placeholder[
@@ -27,6 +27,15 @@ module Jade
27
27
  def type_from_symbol(symbol, registry, var_gen)
28
28
  Type.from_symbol(symbol, registry, var_gen)
29
29
  end
30
+
31
+ def attach_markers(result)
32
+ result
33
+ .constraints
34
+ .select { it.type.is_a?(Type::Var) && it.index != :unindex }
35
+ .each { Constraints.attach_dictionary(it, it) }
36
+
37
+ result
38
+ end
30
39
  end
31
40
  end
32
41
  end
@@ -57,6 +57,8 @@ module Jade
57
57
  st_after_bind,
58
58
  Expected.check(expected_type),
59
59
  interface_qname,
60
+ concrete_type,
61
+ iface_fn_type,
60
62
  )
61
63
  end
62
64
  .then { [it, Result.init(Type.unit)] }
@@ -64,7 +66,7 @@ module Jade
64
66
 
65
67
  private
66
68
 
67
- def infer_fn(impl_fn, registry, state, expected, interface_qname)
69
+ def infer_fn(impl_fn, registry, state, expected, interface_qname, head_type, sig_type)
68
70
  impl_fn => AST::ImplementationFunction(name:, fn:)
69
71
 
70
72
  case fn
@@ -83,29 +85,63 @@ module Jade
83
85
  state,
84
86
  Expected.infer(state.fresh),
85
87
  )
86
- body_state.unify(
87
- body_result.type,
88
- expected.type,
89
- &mismatch_error(state.env.entry_name, impl_fn, interface_qname, name)
90
- )
88
+ body_state
89
+ .unify(
90
+ body_result.type,
91
+ expected.type,
92
+ &mismatch_error(state.env.entry_name, impl_fn, interface_qname, name)
93
+ )
94
+ .then do |unified|
95
+ record_requirements(
96
+ unified,
97
+ body_result.constraints,
98
+ head_type,
99
+ sig_type,
100
+ interface_qname,
101
+ impl_fn,
102
+ name,
103
+ )
104
+ end
91
105
  end
92
106
 
93
107
  in AST::Lambda
94
- check(fn, registry, state, expected).first
108
+ lambda_state, lambda_result = check(fn, registry, state, expected)
109
+
110
+ record_requirements(
111
+ lambda_state,
112
+ lambda_result.constraints,
113
+ head_type,
114
+ sig_type,
115
+ interface_qname,
116
+ impl_fn,
117
+ name,
118
+ )
95
119
 
96
120
  in AST::VariableReference
97
121
  ref_state, ref_result = check(fn, registry, state, expected)
98
122
 
99
- ref_state.unify(
100
- ref_result.type,
101
- expected.type,
102
- &mismatch_error(
103
- state.env.entry_name,
104
- impl_fn,
105
- interface_qname,
106
- name
123
+ ref_state
124
+ .unify(
125
+ ref_result.type,
126
+ expected.type,
127
+ &mismatch_error(
128
+ state.env.entry_name,
129
+ impl_fn,
130
+ interface_qname,
131
+ name
132
+ )
107
133
  )
108
- )
134
+ .then do |unified|
135
+ record_requirements(
136
+ unified,
137
+ ref_result.constraints,
138
+ head_type,
139
+ sig_type,
140
+ interface_qname,
141
+ impl_fn,
142
+ name,
143
+ )
144
+ end
109
145
 
110
146
  # `decoder: zero_arg_fn` becomes `FunctionCall(zero_arg_fn, [])`
111
147
  # after ZeroArgRewrite. Type the call; its result must match the
@@ -115,6 +151,47 @@ module Jade
115
151
  end
116
152
  end
117
153
 
154
+ def record_requirements(state, constraints, head_type, sig_type, interface_qname, impl_fn, fn_name)
155
+ substitution = state.env.substitution
156
+ head_vars = substitution.apply(head_type).unbound_vars.map(&:id).to_set
157
+ names = signature_names(sig_type, substitution)
158
+
159
+ free = constraints
160
+ .map { substitution.apply(it) }
161
+ .select { it.type.is_a?(Type::Var) && !head_vars.include?(it.type.id) }
162
+ .uniq { [it.interface, it.type.id] }
163
+
164
+ free
165
+ .reject { names.key?(it.type.id) }
166
+ .map { unsatisfiable(state, impl_fn, interface_qname, fn_name, it) }
167
+ .then { state.add_errors(it) }
168
+ .require_impl(
169
+ [interface_qname, fn_name],
170
+ free.filter_map { |c| names[c.type.id]&.then { |n| [c.interface, n] } },
171
+ )
172
+ end
173
+
174
+ def signature_names(sig_type, substitution)
175
+ sig_type
176
+ .unbound_vars
177
+ .filter_map do |var|
178
+ substitution
179
+ .apply(var)
180
+ .then { it.is_a?(Type::Var) ? [it.id, var.name] : nil }
181
+ end
182
+ .to_h
183
+ end
184
+
185
+ def unsatisfiable(state, impl_fn, interface_qname, fn_name, constraint)
186
+ Error::ImplementationFunctionConstraint.new(
187
+ state.env.entry_name,
188
+ impl_fn.range,
189
+ interface: interface_qname,
190
+ fn_name:,
191
+ constraint: constraint.to_s,
192
+ )
193
+ end
194
+
118
195
  def constructor_var_in?(type, var_id)
119
196
  case type
120
197
  in Type::Application(constructor: Type::Var(id:)) if id == var_id
@@ -13,6 +13,7 @@ module Jade
13
13
  .env
14
14
  .lookup(symbol.qualified_name)
15
15
  .then { it.attach_origin(node) }
16
+ .then { state.skip_constraints ? it : attach_markers(it) }
16
17
  .then { state.unify_result(it, expected.type) }
17
18
  end
18
19
  end
@@ -28,7 +28,14 @@ module Jade
28
28
  )
29
29
  end
30
30
 
31
- after_state.unify_result(result, expected.type)
31
+ after_state.unify_result(result, expected.type) do
32
+ Error::RecordUpdateTypeMismatch.new(
33
+ state.env.entry_name,
34
+ node.range,
35
+ expected: it.expected,
36
+ actual: it.actual,
37
+ )
38
+ end
32
39
  end
33
40
  end
34
41
  end
@@ -17,6 +17,7 @@ module Jade
17
17
  end
18
18
  .then { state.env.lookup(it) }
19
19
  .then { it.attach_origin(node) }
20
+ .then { state.skip_constraints ? it : attach_markers(it) }
20
21
  .then { [state, it] }
21
22
  end
22
23
  end
@@ -0,0 +1,115 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Requirements
5
+ extend self
6
+
7
+ def reconcile(entry, registry, state)
8
+ pending = state
9
+ .impl_requirements
10
+ .to_h { |key, pairs| [key, pairs - declared_for(key, registry)] }
11
+ .reject { |_, pairs| pairs.empty? }
12
+
13
+ errors(entry, registry, pending)
14
+ .then { return [entry, state.add_errors(it)] if it.any? }
15
+
16
+ amended = amend_all(entry, pending)
17
+ return [entry, state] if amended.equal?(entry)
18
+
19
+ rebind(state.env, amended, registry)
20
+ .then { recheck(entry, registry, it) }
21
+ .then { |rechecked| [amended, rechecked] }
22
+ end
23
+
24
+ private
25
+
26
+ def recheck(entry, registry, env)
27
+ TypeChecking
28
+ .check_node(entry.ast, registry, State.init(env), Expected.infer(env.fresh))
29
+ .first
30
+ end
31
+
32
+ def rebind(env, entry, registry)
33
+ entry
34
+ .defined_values
35
+ .each_value
36
+ .select { it.is_a?(Symbol::InterfaceFunction) && it.constraints.any? }
37
+ .reduce(env) do |acc, sym|
38
+ Type
39
+ .from_symbol(sym, registry, acc.var_gen)
40
+ .then { Inference::Helpers.generalize(acc, *it) }
41
+ .then { acc.bind(sym.qualified_name, it) }
42
+ end
43
+ end
44
+
45
+ def declared_for((interface, fn_name), registry)
46
+ Symbol
47
+ .type_ref_from_qualified_name(interface)
48
+ .then { registry.lookup(it) }
49
+ .then { it.is_a?(Symbol::Interface) ? it.functions : [] }
50
+ .find { it.name == fn_name }
51
+ &.constraints || []
52
+ end
53
+
54
+ def errors(entry, registry, pending)
55
+ pending.flat_map do |(interface, fn_name), constraints|
56
+ declared = declared_for([interface, fn_name], registry)
57
+ next [] if declared.empty? && local?(entry, interface)
58
+
59
+ constraints.map do |iface, var|
60
+ error_for(entry, interface, fn_name, "#{iface} #{var}", declared)
61
+ end
62
+ end
63
+ end
64
+
65
+ def local?(entry, interface)
66
+ entry.defined_types.key?(interface.split('.').last)
67
+ end
68
+
69
+ def error_for(entry, interface, fn_name, constraint, declared)
70
+ return cross_module_error(entry, interface, fn_name, constraint) if declared.empty?
71
+
72
+ Error::UndeclaredRequirement.new(
73
+ entry.name,
74
+ nil,
75
+ interface:,
76
+ fn_name:,
77
+ constraint:,
78
+ declared: declared.map { |iface, var| "#{iface} #{var}" }.join(', '),
79
+ )
80
+ end
81
+
82
+ def cross_module_error(entry, interface, fn_name, constraint)
83
+ Error::CrossModuleRequirement.new(
84
+ entry.name,
85
+ nil,
86
+ interface:,
87
+ fn_name:,
88
+ constraint:,
89
+ )
90
+ end
91
+
92
+ def amend_all(entry, pending)
93
+ pending.reduce(entry) do |acc, ((interface, fn_name), constraints)|
94
+ amend_method(acc, interface, fn_name, constraints)
95
+ end
96
+ end
97
+
98
+ def amend_method(entry, interface_qname, fn_name, constraints)
99
+ symbol = entry.defined_types[interface_qname.split('.').last]
100
+ return entry unless symbol.is_a?(Symbol::Interface)
101
+
102
+ symbol
103
+ .functions
104
+ .map { it.name == fn_name ? with_constraints(it, constraints) : it }
105
+ .then { symbol.with(functions: it) }
106
+ .then { |iface| iface.functions.reduce(entry.define(iface)) { |acc, fn| acc.define(fn) } }
107
+ end
108
+
109
+ def with_constraints(fn, constraints)
110
+ fn.with(constraints: (fn.constraints + constraints).uniq)
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -1,9 +1,17 @@
1
1
  module Jade
2
2
  module Frontend
3
3
  module TypeChecking
4
- State = Data.define(:env, :errors, :skip_constraints) do
4
+ State = Data.define(:env, :errors, :skip_constraints, :impl_requirements) do
5
5
  def self.init(env, skip_constraints: false)
6
- new(env, [], skip_constraints)
6
+ new(env, [], skip_constraints, {})
7
+ end
8
+
9
+ def require_impl(key, constraints)
10
+ return self if constraints.empty?
11
+
12
+ impl_requirements
13
+ .merge(key => constraints) { |_, old, new| (old + new).uniq }
14
+ .then { with(impl_requirements: it) }
7
15
  end
8
16
 
9
17
  def unify_result(result, right, rigid_vars = [], &block)
@@ -8,6 +8,7 @@ require 'jade/frontend/type_checking/expected'
8
8
  require 'jade/frontend/type_checking/inference'
9
9
  require 'jade/frontend/type_checking/loader'
10
10
  require 'jade/frontend/type_checking/port_resolution'
11
+ require 'jade/frontend/type_checking/requirements'
11
12
  require 'jade/frontend/type_checking/result'
12
13
  require 'jade/frontend/type_checking/state'
13
14
  require 'jade/frontend/type_checking/substitution'
@@ -26,11 +27,16 @@ module Jade
26
27
  .load(entry, registry)
27
28
  .then { collect_constraints(entry, registry, it) }
28
29
  .then { check_node(entry.ast, registry, State.init(it), Expected.infer(it.fresh)) }
29
- .then { finalize(*it, registry) }
30
+ .then { |state, _| Requirements.reconcile(entry, registry, state) }
31
+ .then { |amended, state| complete(amended, state, registry) }
32
+ .and_then { PortResolution.resolve(it, registry) }
33
+ end
34
+
35
+ def complete(entry, state, registry)
36
+ finalize(state, registry)
30
37
  .map { Canonicalize.run(entry.ast, it, registry) }
31
38
  .map { it.canonicalize_node_types }
32
39
  .map { entry.with(env: it) }
33
- .and_then { PortResolution.resolve(it, registry) }
34
40
  end
35
41
 
36
42
  # A collecting pass walks declarations in source order, so a call to a
@@ -76,7 +82,7 @@ module Jade
76
82
  .then { it + 1 }
77
83
  end
78
84
 
79
- def finalize(state, result, registry)
85
+ def finalize(state, registry)
80
86
  state.env => { bindings:, entry_name: }
81
87
 
82
88
  errors = bindings
@@ -10,7 +10,7 @@ module Jade
10
10
  }
11
11
 
12
12
  parser(:type_atom) {
13
- type_application | type_var | type_tuple | grouped(lazy { type_function })
13
+ type_application | type_var | type_tuple | grouped(lazy { type_expression })
14
14
  }
15
15
 
16
16
  parser(:type_tuple) {
data/lib/jade/parsing.rb CHANGED
@@ -753,10 +753,23 @@ module Jade
753
753
  }
754
754
 
755
755
  parser(:interface_function_decl) {
756
+ constraint =
757
+ (
758
+ constant >>
759
+ type(:lparen).skip >>
760
+ type_param >>
761
+ type(:rparen).skip
762
+ ).map(&AST.interface_constraint)
763
+
764
+ constraints =
765
+ type(:with).skip >>
766
+ at_least_one(constraint, separated_by: type(:comma).skip)
767
+
756
768
  (
757
769
  (type(:identifier) | (type(:lparen).skip >> operator >> type(:rparen).skip)) >>
758
770
  type(:colon).skip >>
759
- type_expression
771
+ type_expression >>
772
+ optional(constraints, default: []).map { [it] }
760
773
  ).map(&AST.interface_function_decl)
761
774
  }
762
775
 
@@ -268,6 +268,17 @@ module Jade
268
268
 
269
269
  # Constrained helpers — pick the decoder via Decodable.
270
270
 
271
+ function(
272
+ 'decoder',
273
+ {},
274
+ 'Decoder(a)',
275
+ constraints: [['Decode.Decodable', 'a']],
276
+ body: Symbol::DerivedFunction.new(
277
+ params: [],
278
+ body: [:impl_arg, 0, 'decoder'],
279
+ ),
280
+ )
281
+
271
282
  function(
272
283
  'from_value',
273
284
  { value: 'Value' },
@@ -6,7 +6,8 @@ module Jade
6
6
  :interface,
7
7
  :params,
8
8
  :return_type,
9
- :decl_span
9
+ :decl_span,
10
+ :constraints
10
11
  ) do
11
12
  include Base
12
13
 
@@ -8,7 +8,7 @@ module Jade
8
8
  end
9
9
 
10
10
  def constant?
11
- params.empty? && constraints.empty?
11
+ params.empty?
12
12
  end
13
13
  end
14
14
  end
data/lib/jade/symbol.rb CHANGED
@@ -134,8 +134,8 @@ module Jade
134
134
  Interface[nil, name, type_var, functions, default, span]
135
135
  end
136
136
 
137
- def interface_function(name, inteface, params, return_type, span)
138
- InterfaceFunction[nil, name, inteface, params, return_type, span]
137
+ def interface_function(name, inteface, params, return_type, span, constraints = [])
138
+ InterfaceFunction[nil, name, inteface, params, return_type, span, constraints]
139
139
  end
140
140
 
141
141
  def implementation(
@@ -1,27 +1,26 @@
1
1
  module Jade
2
2
  module Type
3
- Function = Data.define(:args, :return_type, :display) do
3
+ Function = Data.define(:args, :return_type) do
4
4
  include Base
5
- include Displayable
6
5
 
7
- def initialize(args:, return_type:, display: nil)
8
- super
9
- end
10
-
11
- def identity
12
- [args, return_type]
13
- end
6
+ # `Int, Int -> Int`, the spelling the formatter writes. Parentheses
7
+ # around a comma list are a tuple, so a nested function keeps its own.
8
+ def to_s
9
+ params = args.empty? ? '()' : args.map { delimited(it) }.join(', ')
14
10
 
15
- def render
16
- args
17
- .map(&:to_s).join(', ')
18
- .then { "(#{it})"} + " -> " + return_type.to_s
11
+ "#{params} -> #{delimited(return_type)}"
19
12
  end
20
13
 
21
14
  def unbound_vars
22
15
  (args.flat_map(&:unbound_vars) + return_type.unbound_vars)
23
16
  .to_set.to_a
24
17
  end
18
+
19
+ private
20
+
21
+ def delimited(type)
22
+ type.is_a?(Function) ? "(#{type})" : type.to_s
23
+ end
25
24
  end
26
25
  end
27
26
  end
data/lib/jade/type.rb CHANGED
@@ -178,9 +178,18 @@ module Jade
178
178
  constraint = Type
179
179
  .constraint(symbol.interface.qualified_name, param_type, nil)
180
180
 
181
- from_symbol_r(symbol.return_type, registry, var_gen, local_map)
182
- .then { |(t, c, _)| [args.empty? ? t : Type.function(args, t), c + arg_cs + [constraint]] }
183
- .then { it + [var_map] }
181
+ ret_type, ret_cs, full_map =
182
+ from_symbol_r(symbol.return_type, registry, var_gen, local_map)
183
+
184
+ extra_cs = symbol.constraints.map { |iface, var_name|
185
+ Type.constraint(iface, full_map.fetch(var_name), nil)
186
+ }
187
+
188
+ [
189
+ args.empty? ? ret_type : Type.function(args, ret_type),
190
+ ret_cs + arg_cs + [constraint] + extra_cs,
191
+ var_map,
192
+ ]
184
193
 
185
194
  in Symbol::Constructor if symbol.args.empty?
186
195
  from_symbol_r(symbol.parent, registry, var_gen, var_map)
data/lib/jade/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Jade
2
- VERSION = '0.10.0'
2
+ VERSION = '0.11.0'
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jade-lang
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Agustin Cornu
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-09-03 00:00:00.000000000 Z
10
+ date: 2026-09-15 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -57,6 +57,7 @@ files:
57
57
  - lib/jade/cli/check.rb
58
58
  - lib/jade/cli/eject.rb
59
59
  - lib/jade/cli/fmt.rb
60
+ - lib/jade/cli/init.rb
60
61
  - lib/jade/cli/lsp.rb
61
62
  - lib/jade/cli/q.rb
62
63
  - lib/jade/clock/runtime.rb
@@ -248,6 +249,7 @@ files:
248
249
  - lib/jade/frontend/type_checking/env.rb
249
250
  - lib/jade/frontend/type_checking/error.rb
250
251
  - lib/jade/frontend/type_checking/error/case_of_branches_type_mismatch.rb
252
+ - lib/jade/frontend/type_checking/error/cross_module_requirement.rb
251
253
  - lib/jade/frontend/type_checking/error/derivation_failed.rb
252
254
  - lib/jade/frontend/type_checking/error/display.rb
253
255
  - lib/jade/frontend/type_checking/error/division_by_zero.rb
@@ -257,6 +259,7 @@ files:
257
259
  - lib/jade/frontend/type_checking/error/if_branch_type_mismatch.rb
258
260
  - lib/jade/frontend/type_checking/error/if_branches_type_mismatch.rb
259
261
  - lib/jade/frontend/type_checking/error/if_condition_type_mismatch.rb
262
+ - lib/jade/frontend/type_checking/error/implementation_function_constraint.rb
260
263
  - lib/jade/frontend/type_checking/error/implementation_type_mismatch.rb
261
264
  - lib/jade/frontend/type_checking/error/list_item_type_mismatch.rb
262
265
  - lib/jade/frontend/type_checking/error/missing_implementation.rb
@@ -266,8 +269,10 @@ files:
266
269
  - lib/jade/frontend/type_checking/error/port_not_encodable.rb
267
270
  - lib/jade/frontend/type_checking/error/range_pattern_type.rb
268
271
  - lib/jade/frontend/type_checking/error/record_access_type_mismatch.rb
272
+ - lib/jade/frontend/type_checking/error/record_update_type_mismatch.rb
269
273
  - lib/jade/frontend/type_checking/error/recursive_derivation.rb
270
274
  - lib/jade/frontend/type_checking/error/type_mismatch.rb
275
+ - lib/jade/frontend/type_checking/error/undeclared_requirement.rb
271
276
  - lib/jade/frontend/type_checking/error/unreachable_branch.rb
272
277
  - lib/jade/frontend/type_checking/error/unresolved_constraint.rb
273
278
  - lib/jade/frontend/type_checking/expected.rb
@@ -306,6 +311,7 @@ files:
306
311
  - lib/jade/frontend/type_checking/loader.rb
307
312
  - lib/jade/frontend/type_checking/placeholder.rb
308
313
  - lib/jade/frontend/type_checking/port_resolution.rb
314
+ - lib/jade/frontend/type_checking/requirements.rb
309
315
  - lib/jade/frontend/type_checking/result.rb
310
316
  - lib/jade/frontend/type_checking/scheme.rb
311
317
  - lib/jade/frontend/type_checking/state.rb