jade-lang 0.1.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 (326) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +23 -0
  3. data/LICENSE +21 -0
  4. data/README.md +386 -0
  5. data/exe/jade +6 -0
  6. data/lib/jade/ast/node.rb +44 -0
  7. data/lib/jade/ast/nodes.rb +35 -0
  8. data/lib/jade/ast/pretty_printer.rb +50 -0
  9. data/lib/jade/ast.rb +723 -0
  10. data/lib/jade/calendar/runtime.rb +15 -0
  11. data/lib/jade/cli/fmt.rb +96 -0
  12. data/lib/jade/cli/lsp.rb +13 -0
  13. data/lib/jade/cli/q.rb +113 -0
  14. data/lib/jade/cli.rb +43 -0
  15. data/lib/jade/clock/runtime.rb +13 -0
  16. data/lib/jade/codegen/boundary/cache.rb +94 -0
  17. data/lib/jade/codegen/boundary/specialized/list.rb +65 -0
  18. data/lib/jade/codegen/boundary/specialized/maybe.rb +40 -0
  19. data/lib/jade/codegen/boundary/specialized/record.rb +165 -0
  20. data/lib/jade/codegen/boundary/specialized/scalar.rb +67 -0
  21. data/lib/jade/codegen/boundary/specialized.rb +106 -0
  22. data/lib/jade/codegen/boundary.rb +189 -0
  23. data/lib/jade/codegen/constructor_reference.rb +18 -0
  24. data/lib/jade/codegen/context.rb +96 -0
  25. data/lib/jade/codegen/emitter.rb +81 -0
  26. data/lib/jade/codegen/function_call.rb +367 -0
  27. data/lib/jade/codegen/function_declaration.rb +199 -0
  28. data/lib/jade/codegen/helpers.rb +103 -0
  29. data/lib/jade/codegen/implementation.rb +178 -0
  30. data/lib/jade/codegen/inline.rb +89 -0
  31. data/lib/jade/codegen/inlines.rb +326 -0
  32. data/lib/jade/codegen/method_names.rb +54 -0
  33. data/lib/jade/codegen/pattern/constructor.rb +57 -0
  34. data/lib/jade/codegen/port_decoder.rb +77 -0
  35. data/lib/jade/codegen/pretty.rb +53 -0
  36. data/lib/jade/codegen/transforms/fold_shape.rb +222 -0
  37. data/lib/jade/codegen/transforms/self_call.rb +80 -0
  38. data/lib/jade/codegen/transforms/tail_call.rb +120 -0
  39. data/lib/jade/codegen/variant_declaration.rb +41 -0
  40. data/lib/jade/codegen.rb +400 -0
  41. data/lib/jade/compiler.rb +69 -0
  42. data/lib/jade/decode.rb +320 -0
  43. data/lib/jade/diagnostics/renderer.rb +121 -0
  44. data/lib/jade/diagnostics.rb +77 -0
  45. data/lib/jade/did_you_mean.rb +16 -0
  46. data/lib/jade/entry.rb +177 -0
  47. data/lib/jade/error.rb +72 -0
  48. data/lib/jade/formatter/accesses.rb +37 -0
  49. data/lib/jade/formatter/bindings.rb +29 -0
  50. data/lib/jade/formatter/body.rb +50 -0
  51. data/lib/jade/formatter/calls.rb +51 -0
  52. data/lib/jade/formatter/case_of.rb +31 -0
  53. data/lib/jade/formatter/case_of_branch.rb +59 -0
  54. data/lib/jade/formatter/collections.rb +78 -0
  55. data/lib/jade/formatter/declarations.rb +178 -0
  56. data/lib/jade/formatter/exposing.rb +48 -0
  57. data/lib/jade/formatter/function_declaration.rb +72 -0
  58. data/lib/jade/formatter/helper.rb +122 -0
  59. data/lib/jade/formatter/if_then_else.rb +64 -0
  60. data/lib/jade/formatter/infix_application.rb +69 -0
  61. data/lib/jade/formatter/lambda.rb +50 -0
  62. data/lib/jade/formatter/leaves.rb +111 -0
  63. data/lib/jade/formatter/module_node.rb +26 -0
  64. data/lib/jade/formatter/pattern.rb +61 -0
  65. data/lib/jade/formatter/type.rb +67 -0
  66. data/lib/jade/formatter.rb +38 -0
  67. data/lib/jade/frontend/comment_attacher.rb +121 -0
  68. data/lib/jade/frontend/desugaring/placeholder.rb +39 -0
  69. data/lib/jade/frontend/desugaring/resolved.rb +63 -0
  70. data/lib/jade/frontend/desugaring.rb +217 -0
  71. data/lib/jade/frontend/fixity_fixer.rb +209 -0
  72. data/lib/jade/frontend/forward_declaration/body.rb +30 -0
  73. data/lib/jade/frontend/forward_declaration/error/bad_import.rb +19 -0
  74. data/lib/jade/frontend/forward_declaration/error/exposed_type_not_found.rb +18 -0
  75. data/lib/jade/frontend/forward_declaration/error/exposed_value_not_found.rb +18 -0
  76. data/lib/jade/frontend/forward_declaration/error/module_not_found.rb +18 -0
  77. data/lib/jade/frontend/forward_declaration/error/private_type_expansion.rb +19 -0
  78. data/lib/jade/frontend/forward_declaration/error/tuple_arity_overflow.rb +25 -0
  79. data/lib/jade/frontend/forward_declaration/error/type_not_found.rb +29 -0
  80. data/lib/jade/frontend/forward_declaration/error/type_not_lowerable.rb +16 -0
  81. data/lib/jade/frontend/forward_declaration/error/unknown_extends_interface.rb +18 -0
  82. data/lib/jade/frontend/forward_declaration/error.rb +11 -0
  83. data/lib/jade/frontend/forward_declaration/function_declaration.rb +32 -0
  84. data/lib/jade/frontend/forward_declaration/helper.rb +91 -0
  85. data/lib/jade/frontend/forward_declaration/implementation.rb +63 -0
  86. data/lib/jade/frontend/forward_declaration/implementation_function.rb +39 -0
  87. data/lib/jade/frontend/forward_declaration/import_declaration.rb +115 -0
  88. data/lib/jade/frontend/forward_declaration/interface_declaration.rb +66 -0
  89. data/lib/jade/frontend/forward_declaration/interop_import_declaration.rb +99 -0
  90. data/lib/jade/frontend/forward_declaration/module.rb +98 -0
  91. data/lib/jade/frontend/forward_declaration/struct_declaration.rb +42 -0
  92. data/lib/jade/frontend/forward_declaration/type_declaration.rb +42 -0
  93. data/lib/jade/frontend/forward_declaration.rb +71 -0
  94. data/lib/jade/frontend/pattern_analysis/exhaustiveness.rb +65 -0
  95. data/lib/jade/frontend/pattern_analysis/matrix.rb +235 -0
  96. data/lib/jade/frontend/pattern_analysis.rb +40 -0
  97. data/lib/jade/frontend/semantic_analysis/assign.rb +20 -0
  98. data/lib/jade/frontend/semantic_analysis/body.rb +33 -0
  99. data/lib/jade/frontend/semantic_analysis/case_of.rb +19 -0
  100. data/lib/jade/frontend/semantic_analysis/case_of_branch.rb +20 -0
  101. data/lib/jade/frontend/semantic_analysis/char_literal.rb +14 -0
  102. data/lib/jade/frontend/semantic_analysis/constructor_reference.rb +64 -0
  103. data/lib/jade/frontend/semantic_analysis/error/circular_extends.rb +19 -0
  104. data/lib/jade/frontend/semantic_analysis/error/constant_not_callable.rb +24 -0
  105. data/lib/jade/frontend/semantic_analysis/error/constructor_not_found.rb +34 -0
  106. data/lib/jade/frontend/semantic_analysis/error/constructor_pattern_arity_mismatch.rb +24 -0
  107. data/lib/jade/frontend/semantic_analysis/error/duplicate_field.rb +18 -0
  108. data/lib/jade/frontend/semantic_analysis/error/duplicate_function_declaration.rb +25 -0
  109. data/lib/jade/frontend/semantic_analysis/error/duplicate_record_field.rb +19 -0
  110. data/lib/jade/frontend/semantic_analysis/error/invalid_list_rest_pattern.rb +21 -0
  111. data/lib/jade/frontend/semantic_analysis/error/kwargs_on_non_constructor.rb +17 -0
  112. data/lib/jade/frontend/semantic_analysis/error/missing_exposing_clause.rb +17 -0
  113. data/lib/jade/frontend/semantic_analysis/error/missing_extends_implementation.rb +21 -0
  114. data/lib/jade/frontend/semantic_analysis/error/missing_field.rb +20 -0
  115. data/lib/jade/frontend/semantic_analysis/error/missing_implementation_function.rb +19 -0
  116. data/lib/jade/frontend/semantic_analysis/error/module_not_found.rb +22 -0
  117. data/lib/jade/frontend/semantic_analysis/error/nested_task_port.rb +19 -0
  118. data/lib/jade/frontend/semantic_analysis/error/non_task_port.rb +22 -0
  119. data/lib/jade/frontend/semantic_analysis/error/orphan_implementation.rb +20 -0
  120. data/lib/jade/frontend/semantic_analysis/error/predicate_must_return_bool.rb +22 -0
  121. data/lib/jade/frontend/semantic_analysis/error/predicate_name_not_allowed.rb +25 -0
  122. data/lib/jade/frontend/semantic_analysis/error/shadowing_error.rb +22 -0
  123. data/lib/jade/frontend/semantic_analysis/error/type_args_mismatch.rb +25 -0
  124. data/lib/jade/frontend/semantic_analysis/error/type_param_required.rb +19 -0
  125. data/lib/jade/frontend/semantic_analysis/error/unbound_type_variable.rb +22 -0
  126. data/lib/jade/frontend/semantic_analysis/error/undefined_variable.rb +29 -0
  127. data/lib/jade/frontend/semantic_analysis/error/unknown_field.rb +20 -0
  128. data/lib/jade/frontend/semantic_analysis/error/unknown_implementation_function.rb +19 -0
  129. data/lib/jade/frontend/semantic_analysis/error/unused_interface_type_param.rb +24 -0
  130. data/lib/jade/frontend/semantic_analysis/error/value_not_exposed.rb +23 -0
  131. data/lib/jade/frontend/semantic_analysis/error/variable_not_found.rb +25 -0
  132. data/lib/jade/frontend/semantic_analysis/error.rb +40 -0
  133. data/lib/jade/frontend/semantic_analysis/function_call.rb +60 -0
  134. data/lib/jade/frontend/semantic_analysis/function_declaration.rb +58 -0
  135. data/lib/jade/frontend/semantic_analysis/grouping.rb +17 -0
  136. data/lib/jade/frontend/semantic_analysis/helper.rb +152 -0
  137. data/lib/jade/frontend/semantic_analysis/if_then_else.rb +20 -0
  138. data/lib/jade/frontend/semantic_analysis/implementation.rb +143 -0
  139. data/lib/jade/frontend/semantic_analysis/implementation_function.rb +16 -0
  140. data/lib/jade/frontend/semantic_analysis/import_declaration.rb +14 -0
  141. data/lib/jade/frontend/semantic_analysis/interface_declaration.rb +45 -0
  142. data/lib/jade/frontend/semantic_analysis/interop_import_declaration.rb +69 -0
  143. data/lib/jade/frontend/semantic_analysis/keyed_call/validation.rb +109 -0
  144. data/lib/jade/frontend/semantic_analysis/keyed_call.rb +88 -0
  145. data/lib/jade/frontend/semantic_analysis/lambda.rb +23 -0
  146. data/lib/jade/frontend/semantic_analysis/list.rb +17 -0
  147. data/lib/jade/frontend/semantic_analysis/literal.rb +23 -0
  148. data/lib/jade/frontend/semantic_analysis/member_access.rb +87 -0
  149. data/lib/jade/frontend/semantic_analysis/module_node.rb +27 -0
  150. data/lib/jade/frontend/semantic_analysis/pattern_binding.rb +27 -0
  151. data/lib/jade/frontend/semantic_analysis/pattern_constructor.rb +47 -0
  152. data/lib/jade/frontend/semantic_analysis/pattern_list.rb +33 -0
  153. data/lib/jade/frontend/semantic_analysis/pattern_literal.rb +17 -0
  154. data/lib/jade/frontend/semantic_analysis/pattern_record.rb +25 -0
  155. data/lib/jade/frontend/semantic_analysis/pattern_wildcard.rb +14 -0
  156. data/lib/jade/frontend/semantic_analysis/qualified_access.rb +14 -0
  157. data/lib/jade/frontend/semantic_analysis/record_access.rb +14 -0
  158. data/lib/jade/frontend/semantic_analysis/record_field.rb +17 -0
  159. data/lib/jade/frontend/semantic_analysis/record_literal.rb +21 -0
  160. data/lib/jade/frontend/semantic_analysis/record_update.rb +21 -0
  161. data/lib/jade/frontend/semantic_analysis/struct_declaration.rb +44 -0
  162. data/lib/jade/frontend/semantic_analysis/tuple.rb +17 -0
  163. data/lib/jade/frontend/semantic_analysis/type_declaration.rb +69 -0
  164. data/lib/jade/frontend/semantic_analysis/variable_reference.rb +27 -0
  165. data/lib/jade/frontend/semantic_analysis/variant_declaration.rb +18 -0
  166. data/lib/jade/frontend/semantic_analysis.rb +161 -0
  167. data/lib/jade/frontend/type_checking/canonicalize.rb +97 -0
  168. data/lib/jade/frontend/type_checking/constraints/deriving/decodable.rb +144 -0
  169. data/lib/jade/frontend/type_checking/constraints/deriving/encodable.rb +144 -0
  170. data/lib/jade/frontend/type_checking/constraints/deriving/eq.rb +265 -0
  171. data/lib/jade/frontend/type_checking/constraints/deriving/helpers.rb +59 -0
  172. data/lib/jade/frontend/type_checking/constraints/deriving.rb +28 -0
  173. data/lib/jade/frontend/type_checking/constraints.rb +101 -0
  174. data/lib/jade/frontend/type_checking/definition.rb +71 -0
  175. data/lib/jade/frontend/type_checking/env.rb +79 -0
  176. data/lib/jade/frontend/type_checking/error/case_of_branches_type_mismatch.rb +19 -0
  177. data/lib/jade/frontend/type_checking/error/derivation_failed.rb +21 -0
  178. data/lib/jade/frontend/type_checking/error/function_body_type_mismatch.rb +23 -0
  179. data/lib/jade/frontend/type_checking/error/function_call_type_mismatch.rb +37 -0
  180. data/lib/jade/frontend/type_checking/error/if_branch_type_mismatch.rb +19 -0
  181. data/lib/jade/frontend/type_checking/error/if_branches_type_mismatch.rb +18 -0
  182. data/lib/jade/frontend/type_checking/error/if_condition_type_mismatch.rb +17 -0
  183. data/lib/jade/frontend/type_checking/error/implementation_type_mismatch.rb +20 -0
  184. data/lib/jade/frontend/type_checking/error/list_item_type_mismatch.rb +19 -0
  185. data/lib/jade/frontend/type_checking/error/missing_implementation.rb +20 -0
  186. data/lib/jade/frontend/type_checking/error/missing_patterns.rb +26 -0
  187. data/lib/jade/frontend/type_checking/error/pattern_type_mismatch.rb +13 -0
  188. data/lib/jade/frontend/type_checking/error/port_not_decodable.rb +38 -0
  189. data/lib/jade/frontend/type_checking/error/record_access_type_mismatch.rb +14 -0
  190. data/lib/jade/frontend/type_checking/error/type_mismatch.rb +23 -0
  191. data/lib/jade/frontend/type_checking/error/unresolved_constraint.rb +20 -0
  192. data/lib/jade/frontend/type_checking/error.rb +18 -0
  193. data/lib/jade/frontend/type_checking/expected.rb +23 -0
  194. data/lib/jade/frontend/type_checking/generalization.rb +17 -0
  195. data/lib/jade/frontend/type_checking/generalizer.rb +38 -0
  196. data/lib/jade/frontend/type_checking/inference/assign.rb +58 -0
  197. data/lib/jade/frontend/type_checking/inference/body.rb +45 -0
  198. data/lib/jade/frontend/type_checking/inference/case_of.rb +102 -0
  199. data/lib/jade/frontend/type_checking/inference/constructor_reference.rb +21 -0
  200. data/lib/jade/frontend/type_checking/inference/function_call.rb +132 -0
  201. data/lib/jade/frontend/type_checking/inference/function_declaration.rb +70 -0
  202. data/lib/jade/frontend/type_checking/inference/grouping.rb +18 -0
  203. data/lib/jade/frontend/type_checking/inference/helpers.rb +34 -0
  204. data/lib/jade/frontend/type_checking/inference/if_then_else.rb +46 -0
  205. data/lib/jade/frontend/type_checking/inference/implementation.rb +150 -0
  206. data/lib/jade/frontend/type_checking/inference/import_declaration.rb +19 -0
  207. data/lib/jade/frontend/type_checking/inference/interface_declaration.rb +18 -0
  208. data/lib/jade/frontend/type_checking/inference/interop_import_declaration.rb +18 -0
  209. data/lib/jade/frontend/type_checking/inference/lambda.rb +87 -0
  210. data/lib/jade/frontend/type_checking/inference/list.rb +52 -0
  211. data/lib/jade/frontend/type_checking/inference/literal.rb +24 -0
  212. data/lib/jade/frontend/type_checking/inference/module.rb +18 -0
  213. data/lib/jade/frontend/type_checking/inference/pattern.rb +135 -0
  214. data/lib/jade/frontend/type_checking/inference/qualified_access.rb +23 -0
  215. data/lib/jade/frontend/type_checking/inference/record_access.rb +35 -0
  216. data/lib/jade/frontend/type_checking/inference/record_field.rb +19 -0
  217. data/lib/jade/frontend/type_checking/inference/record_literal.rb +24 -0
  218. data/lib/jade/frontend/type_checking/inference/record_update.rb +37 -0
  219. data/lib/jade/frontend/type_checking/inference/struct_declaration.rb +18 -0
  220. data/lib/jade/frontend/type_checking/inference/type_declaration.rb +18 -0
  221. data/lib/jade/frontend/type_checking/inference/variable_reference.rb +27 -0
  222. data/lib/jade/frontend/type_checking/inference.rb +27 -0
  223. data/lib/jade/frontend/type_checking/instantiation.rb +24 -0
  224. data/lib/jade/frontend/type_checking/loader.rb +80 -0
  225. data/lib/jade/frontend/type_checking/placeholder.rb +12 -0
  226. data/lib/jade/frontend/type_checking/port_resolution.rb +123 -0
  227. data/lib/jade/frontend/type_checking/result.rb +41 -0
  228. data/lib/jade/frontend/type_checking/scheme.rb +20 -0
  229. data/lib/jade/frontend/type_checking/state.rb +52 -0
  230. data/lib/jade/frontend/type_checking/substitution.rb +93 -0
  231. data/lib/jade/frontend/type_checking/unification.rb +282 -0
  232. data/lib/jade/frontend/type_checking/var_gen.rb +33 -0
  233. data/lib/jade/frontend/type_checking.rb +129 -0
  234. data/lib/jade/frontend/unused_analysis.rb +41 -0
  235. data/lib/jade/frontend/usage_analysis/reference_index.rb +53 -0
  236. data/lib/jade/frontend/usage_analysis.rb +195 -0
  237. data/lib/jade/frontend.rb +101 -0
  238. data/lib/jade/interop/boundary.rb +68 -0
  239. data/lib/jade/interop/error.rb +84 -0
  240. data/lib/jade/interop/lowering/error.rb +32 -0
  241. data/lib/jade/interop/lowering.rb +53 -0
  242. data/lib/jade/interop/runtime.rb +24 -0
  243. data/lib/jade/interop.rb +1 -0
  244. data/lib/jade/lexer.rb +189 -0
  245. data/lib/jade/lsp/converters.rb +542 -0
  246. data/lib/jade/lsp/handlers.rb +340 -0
  247. data/lib/jade/lsp/server.rb +63 -0
  248. data/lib/jade/lsp/snippets.rb +100 -0
  249. data/lib/jade/lsp/state.rb +25 -0
  250. data/lib/jade/lsp.rb +16 -0
  251. data/lib/jade/module_loader/cache.rb +56 -0
  252. data/lib/jade/module_loader/dependency_graph.rb +23 -0
  253. data/lib/jade/module_loader/dependency_resolver.rb +48 -0
  254. data/lib/jade/module_loader/normalize.rb +34 -0
  255. data/lib/jade/module_loader/topological_sort.rb +41 -0
  256. data/lib/jade/module_loader.rb +127 -0
  257. data/lib/jade/parsing/combinators.rb +291 -0
  258. data/lib/jade/parsing/error.rb +154 -0
  259. data/lib/jade/parsing/token.rb +12 -0
  260. data/lib/jade/parsing/type.rb +92 -0
  261. data/lib/jade/parsing.rb +674 -0
  262. data/lib/jade/port.rb +1 -0
  263. data/lib/jade/registry.rb +79 -0
  264. data/lib/jade/result.rb +121 -0
  265. data/lib/jade/runtime.rb +127 -0
  266. data/lib/jade/source.rb +62 -0
  267. data/lib/jade/stdlib/basics.rb +214 -0
  268. data/lib/jade/stdlib/bytes.rb +70 -0
  269. data/lib/jade/stdlib/calendar.rb +405 -0
  270. data/lib/jade/stdlib/char.rb +27 -0
  271. data/lib/jade/stdlib/clock.rb +342 -0
  272. data/lib/jade/stdlib/compiled.rb +48 -0
  273. data/lib/jade/stdlib/decode/params.rb +154 -0
  274. data/lib/jade/stdlib/decode.rb +315 -0
  275. data/lib/jade/stdlib/dict.rb +134 -0
  276. data/lib/jade/stdlib/encode.rb +143 -0
  277. data/lib/jade/stdlib/intrinsics.rb +280 -0
  278. data/lib/jade/stdlib/list.rb +214 -0
  279. data/lib/jade/stdlib/maybe.rb +73 -0
  280. data/lib/jade/stdlib/result.rb +131 -0
  281. data/lib/jade/stdlib/set.rb +123 -0
  282. data/lib/jade/stdlib/string.rb +65 -0
  283. data/lib/jade/stdlib/task.rb +55 -0
  284. data/lib/jade/stdlib/tuple.rb +21 -0
  285. data/lib/jade/stdlib.rb +112 -0
  286. data/lib/jade/symbol/anonymous_record.rb +7 -0
  287. data/lib/jade/symbol/base.rb +15 -0
  288. data/lib/jade/symbol/constructor.rb +11 -0
  289. data/lib/jade/symbol/derived_function.rb +5 -0
  290. data/lib/jade/symbol/function.rb +15 -0
  291. data/lib/jade/symbol/function_type.rb +7 -0
  292. data/lib/jade/symbol/implementation.rb +17 -0
  293. data/lib/jade/symbol/implementation_template.rb +13 -0
  294. data/lib/jade/symbol/interface.rb +11 -0
  295. data/lib/jade/symbol/interface_function.rb +18 -0
  296. data/lib/jade/symbol/interop_function.rb +22 -0
  297. data/lib/jade/symbol/lambda.rb +7 -0
  298. data/lib/jade/symbol/parser.rb +79 -0
  299. data/lib/jade/symbol/partial_application.rb +7 -0
  300. data/lib/jade/symbol/record_type.rb +8 -0
  301. data/lib/jade/symbol/stdlib_function.rb +15 -0
  302. data/lib/jade/symbol/stdlib_implementation.rb +7 -0
  303. data/lib/jade/symbol/struct.rb +15 -0
  304. data/lib/jade/symbol/type_application.rb +8 -0
  305. data/lib/jade/symbol/type_ref.rb +11 -0
  306. data/lib/jade/symbol/union.rb +15 -0
  307. data/lib/jade/symbol/value_ref.rb +15 -0
  308. data/lib/jade/symbol/variable.rb +7 -0
  309. data/lib/jade/symbol/variant.rb +11 -0
  310. data/lib/jade/symbol.rb +162 -0
  311. data/lib/jade/task.rb +103 -0
  312. data/lib/jade/tasks/rspec.rb +266 -0
  313. data/lib/jade/tasks.rb +70 -0
  314. data/lib/jade/type/anonymous_record.rb +33 -0
  315. data/lib/jade/type/application.rb +21 -0
  316. data/lib/jade/type/base.rb +9 -0
  317. data/lib/jade/type/constraint.rb +17 -0
  318. data/lib/jade/type/constructor.rb +19 -0
  319. data/lib/jade/type/function.rb +18 -0
  320. data/lib/jade/type/partial_application.rb +17 -0
  321. data/lib/jade/type/unit.rb +15 -0
  322. data/lib/jade/type/var.rb +21 -0
  323. data/lib/jade/type.rb +259 -0
  324. data/lib/jade/version.rb +3 -0
  325. data/lib/jade.rb +55 -0
  326. metadata +387 -0
