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,144 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Constraints
5
+ module Deriving
6
+ module Encodable
7
+ extend self
8
+ include Helpers
9
+
10
+ INTERFACE = 'Encode.Encodable'
11
+
12
+ def supports?(interface)
13
+ interface == INTERFACE
14
+ end
15
+
16
+ def derive(constraint, registry, entry_name, &lookup)
17
+ case constraint.type
18
+ in Type::Application(constructor: Type::Constructor(name: 'List.List'), args: [inner])
19
+ derive_list(constraint, inner, lookup, entry_name)
20
+
21
+ in Type::Application(constructor: Type::Constructor(name: 'Maybe.Maybe'), args: [inner])
22
+ derive_nullable(constraint, inner, lookup, entry_name)
23
+
24
+ in Type::Application(constructor: Type::Constructor(name:), args:)
25
+ resolved_sym = Symbol
26
+ .type_ref_from_qualified_name(name)
27
+ .then { registry.lookup(it) }
28
+
29
+ case resolved_sym
30
+ in Symbol::Struct
31
+ derive_struct(constraint, resolved_sym, args, registry, lookup, entry_name)
32
+
33
+ else
34
+ failed(constraint, entry_name)
35
+ end
36
+
37
+ else
38
+ failed(constraint, entry_name)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def failed(constraint, entry_name)
45
+ Err[
46
+ Error::DerivationFailed.new(
47
+ entry_name,
48
+ constraint.origin&.range,
49
+ constraint:,
50
+ trace: [],
51
+ )
52
+ ]
53
+ end
54
+
55
+ def derive_list(constraint, inner_type, lookup, entry_name)
56
+ dep = Type.constraint(INTERFACE, inner_type, nil)
57
+
58
+ lookup.call(dep).and_then do |dep_impl|
59
+ body = [:call,
60
+ [:stdlib_fn, 'Encode.list'],
61
+ [
62
+ [:impl_arg, 0, 'encoder'],
63
+ [:var, 'items'],
64
+ ],
65
+ ]
66
+
67
+ Ok[implementation(constraint, params: ['items'], body:, deps: [dep_impl])]
68
+ end
69
+ end
70
+
71
+ def derive_nullable(constraint, inner_type, lookup, entry_name)
72
+ dep = Type.constraint(INTERFACE, inner_type, nil)
73
+
74
+ lookup.call(dep).and_then do |dep_impl|
75
+ body = [:call,
76
+ [:stdlib_fn, 'Encode.nullable'],
77
+ [
78
+ [:impl_arg, 0, 'encoder'],
79
+ [:var, 'maybe'],
80
+ ],
81
+ ]
82
+
83
+ Ok[implementation(constraint, params: ['maybe'], body:, deps: [dep_impl])]
84
+ end
85
+ end
86
+
87
+ def derive_struct(constraint, struct_sym, type_args, registry, lookup, entry_name)
88
+ fields = struct_fields(struct_sym, type_args, registry)
89
+
90
+ field_deps = fields
91
+ .map { |_, field_type| Type.constraint(INTERFACE, field_type, nil) }
92
+
93
+ resolved_deps = field_deps
94
+ .map do |dep|
95
+ lookup.call(dep) => Ok[impl]
96
+ impl
97
+ end
98
+
99
+ pair_irs = fields
100
+ .each_with_index
101
+ .map do |(field_name, _), idx|
102
+ [:call,
103
+ [:stdlib_fn, 'Tuple.pair'],
104
+ [
105
+ field_name.to_s,
106
+ [:call,
107
+ [:impl_arg, idx, 'encoder'],
108
+ [[:access, [:var, 'rec'], field_name.to_s]],
109
+ ],
110
+ ],
111
+ ]
112
+ end
113
+
114
+ body = [:call,
115
+ [:stdlib_fn, 'Encode.object'],
116
+ [
117
+ [:list, pair_irs],
118
+ ],
119
+ ]
120
+
121
+ Ok[implementation(constraint, params: ['rec'], body:, deps: resolved_deps)]
122
+ end
123
+
124
+ def implementation(constraint, params:, body:, deps:)
125
+ encoder_fn = Symbol::DerivedFunction.new(params:, body:)
126
+
127
+ Symbol::Implementation.new(
128
+ module_name: nil,
129
+ interface: Symbol.type_ref_from_qualified_name(constraint.interface),
130
+ type: constraint.type,
131
+ type_params: [],
132
+ constraints: [],
133
+ functions: { 'encoder' => encoder_fn },
134
+ deps:,
135
+ extends: [],
136
+ decl_span: nil,
137
+ )
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,265 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Constraints
5
+ module Deriving
6
+ module Eq
7
+ extend self
8
+ include Helpers
9
+
10
+ INTERFACE = 'Basics.Eq'
11
+
12
+ def supports?(interface) = interface == INTERFACE
13
+
14
+ def derive(constraint, registry, entry_name, &lookup)
15
+ resolve(constraint, registry, entry_name, lookup)
16
+ end
17
+
18
+ private
19
+
20
+ def resolve(constraint, registry, entry_name, lookup)
21
+ case [constraint.interface, constraint.type]
22
+ in [INTERFACE, Type::Application(constructor:, args:)]
23
+ registry
24
+ .implementations[[constraint.interface, constructor.name]]
25
+ .then do
26
+ it \
27
+ ? Ok[it]
28
+ : derive_for_type(constraint, constructor, args, registry, lookup, entry_name)
29
+ end
30
+ .on_err { return Err[it] } => Ok(impl)
31
+
32
+ case impl
33
+ in Symbol::ImplementationTemplate
34
+ deps = dependencies_of(impl, args)
35
+ resolved_deps = deps.filter_map { |dep|
36
+ next if dep.type in Type::Var
37
+ lookup.call(dep) => Ok[resolved]; resolved
38
+ }
39
+
40
+ Symbol::Implementation.new(
41
+ module_name: nil,
42
+ interface: Symbol.type_ref_from_qualified_name(constraint.interface),
43
+ type: constraint.type,
44
+ type_params: args,
45
+ constraints: deps,
46
+ functions: impl.functions,
47
+ deps: resolved_deps,
48
+ extends: [],
49
+ decl_span: nil,
50
+ )
51
+
52
+ else
53
+ impl
54
+ end
55
+ .then { Ok[it] }
56
+
57
+ in [INTERFACE, Type::AnonymousRecord(fields:)]
58
+ derive_record_eq(constraint, fields, lookup)
59
+
60
+ else
61
+ Err[
62
+ Error::DerivationFailed
63
+ .new(entry_name, constraint.origin.range, constraint:, trace: [])
64
+ ]
65
+ end
66
+ end
67
+
68
+ def dependencies_of(impl, args)
69
+ subst = impl
70
+ .type_params
71
+ .map(&:id)
72
+ .zip(args)
73
+ .to_h
74
+
75
+ impl
76
+ .constraints
77
+ .map { it.with(type: substitute_type(it.type, subst)) }
78
+ end
79
+
80
+ def substitute_type(type, subst)
81
+ case type
82
+
83
+ in Type::Var(id:)
84
+ subst.fetch(id, type)
85
+
86
+ in Type::Application(constructor:, args:)
87
+ Type::Application.new(
88
+ constructor: constructor,
89
+ args: args.map { substitute_type(it, subst) }
90
+ )
91
+
92
+ in Type::AnonymousRecord(fields:)
93
+ Type::AnonymousRecord.new(
94
+ fields: fields.transform_values { substitute_type(it, subst) }
95
+ )
96
+
97
+ else
98
+ type
99
+ end
100
+ end
101
+
102
+ def derive_for_type(constraint, constructor, args, registry, lookup, entry_name)
103
+ symbol =
104
+ Symbol
105
+ .type_ref_from_qualified_name(constructor.name)
106
+ .then { registry.lookup(it) }
107
+
108
+ case symbol
109
+ in Symbol::Union
110
+ Ok[derive_union_eq(constraint, symbol, registry, lookup)]
111
+
112
+ in Symbol::Struct
113
+ derive_struct_eq(constraint, symbol, args, registry, lookup, entry_name)
114
+
115
+ else
116
+ Err[
117
+ Error::DerivationFailed
118
+ .new(entry_name, constraint.origin.range, constraint:, trace: [])
119
+ ]
120
+ end
121
+ end
122
+
123
+ def derive_union_eq(constraint, symbol, registry, lookup)
124
+ type_vars = symbol.type_params.map(&:name)
125
+ index_map = type_vars.each_with_index.map.to_h
126
+
127
+ cases = symbol.variants
128
+ .map { registry.lookup(it) }
129
+ .map { build_variant_case(it, index_map, lookup, constraint.origin) }
130
+
131
+ eq_fn = Symbol::DerivedFunction.new(
132
+ params: ["one", "other"],
133
+ body: [:case,
134
+ [:list, [[:var, "one"], [:var, "other"]]],
135
+ cases + [[[:_], [false]]],
136
+ ],
137
+ )
138
+
139
+ if type_vars.empty?
140
+ Symbol::Implementation.new(
141
+ module_name: nil,
142
+ interface: Symbol.type_ref_from_qualified_name(constraint.interface),
143
+ type: constraint.type,
144
+ type_params: [],
145
+ constraints: [],
146
+ functions: { '(==)' => eq_fn },
147
+ deps: [],
148
+ extends: [],
149
+ decl_span: nil,
150
+ )
151
+ else
152
+ Symbol::ImplementationTemplate.new(
153
+ interface: Symbol.type_ref_from_qualified_name(constraint.interface),
154
+ type: constraint.type,
155
+ type_params: type_vars.map { Type.var(it) },
156
+ constraints: type_vars.map {
157
+ Type.constraint(INTERFACE, Type.var(it), constraint.origin)
158
+ },
159
+ functions: { '(==)' => eq_fn },
160
+ )
161
+ end
162
+ end
163
+
164
+ def build_variant_case(variant, index_map, lookup, origin)
165
+ field_count = variant.args.length
166
+
167
+ left_vars = (0...field_count).map { |i| "l#{i}" }
168
+ right_vars = (0...field_count).map { |i| "r#{i}" }
169
+
170
+ left_pattern = [:constructor, variant.qualified_name, left_vars]
171
+ right_pattern = [:constructor, variant.qualified_name, right_vars]
172
+
173
+ comparisons =
174
+ variant.args.each_with_index.map do |arg_type, i|
175
+ case arg_type
176
+
177
+ in Symbol::Variable(name:)
178
+ idx = index_map[name]
179
+
180
+ [:call,
181
+ [:impl_arg, idx, "(==)"],
182
+ [[:var, left_vars[i]], [:var, right_vars[i]]]
183
+ ]
184
+
185
+ else
186
+ lookup.call(Type.constraint(INTERFACE, arg_type, origin)) => Ok[impl]
187
+
188
+ [:call,
189
+ [:impl_value, impl, "(==)"],
190
+ [[:var, left_vars[i]], [:var, right_vars[i]]]
191
+ ]
192
+ end
193
+ end
194
+
195
+ body =
196
+ if comparisons.empty?
197
+ [true]
198
+ else
199
+ first_comparison, *rest = comparisons
200
+ [rest.reduce(first_comparison) { |acc, item| [:and, acc, item] }]
201
+ end
202
+
203
+ [[:list, [left_pattern, right_pattern]], body]
204
+ end
205
+
206
+ def derive_record_eq(constraint, fields, lookup)
207
+ field_types = fields.values
208
+ field_keys = fields.keys
209
+
210
+ resolve_field_deps(field_types, lookup, constraint.origin)
211
+ .and_then do |deps|
212
+ field_keys
213
+ .each_with_index.map { |field_name, idx|
214
+ left = [:access, [:var, 'one'], field_name]
215
+ right = [:access, [:var, 'other'], field_name]
216
+ [:call, [:impl_arg, idx, '(==)'], [left, right]]
217
+ }
218
+ .then { build_record_impl(constraint, it, deps) }
219
+ .then { Ok[it] }
220
+ end
221
+ end
222
+
223
+ def derive_struct_eq(constraint, struct_sym, type_args, registry, lookup, entry_name)
224
+ fields = struct_fields(struct_sym, type_args, registry)
225
+ field_types = fields.map { |_, t| t }
226
+ field_names = fields.map { |k, _| k.to_s }
227
+
228
+ resolve_field_deps(field_types, lookup, constraint.origin).and_then do |deps|
229
+ comparisons = field_names.each_with_index.map { |field_name, idx|
230
+ left = [:access, [:var, 'one'], field_name]
231
+ right = [:access, [:var, 'other'], field_name]
232
+ [:call, [:impl_arg, idx, '(==)'], [left, right]]
233
+ }
234
+ Ok[build_record_impl(constraint, comparisons, deps)]
235
+ end
236
+ end
237
+
238
+ def resolve_field_deps(field_types, lookup, origin)
239
+ field_types
240
+ .map { lookup.call(Type.constraint(INTERFACE, it, origin)) }
241
+ .then { Results.sequence(it) }
242
+ end
243
+
244
+ def build_record_impl(constraint, comparisons, deps)
245
+ body = comparisons.empty? ? true : comparisons.reduce { |a, b| [:and, a, b] }
246
+ eq_fn = Symbol::DerivedFunction.new(params: ['one', 'other'], body:)
247
+
248
+ Symbol::Implementation.new(
249
+ module_name: nil,
250
+ interface: Symbol.type_ref_from_qualified_name(constraint.interface),
251
+ type: constraint.type,
252
+ type_params: [],
253
+ constraints: [],
254
+ functions: { '(==)' => eq_fn },
255
+ deps:,
256
+ extends: [],
257
+ decl_span: nil,
258
+ )
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end
264
+ end
265
+ end
@@ -0,0 +1,59 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Constraints
5
+ module Deriving
6
+ module Helpers
7
+ extend self
8
+
9
+ def struct_fields(struct_sym, type_args, registry)
10
+ record = struct_sym.record_type
11
+ type_param_names = struct_sym.type_params.map(&:name)
12
+ subst = type_param_names.zip(type_args).to_h
13
+
14
+ record
15
+ .fields
16
+ .map { |name, sym| [name, instantiate(sym, subst, registry)] }
17
+ end
18
+
19
+ def instantiate(sym, subst, registry)
20
+ case sym
21
+ in Symbol::Variable(name:)
22
+ subst.fetch(name) { Type.var(nil, name) }
23
+
24
+ in Symbol::TypeApplication(constructor:, args:)
25
+ inner_args = args
26
+ .map { instantiate(it, subst, registry) }
27
+
28
+ Symbol
29
+ .type_ref(constructor.module_name, constructor.name)
30
+ .then { registry.lookup(it) }
31
+ .then { type_application_to_type(it, inner_args) }
32
+
33
+ in Symbol::TypeRef
34
+ registry
35
+ .lookup(sym)
36
+ .then { type_application_to_type(it, []) }
37
+
38
+ in Symbol::FunctionType(params:, return_type:)
39
+ Type.function(
40
+ params.map { instantiate(it, subst, registry) },
41
+ instantiate(return_type, subst, registry),
42
+ )
43
+ end
44
+ end
45
+
46
+ def type_application_to_type(sym, args)
47
+ case sym
48
+ in Symbol::Union | Symbol::Struct
49
+ Type
50
+ .constructor(sym.qualified_name)
51
+ .apply(args)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,28 @@
1
+ require_relative './deriving/helpers.rb'
2
+ require_relative './deriving/eq.rb'
3
+ require_relative './deriving/decodable.rb'
4
+ require_relative './deriving/encodable.rb'
5
+
6
+ module Jade
7
+ module Frontend
8
+ module TypeChecking
9
+ module Constraints
10
+ module Deriving
11
+ extend self
12
+
13
+ DERIVERS = [Eq, Decodable, Encodable]
14
+
15
+ def derivable?(interface)
16
+ DERIVERS.any? { it.supports?(interface) }
17
+ end
18
+
19
+ def derive(constraint, registry, entry_name, &lookup)
20
+ DERIVERS
21
+ .find { it.supports?(constraint.interface) }
22
+ .then { it.derive(constraint, registry, entry_name, &lookup) }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,101 @@
1
+ require 'jade/frontend/type_checking/constraints/deriving'
2
+
3
+ module Jade
4
+ module Frontend
5
+ module TypeChecking
6
+ module Constraints
7
+ extend self
8
+
9
+ def resolve(constraint, registry, entry_name)
10
+ if constraint.type in Type::Var
11
+ Error::UnresolvedConstraint
12
+ .new(entry_name, constraint.origin&.range, constraint:)
13
+ .then { return Err[it] }
14
+ end
15
+
16
+ if impl = lookup(constraint, registry)
17
+ impl
18
+ .extends
19
+ .map do |iface_ref|
20
+ Type
21
+ .constraint(
22
+ iface_ref.qualified_name,
23
+ constraint.type,
24
+ constraint.origin,
25
+ )
26
+ .then { resolve(it, registry, entry_name) } => Ok[resolved]
27
+
28
+ resolved
29
+ end
30
+ .then { impl.deps + it }
31
+ .then { impl.with(deps: it) }
32
+ .then { return Ok[it] }
33
+ end
34
+
35
+ if Deriving.derivable?(constraint.interface)
36
+ Deriving
37
+ .derive(constraint, registry, entry_name) { resolve(it, registry, entry_name) }
38
+ .then { return it }
39
+ end
40
+
41
+ constraint.origin.range
42
+ .then { Error::MissingImplementation.new(entry_name, it, constraint:) }
43
+ .then { Err[it] }
44
+ end
45
+
46
+ # An origin's dictionaries can be touched by multiple inference frames:
47
+ # the call's own callee constraints attach here, and outer frames
48
+ # also attach when args bubble up concretely. Var-typed markers' ids
49
+ # may chain further as inference proceeds; the finalize-time
50
+ # canonicalize pass walks the AST and rewrites them to their final
51
+ # form so codegen can read marker.type.id directly.
52
+ def attach_dictionary(constraint, impl)
53
+ constraint => Type::Constraint(
54
+ origin: { dictionaries: dicts },
55
+ index:,
56
+ )
57
+
58
+ fail "constraint missing index: #{constraint}" if index == :unindex
59
+
60
+ return if dicts[index].is_a?(Symbol::Implementation) &&
61
+ impl.is_a?(Type::Constraint)
62
+
63
+ dicts[index] = impl
64
+ end
65
+
66
+ def solve_at_finalize(constraint, registry, entry_name)
67
+ resolve(constraint, registry, entry_name)
68
+ .map { |impl| attach_dictionary(constraint, impl); [] }
69
+ .on_err(Error::UnresolvedConstraint) { Ok[[]] }
70
+ .on_err { Ok[[it]] }
71
+ .with_default([])
72
+ end
73
+
74
+ def solve_at_call_site(constraint, registry, entry_name)
75
+ resolve(constraint, registry, entry_name)
76
+ .map { |impl| attach_dictionary(constraint, impl); [] }
77
+ .on_err(Error::MissingImplementation) { Ok[[it]] }
78
+ .on_err(Error::DerivationFailed) { Ok[[it]] }
79
+ .with_default([])
80
+ end
81
+
82
+ private
83
+
84
+ def lookup(constraint, registry)
85
+ key =
86
+ case constraint.type
87
+ in Type::Application(constructor:) then constructor.name
88
+ in Type::PartialApplication(constructor:) then constructor.name
89
+ in Type::Constructor(name:) then name
90
+ else constraint.type.to_s
91
+ end
92
+
93
+ case registry.implementations[[constraint.interface, key]]
94
+ in Symbol::Implementation => impl then impl
95
+ else nil
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,71 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+
5
+ StructDef = Data.define(:name, :type_params, :body)
6
+ TypeDef = Data.define(:name, :type_params, :constructors) do
7
+ def opaque?
8
+ constructors.empty?
9
+ end
10
+ end
11
+ ConstructorDef = Data.define(:name, :parent_name, :args)
12
+ InterfaceDef = Data.define(:name)
13
+
14
+ module Definition
15
+ extend self
16
+
17
+ def from_symbol(sym, var_gen = VarGen.new, registry)
18
+ # TODO: Don't need a var gen here, definitions don't have identity. they just share the name
19
+ case sym
20
+ in Symbol::Struct
21
+ type_params, type_params_map = sym
22
+ .type_params
23
+ .reduce([[], {}]) do |(types, local_map), sym|
24
+ Type.send(:from_symbol_r, sym, registry, var_gen, local_map)
25
+ .then { |(t, _, new_map)| [types + [t], new_map] }
26
+ end
27
+
28
+ Type
29
+ .send(:from_symbol_r, sym.record_type, registry, var_gen, type_params_map)
30
+ .first
31
+ .then { Definition.struct(sym.qualified_name, type_params, it) }
32
+
33
+ in Symbol::Union
34
+ type = Type.from_symbol(sym, registry, var_gen).first
35
+
36
+ sym
37
+ .variants
38
+ .map do |variant|
39
+ args = case Type.from_symbol(variant, registry, var_gen).first
40
+ in Type::Function(args:) then args
41
+ else []
42
+ end
43
+ Definition.constructor(variant.qualified_name, sym.qualified_name, args)
44
+ end
45
+ .then { Definition.type(sym.qualified_name, type.args, it) }
46
+
47
+ in Symbol::Interface(name:)
48
+ InterfaceDef[name]
49
+
50
+ in Symbol::TypeRef
51
+ registry
52
+ .lookup(sym)
53
+ .then { from_symbol(it, var_gen, registry) }
54
+ end
55
+ end
56
+
57
+ def constructor(name, parent_name, args)
58
+ ConstructorDef[name, parent_name, args]
59
+ end
60
+
61
+ def type(name, type_params, constructors)
62
+ TypeDef[name, type_params, constructors]
63
+ end
64
+
65
+ def struct(name, type_params, body)
66
+ StructDef[name, type_params, body]
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end