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,79 @@
1
+ require 'jade/frontend/type_checking/placeholder'
2
+ require 'jade/frontend/type_checking/scheme'
3
+ require 'jade/frontend/type_checking/var_gen'
4
+
5
+ module Jade
6
+ module Frontend
7
+ module TypeChecking
8
+ Env = Data.define(
9
+ :entry_name, :bindings, :substitution,
10
+ :definitions, :var_gen, :node_types,
11
+ ) do
12
+ def self.empty(var_gen = VarGen.new)
13
+ Env[nil, {}, Substitution::EMPTY, {}, var_gen, {}]
14
+ end
15
+
16
+ def fresh
17
+ var_gen.fresh
18
+ end
19
+
20
+ def bind(key, value)
21
+ bindings
22
+ .merge(key => value)
23
+ .then { with(bindings: it) }
24
+ end
25
+
26
+ def pin_type(node_id, type)
27
+ with(node_types: node_types.merge(node_id => type))
28
+ end
29
+
30
+ # Post-finalize, apply the env's substitution to every pinned
31
+ # type so stored types are canonical (no leftover Type::Var that
32
+ # the substitution would resolve).
33
+ def canonicalize_node_types
34
+ node_types
35
+ .transform_values { substitution.apply(it) }
36
+ .then { with(node_types: it) }
37
+ end
38
+
39
+ def define(key, value)
40
+ definitions
41
+ .merge(key => value)
42
+ .then { with(definitions: it) }
43
+ end
44
+
45
+ def lookup(key)
46
+ binding = bindings[key]
47
+
48
+ type, constraints =
49
+ case bindings[key]
50
+ in Scheme => scheme
51
+ Instantiation.instantiate(scheme, var_gen)
52
+
53
+ in Placeholder => placeholder
54
+ Scheme[placeholder.free_vars, placeholder.type, placeholder.constraints]
55
+ .then { Instantiation.instantiate(it, var_gen) }
56
+ end
57
+
58
+ Result.init(type, constraints)
59
+ end
60
+
61
+ def lookup_def(key)
62
+ definitions[key]
63
+ end
64
+
65
+ def free_vars
66
+ bindings
67
+ .values
68
+ .flat_map(&:free_vars)
69
+ .flat_map { substitution.apply(it).unbound_vars }
70
+ .uniq(&:id)
71
+ end
72
+
73
+ def composose_substitution(sub)
74
+ with(substitution: substitution.compose(sub))
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,19 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class CaseOfBranchesTypeMismatch < Error::TypeMismatch
6
+ def initialize(entry, span, expected:, actual:, actual_index:)
7
+ super
8
+ @actual_index = actual_index
9
+ end
10
+
11
+ def message
12
+ "First branch of this case statement is #{@expected} " +
13
+ "but #{ordinal(@actual_index)} branch is #{@actual}"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class DerivationFailed < Jade::Error
6
+ attr_reader :constraint
7
+
8
+ def initialize(entry, span, constraint:, trace: [])
9
+ @constraint = constraint
10
+ @trace = trace
11
+ super(entry:, span:)
12
+ end
13
+
14
+ def message
15
+ "#{@constraint.interface} cannot be derived for #{@constraint.type}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class FunctionBodyTypeMismatch < TypeMismatch
6
+ def initialize(entry, span, expected:, actual:, function_name:)
7
+ super
8
+ @function_name = function_name
9
+ end
10
+
11
+ def message
12
+ "There's a problem with the body of `#{@function_name}` definition: " ++
13
+ "it returns #{@actual} but its signature says it should be #{@expected}"
14
+ end
15
+
16
+ def label
17
+ "returns #{@actual}, expected #{@expected}"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class FunctionCallTypeMismatch < TypeMismatch
6
+ def initialize(entry, span, expected:, actual:, infix:)
7
+ super
8
+ @infix = infix
9
+ end
10
+
11
+ def message
12
+ case @infix
13
+ in AST::InfixOperator(value:)
14
+ infix_error(value)
15
+ else
16
+ "Function call mismatch, expected #{@expected} but found #{@actual}"
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def infix_error(operator)
23
+ if @expected.args.first != @actual.args.first
24
+ return "Left side of (#{operator}) expects #{@expected.args.first} but found #{@actual.args.first}"
25
+ end
26
+
27
+ if @expected.args.last != @actual.args.last
28
+ return "Right side of (#{operator}) expects #{@expected.args.last} but found #{@actual.args.last}"
29
+ end
30
+
31
+ "Function call mismatch, expected #{@expected} but found #{@actual}"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class IfBranchTypeMismatch < TypeMismatch
6
+ def initialize(entry, span, expected:, actual:, branch:)
7
+ super
8
+ @branch = branch == :then ? 'then' : 'else'
9
+ end
10
+
11
+ def message
12
+ "The #{@branch} branch of this if statement is expected to return" +
13
+ " #{@expected} but got #{@actual}"
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 Error
5
+ class IfBranchesTypeMismatch < TypeMismatch
6
+ def initialize(entry, span, expected:, actual:)
7
+ super
8
+ end
9
+
10
+ def message
11
+ "If branches must return the same type. The then branch produces " +
12
+ "#{@expected} but the else branch produces #{@actual}"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class IfConditionTypeMismatch < TypeMismatch
6
+ def initialize(entry, span, expected: Type.bool, actual:)
7
+ super
8
+ end
9
+
10
+ def message
11
+ "If condition expects #{@expected} but found #{@actual}"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class ImplementationTypeMismatch < TypeMismatch
6
+ def initialize(entry, span, expected:, actual:, interface:, fn_name:)
7
+ super(entry, span, expected:, actual:)
8
+ @interface = interface
9
+ @fn_name = fn_name
10
+ end
11
+
12
+ def message
13
+ "Implementation of #{@interface}.#{@fn_name}: " \
14
+ "expected #{@expected} but the provided function has type #{@actual}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class ListItemTypeMismatch < TypeMismatch
6
+ def initialize(entry, span, expected:, actual:, actual_index:)
7
+ super
8
+ @actual_index = actual_index
9
+ end
10
+
11
+ def message
12
+ "The #{ordinal(@actual_index)} item does not match the previous items in the list, " +
13
+ "expected #{@expected} but found #{@actual}"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class MissingImplementation < Jade::Error
6
+ attr_reader :constraint
7
+
8
+ def initialize(entry, span, constraint:)
9
+ @constraint = constraint
10
+ super(entry:, span:)
11
+ end
12
+
13
+ def message
14
+ "No implementation of #{@constraint.interface} for #{@constraint.type}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class MissingPatterns < Jade::Error
6
+ def initialize(entry, span, missing_patterns:)
7
+ @missing_patterns = missing_patterns
8
+ super(entry:, span:)
9
+ end
10
+
11
+ def message
12
+ patterns_str = @missing_patterns
13
+ .map { |row| row.map(&:to_s).join(', ') }
14
+ .map { " #{it}" }
15
+ .join("\n")
16
+ "Pattern match is not exhaustive. Missing cases:\n#{patterns_str}"
17
+ end
18
+
19
+ def label
20
+ "non-exhaustive pattern match"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class PatternTypeMismatch < TypeMismatch
6
+ def message
7
+ "Pattern is trying to match #{@expected} with #{@actual}"
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,38 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class PortNotDecodable < Jade::Error
6
+ attr_reader :port_name, :arm, :type
7
+
8
+ def initialize(entry, span, port_name:, arm:, type:)
9
+ @port_name = port_name
10
+ @arm = arm
11
+ @type = type
12
+ super(entry:, span:)
13
+ end
14
+
15
+ def message
16
+ "Port `#{@port_name}` cannot decode its #{@arm} arm (`#{@type}`): " \
17
+ "no Decodable instance"
18
+ end
19
+
20
+ def label
21
+ "no Decodable instance for `#{@type}`"
22
+ end
23
+
24
+ def notes
25
+ [
26
+ Jade::Diagnostics::Annotation[
27
+ :help,
28
+ "implement Decodable for `#{@type}` so it can be decoded " \
29
+ "automatically, or declare the port with `Decode.Value` " \
30
+ "to skip auto-decoding",
31
+ ],
32
+ ]
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class RecordAccessTypeMismatch < TypeMismatch
6
+ def message
7
+ "Something is off with this record access, it expects #{@expected} " +
8
+ "but found #{@actual}"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class TypeMismatch < Jade::Error
6
+ def initialize(entry, span, expected:, actual:, **)
7
+ @expected = expected
8
+ @actual = actual
9
+ super(entry:, span:)
10
+ end
11
+
12
+ def message
13
+ "Expected #{@expected} but got #{@actual}"
14
+ end
15
+
16
+ def label
17
+ "expected #{@expected}, got #{@actual}"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Error
5
+ class UnresolvedConstraint < Jade::Error
6
+ attr_reader :constraint
7
+
8
+ def initialize(entry, span, constraint:)
9
+ @constraint = constraint
10
+ super(entry:, span:)
11
+ end
12
+
13
+ def message
14
+ "Unresolved constraint: #{@constraint.interface} #{@constraint.type}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ require 'jade/error'
2
+
3
+ require 'jade/frontend/type_checking/error/type_mismatch'
4
+
5
+ require 'jade/frontend/type_checking/error/case_of_branches_type_mismatch'
6
+ require 'jade/frontend/type_checking/error/derivation_failed'
7
+ require 'jade/frontend/type_checking/error/function_body_type_mismatch'
8
+ require 'jade/frontend/type_checking/error/function_call_type_mismatch'
9
+ require 'jade/frontend/type_checking/error/if_branch_type_mismatch'
10
+ require 'jade/frontend/type_checking/error/if_branches_type_mismatch'
11
+ require 'jade/frontend/type_checking/error/if_condition_type_mismatch'
12
+ require 'jade/frontend/type_checking/error/missing_patterns'
13
+ require 'jade/frontend/type_checking/error/list_item_type_mismatch'
14
+ require 'jade/frontend/type_checking/error/pattern_type_mismatch'
15
+ require 'jade/frontend/type_checking/error/record_access_type_mismatch'
16
+ require 'jade/frontend/type_checking/error/unresolved_constraint'
17
+ require 'jade/frontend/type_checking/error/implementation_type_mismatch'
18
+ require 'jade/frontend/type_checking/error/missing_implementation'
@@ -0,0 +1,23 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ Expected = Data.define(:type, :authoritative) do
5
+ def check?
6
+ authoritative == true
7
+ end
8
+
9
+ def self.check(type)
10
+ self[type, true]
11
+ end
12
+
13
+ def self.infer(type)
14
+ self[type, false]
15
+ end
16
+
17
+ def rigid_vars
18
+ check? ? type.unbound_vars : []
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Generalization
5
+ extend self
6
+
7
+ def generalize(env, type, constraints = [])
8
+ (type.unbound_vars + constraints.flat_map(&:unbound_vars))
9
+ .uniq(&:id)
10
+ .then { it - env.free_vars }
11
+ .then { Scheme[it, type, constraints] }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,38 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Generalizer
5
+ extend self
6
+ include Inference::Helpers
7
+
8
+ def generalize(env)
9
+ env
10
+ .bindings
11
+ .reduce(env) do |e, (k, binding)|
12
+ case binding
13
+ in Placeholder(type:, constraints:)
14
+ unbound_cs = constraints
15
+ .map { e.substitution.apply(it) }
16
+ .uniq
17
+ .select { it.unbound_vars.any? }
18
+
19
+ Generalization.
20
+ generalize(
21
+ # Remove the current placeholder and all Scheme bindings (local
22
+ # params/variables) so they don't pollute free_vars during
23
+ # generalization. Only other Placeholders contribute free_vars.
24
+ e.with(bindings: e.bindings.except(k).select { |_, v| v.is_a?(Placeholder) }),
25
+ e.substitution.apply(type),
26
+ unbound_cs,
27
+ )
28
+ .then { e.bind(k, it) }
29
+ else
30
+
31
+ next e
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,58 @@
1
+ require 'jade/frontend/pattern_analysis'
2
+
3
+ module Jade
4
+ module Frontend
5
+ module TypeChecking
6
+ module Inference
7
+ module Assign
8
+ extend Helpers
9
+ extend self
10
+
11
+ def infer(node, registry, state, expected)
12
+ node => AST::Assign(pattern:, expression:)
13
+
14
+ expr_state, expr_result = check(
15
+ expression,
16
+ registry,
17
+ state,
18
+ Expected.infer(state.fresh),
19
+ )
20
+
21
+ pattern_state, _ = Pattern.infer(
22
+ pattern,
23
+ registry,
24
+ expr_state,
25
+ Expected.check(expr_result.type),
26
+ )
27
+
28
+ final_state, residual_cs =
29
+ case pattern
30
+ in AST::Pattern::Binding(name:)
31
+ bind_with_residual(pattern_state, expr_state, expr_result, name)
32
+ else
33
+ [pattern_state, expr_result.constraints]
34
+ end
35
+
36
+ PatternAnalysis::Exhaustiveness
37
+ .assert([pattern], pattern.range, final_state.env, registry, expr_result.type)
38
+ .then { final_state.add_errors(it) }
39
+ .unify_result(expr_result.with(constraints: residual_cs), expected.type)
40
+ end
41
+
42
+ private
43
+
44
+ # Constraints whose vars are quantified into the new binding's scheme
45
+ # are captured by it; the rest propagate to the enclosing scope.
46
+ def bind_with_residual(pattern_state, expr_state, expr_result, name)
47
+ result = expr_result.apply(pattern_state.env.substitution)
48
+ scheme = generalize(expr_state.env, result.type, result.constraints)
49
+
50
+ result.constraints
51
+ .reject { |c| c.unbound_vars.any? { |v| scheme.quantified.any? { it.id == v.id } } }
52
+ .then { [pattern_state.bind(name, scheme), it] }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,45 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Inference
5
+ module Body
6
+ extend Helpers
7
+ extend self
8
+
9
+ def infer(node, registry, state, expected)
10
+ node => AST::Body(expressions:)
11
+
12
+ *first_expressions, last_expression = expressions
13
+
14
+ first_state, first_cs = first_expressions
15
+ .reduce([state, []]) do |(acc, cs), expr|
16
+ new_state, result = check(
17
+ expr,
18
+ registry,
19
+ acc,
20
+ Expected.infer(state.fresh),
21
+ )
22
+ [new_state, cs + result.constraints]
23
+ end
24
+
25
+ last_state, last_result = check(
26
+ last_expression,
27
+ registry,
28
+ first_state,
29
+ expected,
30
+ )
31
+
32
+ first_cs
33
+ .map { last_state.env.substitution.apply(it) }
34
+ .then do
35
+ last_result
36
+ .with(constraints: it + last_result.constraints)
37
+ .then { |result| [last_state, result] }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+