@@ -0,0 +1,102 @@
1
+ require 'jade/frontend/pattern_analysis'
2
+
3
+ module Jade
4
+ module Frontend
5
+ module TypeChecking
6
+ module Inference
7
+ module CaseOf
8
+ extend Helpers
9
+ extend self
10
+
11
+ def infer(node, registry, state, expected)
12
+ node => AST::CaseOf(expression:, branches:)
13
+
14
+ new_state, expr_result = check(
15
+ expression,
16
+ registry,
17
+ state,
18
+ Expected.infer(state.fresh),
19
+ )
20
+
21
+ first_branch, *rest_branches = branches
22
+ after_first_state, first_result = infer_branch(
23
+ first_branch,
24
+ registry,
25
+ new_state,
26
+ expected,
27
+ expr_result,
28
+ )
29
+
30
+ seed = [
31
+ after_first_state,
32
+ expr_result.constraints + first_result.constraints
33
+ ]
34
+
35
+ rest_branches
36
+ .each_with_index
37
+ .reduce(seed) do |(acc, cs), (branch, i)|
38
+ unify_branch(
39
+ branch,
40
+ i,
41
+ acc,
42
+ first_result,
43
+ cs,
44
+ registry,
45
+ expected,
46
+ expr_result,
47
+ )
48
+ end
49
+ .then { |st, cs| [check_exhaustiveness(node, st, registry, expr_result), cs] }
50
+ .then do |st, cs|
51
+ first_result
52
+ .with(constraints: cs)
53
+ .apply(st.env.substitution)
54
+ .then { |result| [st, result] }
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def unify_branch(branch, i, state, first_result, cs, registry, expected, expr_result)
61
+ new_state, body = infer_branch(branch, registry, state, expected, expr_result)
62
+
63
+ new_state
64
+ .unify(body.type, first_result.type) { branch_mismatch(new_state, branch, it, i) }
65
+ .then { [it, cs + body.constraints] }
66
+ end
67
+
68
+ def branch_mismatch(state, branch, error, index)
69
+ Error::CaseOfBranchesTypeMismatch.new(
70
+ state.env.entry_name,
71
+ branch.range,
72
+ actual: error.actual,
73
+ expected: error.expected,
74
+ actual_index: index + 2,
75
+ )
76
+ end
77
+
78
+ def check_exhaustiveness(node, state, registry, result)
79
+ node => AST::CaseOf(branches:)
80
+
81
+ patterns = branches.map(&:pattern)
82
+ type = result.apply(state.env.substitution).type
83
+
84
+ PatternAnalysis::Exhaustiveness
85
+ .assert(patterns, node.range, state.env, registry, type)
86
+ .then { state.add_errors(it) }
87
+ end
88
+
89
+ def infer_branch(node, registry, env, expected, expression_result)
90
+ node => AST::CaseOfBranch(pattern:, body:)
91
+
92
+ pattern_state, _pattern_result = Pattern.infer(
93
+ pattern, registry, env, Expected.infer(expression_result.type)
94
+ )
95
+
96
+ check(body, registry, pattern_state, expected)
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,21 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module ConstructorReference
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, registry, state, expected)
10
+ node => AST::ConstructorReference(symbol:)
11
+
12
+ state
13
+ .env
14
+ .lookup(symbol.qualified_name)
15
+ .then { state.unify_result(it, expected.type) }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,132 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module FunctionCall
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, registry, state, expected)
10
+ node => AST::FunctionCall(callee:, args:)
11
+
12
+ callee_state, callee_result = check(
13
+ callee,
14
+ registry,
15
+ state,
16
+ Expected.infer(state.fresh),
17
+ )
18
+ .then { |st, rs| [st, rs.attach_origin(node)] }
19
+
20
+ args_state, args_acc = args
21
+ .reduce([callee_state, Result.accumulator]) do |(state_acc, acc), arg|
22
+ check(
23
+ arg,
24
+ registry,
25
+ state_acc,
26
+ Expected.infer(state_acc.fresh),
27
+ )
28
+ .then { |(new_state, result)| [new_state, acc.add(result)] }
29
+ end
30
+
31
+ after_callee_state, result_type = unify_callee(
32
+ args_state,
33
+ callee_result,
34
+ args_acc,
35
+ node,
36
+ state,
37
+ )
38
+
39
+ after_callee_state.unify_result(
40
+ callee_result.map { result_type },
41
+ expected.type,
42
+ &type_error(state, node)
43
+ )
44
+ .then do |st, rs|
45
+ # When expected is authoritative and this unification failed,
46
+ # adopt expected.type so the enclosing body-level unify doesn't
47
+ # re-report the same mismatch.
48
+ adopted = expected.check? && st.errors.size > after_callee_state.errors.size
49
+ base_rs = adopted ? rs.with(type: expected.type) : rs
50
+
51
+ callee_subst = base_rs
52
+ .constraints
53
+ .map { st.env.substitution.apply(it) }
54
+
55
+ args_subst = args_acc
56
+ .constraints
57
+ .map { st.env.substitution.apply(it) }
58
+
59
+ propagated = (callee_subst + args_subst)
60
+ .select { it.type.is_a?(Type::Var) }
61
+
62
+ # Pass 1 still needs propagation so constraints from inner calls
63
+ # bubble up through outer constructor calls and reach the function
64
+ # binding before generalization. Skip only the mutating dictionary
65
+ # attachment, which would otherwise emit double dispatch code.
66
+ next [st, base_rs.with(constraints: propagated)] if st.skip_constraints
67
+
68
+ # Attach a resolution per callee constraint, in callee order, so codegen
69
+ # can pass dicts positionally. Concrete constraints attach a resolved
70
+ # Implementation; var-typed ones attach themselves as a marker meaning
71
+ # "use the enclosing function's local dict".
72
+ callee_errors = callee_subst
73
+ .flat_map do |c|
74
+ case c.type
75
+ in Type::Var
76
+ Constraints.attach_dictionary(c, c)
77
+ []
78
+ else
79
+ Constraints.solve_at_call_site(c, registry, st.env.entry_name)
80
+ end
81
+ end
82
+
83
+ # Args' constraints dispatch at their own origins (inner call sites,
84
+ # or a QualifiedAccess/VariableReference when a polymorphic fn is
85
+ # passed as a value). Var-typed ones attach themselves as a marker,
86
+ # mirroring the callee path, so reference-as-value codegen can
87
+ # resolve via the enclosing function's dict_env.
88
+ args_errors = args_subst
89
+ .flat_map do |c|
90
+ case c.type
91
+ in Type::Var
92
+ Constraints.attach_dictionary(c, c)
93
+ []
94
+ else
95
+ Constraints.solve_at_call_site(c, registry, st.env.entry_name)
96
+ end
97
+ end
98
+
99
+ st
100
+ .add_errors(callee_errors + args_errors)
101
+ .then { [it, base_rs.with(constraints: propagated)] }
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def unify_callee(state, callee_result, args_acc, node, outer)
108
+ return_type = state.fresh
109
+ fn_type = Type.function(args_acc.types, return_type)
110
+
111
+ state
112
+ .unify_result(Result.init(fn_type), callee_result.type, &type_error(outer, node))
113
+ .first
114
+ .then { [it, return_type] }
115
+ end
116
+
117
+ def type_error(state, node)
118
+ ->(e) do
119
+ Error::FunctionCallTypeMismatch.new(
120
+ state.env.entry_name,
121
+ node.range,
122
+ expected: e.expected,
123
+ actual: e.actual,
124
+ infix: node.infix,
125
+ )
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,70 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module FunctionDeclaration
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, registry, state, _)
10
+ node => AST::FunctionDeclaration(symbol:, body:, params:)
11
+
12
+ # Use the binding directly instead of env.lookup, which would
13
+ # instantiate fresh vars and detach body call sites' dict markers
14
+ # from the binding's stored constraints.
15
+ state
16
+ .env
17
+ .bindings[symbol.qualified_name] => {
18
+ type: fn_type, constraints: fn_constraints,
19
+ }
20
+
21
+ arg_types, return_type = Type.signature(fn_type)
22
+
23
+ new_state, body_result = arg_types
24
+ .zip(params)
25
+ .reduce(state) do |acc, (t, p)|
26
+ acc.bind(p.name, Scheme.mono(t))
27
+ end
28
+ .then { check(body, registry, it, Expected.check(return_type)) }
29
+
30
+ new_state
31
+ .unify(
32
+ body_result.type,
33
+ return_type,
34
+ fn_type.unbound_vars
35
+ ) do
36
+ Error::FunctionBodyTypeMismatch.new(
37
+ state.env.entry_name,
38
+ node.range,
39
+ expected: it.expected,
40
+ actual: it.actual,
41
+ function_name: node.name,
42
+ )
43
+ end
44
+ .then do |st|
45
+ next st if st.env.bindings[symbol.qualified_name].is_a?(Scheme)
46
+
47
+ updated_constraints = (fn_constraints + body_result.constraints)
48
+ .map { st.env.substitution.apply(it) }
49
+ .uniq
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
+ st.bind(
57
+ symbol.qualified_name,
58
+ Placeholder[
59
+ st.env.substitution.apply(fn_type),
60
+ updated_constraints,
61
+ ]
62
+ )
63
+ end
64
+ .then { [it, Result.init(Type.unit)] }
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,18 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module Grouping
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, registry, env, expected_type)
10
+ node => AST::Grouping(expression:)
11
+
12
+ check(expression, registry, env, expected_type)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ require 'jade/frontend/type_checking/generalization'
2
+ require 'jade/frontend/type_checking/instantiation'
3
+
4
+ module Jade
5
+ module Frontend
6
+ module TypeChecking
7
+ module Inference
8
+ module Helpers
9
+ extend self
10
+
11
+ def unify(actual, expected)
12
+ Unification.unify(actual, expected)
13
+ end
14
+
15
+ def instantiate(scheme, var_gen)
16
+ Instantiation.instantiate(scheme, var_gen)
17
+ end
18
+
19
+ def generalize(env, type, constraints = [])
20
+ Generalization.generalize(env, type, constraints)
21
+ end
22
+
23
+ def check(node, registry, env, expected_type)
24
+ TypeChecking.check_node(node, registry, env, expected_type)
25
+ end
26
+
27
+ def type_from_symbol(symbol, registry, var_gen)
28
+ Type.from_symbol(symbol, registry, var_gen)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,46 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module IfThenElse
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, registry, state, expected)
10
+ node => AST::IfThenElse(condition:, if_branch:, else_branch:)
11
+
12
+ cond_state, cond_result = check(condition, registry, state, Expected.check(Type.bool))
13
+ after_cond_state, _ = cond_state.unify_result(cond_result, Type.bool) do
14
+ Error::IfConditionTypeMismatch.new(
15
+ state.env.entry_name,
16
+ condition.range,
17
+ actual: it.actual,
18
+ )
19
+ end
20
+
21
+ if_state, if_result = check(if_branch, registry, after_cond_state, expected)
22
+ else_state, else_result = check(else_branch, registry, if_state, expected)
23
+
24
+ constraints = cond_result.constraints +
25
+ if_result.constraints +
26
+ else_result.constraints
27
+
28
+ else_state
29
+ .unify_result(
30
+ else_result.with(constraints:),
31
+ if_result.type,
32
+ expected.rigid_vars
33
+ ) do
34
+ Error::IfBranchesTypeMismatch.new(
35
+ state.env.entry_name,
36
+ else_branch.range,
37
+ expected: it.expected,
38
+ actual: it.actual,
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,150 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module Implementation
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, registry, state, _expected)
10
+ node => AST::Implementation(functions:)
11
+
12
+ impl = node.symbol
13
+
14
+ interface_sym = registry.lookup(impl.interface)
15
+ interface_qname = impl.interface.qualified_name
16
+
17
+ # Build the concrete type for the constructor, respecting its type params
18
+ concrete_type, = type_from_symbol(impl.type, registry, state.env.var_gen)
19
+
20
+ functions
21
+ .reduce(state) do |st, impl_fn|
22
+ impl_fn => AST::ImplementationFunction(name:)
23
+
24
+ iface_fn = interface_sym
25
+ .functions
26
+ .find { |f| f.name == name }
27
+
28
+ # Instantiate the interface function with fresh vars
29
+ iface_fn_type, iface_fn_constraints =
30
+ type_from_symbol(iface_fn, registry, st.env.var_gen)
31
+
32
+ # The type var standing for the interface's type param
33
+ t_var = iface_fn_constraints
34
+ .find { |c| c.interface == interface_qname }
35
+ .type
36
+
37
+ # When the interface uses t_var as a constructor (e.g. f(a) -> f(b)),
38
+ # bind it to a partial application so that f(a) beta-reduces correctly.
39
+ # For 1-param types (Maybe): tail = [] → constructor
40
+ # For 2-param types (Result): tail = [e] → PartialApplication[Constructor, [e]]
41
+ binding_type =
42
+ case [constructor_var_in?(iface_fn_type, t_var.id), concrete_type]
43
+ in [true, Type::Application(constructor:, args:)]
44
+ tail = args.drop(1)
45
+ tail.empty? ? constructor : Type::PartialApplication[constructor, tail]
46
+ else
47
+ concrete_type
48
+ end
49
+
50
+ # Bind the interface type var to the concrete type
51
+ st_after_bind = st.unify(t_var, binding_type) { nil }
52
+ expected_type = st_after_bind.env.substitution.apply(iface_fn_type)
53
+
54
+ infer_fn(
55
+ impl_fn,
56
+ registry,
57
+ st_after_bind,
58
+ Expected.check(expected_type),
59
+ interface_qname,
60
+ )
61
+ end
62
+ .then { [it, Result.init(Type.unit)] }
63
+ end
64
+
65
+ private
66
+
67
+ def infer_fn(impl_fn, registry, state, expected, interface_qname)
68
+ impl_fn => AST::ImplementationFunction(name:, fn:)
69
+
70
+ case fn
71
+ in AST::Lambda(params: [])
72
+ # 0-arg lambda for a non-function field (e.g. `decoder: () -> { ... }`
73
+ # against `decoder: Decoder(a)`) acts as a thunk: type the body and
74
+ # unify with expected. Mirrors `from_symbol_r`'s 0-arg collapse for
75
+ # named `def f() -> T`. Codegen emits a `->()` either way; the
76
+ # runtime always `.call`s the impl entry.
77
+ if expected.type.is_a?(Type::Function)
78
+ check(fn, registry, state, expected).first
79
+ else
80
+ body_state, body_result = check(
81
+ fn.body,
82
+ registry,
83
+ state,
84
+ Expected.infer(state.fresh),
85
+ )
86
+ body_state.unify(
87
+ body_result.type,
88
+ expected.type,
89
+ &mismatch_error(state.env.entry_name, impl_fn, interface_qname, name)
90
+ )
91
+ end
92
+
93
+ in AST::Lambda
94
+ check(fn, registry, state, expected).first
95
+
96
+ in AST::VariableReference
97
+ ref_state, ref_result = check(fn, registry, state, expected)
98
+
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
107
+ )
108
+ )
109
+
110
+ # `decoder: zero_arg_fn` becomes `FunctionCall(zero_arg_fn, [])`
111
+ # after ZeroArgRewrite. Type the call; its result must match the
112
+ # interface field's type.
113
+ in AST::FunctionCall
114
+ check(fn, registry, state, expected).first
115
+ end
116
+ end
117
+
118
+ def constructor_var_in?(type, var_id)
119
+ case type
120
+ in Type::Application(constructor: Type::Var(id:)) if id == var_id
121
+ true
122
+
123
+ in Type::Application(constructor:, args:)
124
+ [constructor, *args].any? { constructor_var_in?(it, var_id) }
125
+
126
+ in Type::Function(args:, return_type:)
127
+ [*args, return_type].any? { constructor_var_in?(it, var_id) }
128
+
129
+ else
130
+ false
131
+ end
132
+ end
133
+
134
+ def mismatch_error(entry_name, impl_fn, interface_qname, fn_name)
135
+ ->(e) do
136
+ Error::ImplementationTypeMismatch.new(
137
+ entry_name,
138
+ impl_fn.range,
139
+ expected: e.expected,
140
+ actual: e.actual,
141
+ interface: interface_qname,
142
+ fn_name:,
143
+ )
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,19 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module ImportDeclaration
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, _, state, _)
10
+ node => AST::ImportDeclaration
11
+ Type.unit
12
+ .then { Result.init(it) }
13
+ .then { [state, it] }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module InterfaceDeclaration
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, _, state, _)
10
+ node => AST::InterfaceDeclaration
11
+
12
+ [state, Result.init(Type.unit)]
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module InteropImportDeclaration
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, _, state, _)
10
+ node => AST::InteropImportDeclaration
11
+
12
+ [state, Result.init(Type.unit)]
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end