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,21 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module RecordUpdate
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::RecordUpdate(base:, fields:)
10
+
11
+ Result
12
+ .combine(node, scope:,
13
+ base: analyze_node(base, registry, scope, entry),
14
+ fields: analyze_in_parallel(fields, registry, scope, entry),
15
+ )
16
+ .add_errors(analyze_duplicate_fields(fields, entry))
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module StructDeclaration
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::StructDeclaration(name:)
10
+
11
+ symbol_ref = entry.lookup_type(name).to_ref
12
+
13
+ Result
14
+ .init(node.with(symbol: symbol_ref), scope)
15
+ .add_errors(validate_no_unbound_vars(symbol_ref, registry, entry))
16
+ .add_errors(validate_type_symbol(symbol_ref, registry, entry))
17
+ end
18
+
19
+ private
20
+
21
+ def validate_no_unbound_vars(symbol, registry, entry)
22
+ actual_symbol = registry.lookup(symbol)
23
+
24
+ missing_vars = collect_vars(actual_symbol.record_type, registry)
25
+ .group_by(&:name)
26
+ .reject { |(k, _)| actual_symbol.type_params.map(&:name).include? k }
27
+ .values
28
+ .flatten
29
+
30
+ return [] if missing_vars.empty?
31
+
32
+ [
33
+ Error::UnboundTypeVariable.new(
34
+ entry.name,
35
+ missing_vars.size == 1 ? missing_vars.first.decl_span : actual_symbol.decl_span,
36
+ type_name: symbol.name,
37
+ variables: missing_vars.map(&:name),
38
+ )
39
+ ]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,17 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module Tuple
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::Tuple(items:)
10
+
11
+ analyze_in_sequence(items, registry, scope, entry)
12
+ .with(scope:)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,69 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module TypeDeclaration
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::TypeDeclaration(name:, variants:)
10
+
11
+ symbol_ref = entry.lookup_type(name).to_ref
12
+
13
+ analyze_in_parallel(variants, registry, scope, entry)
14
+ .then { Result.combine(node, scope:, variants: it) }
15
+ .map_node { it.with(symbol: symbol_ref) }
16
+ .add_errors(validate_no_unbound_vars(symbol_ref, registry, entry))
17
+ .add_errors(validate_type_symbol(symbol_ref, registry, entry))
18
+ end
19
+
20
+ private
21
+
22
+ def validate_no_unbound_vars(symbol, registry, entry)
23
+ actual_symbol = registry.lookup(symbol)
24
+
25
+ vars = actual_symbol
26
+ .variants
27
+ .flat_map { collect_vars(it, registry) }
28
+ .group_by(&:name)
29
+
30
+ missing_vars = vars
31
+ .reject { |(k, _)| actual_symbol.type_params.map(&:name).include? k }
32
+ .values
33
+ .flatten
34
+
35
+ return [] if missing_vars.empty?
36
+
37
+ [
38
+ Error::UnboundTypeVariable.new(
39
+ entry.name,
40
+ missing_vars.size == 1 ? missing_vars.first.decl_span : actual_symbol.decl_span,
41
+ type_name: symbol.name,
42
+ variables: missing_vars.map(&:name),
43
+ )
44
+ ]
45
+ end
46
+
47
+ def collect_vars(symbol, registry)
48
+ case symbol
49
+ in Symbol::TypeRef | Symbol::ValueRef
50
+ registry.lookup(symbol)
51
+ .then { collect_vars(it, registry) }
52
+
53
+ in Symbol::Constructor(args:)
54
+ args.flat_map { collect_vars(it, registry) }
55
+
56
+ in Symbol::Variable
57
+ [symbol]
58
+
59
+ in Symbol::TypeApplication(args:)
60
+ args.flat_map { collect_vars(it, registry) }
61
+
62
+ in Symbol::RecordType(row_var:)
63
+ row_var.nil? ? [] : [row_var]
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,27 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module VariableReference
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, _registry, scope, entry)
9
+ node => AST::VariableReference(name:)
10
+
11
+ case scope.lookup(name)
12
+ in nil
13
+ Result
14
+ .init(node.with(symbol: Symbol.var(name, node.range)), scope)
15
+ .add_errors([Error::UndefinedVariable.new(
16
+ entry.name, node.range, var_ref: name,
17
+ candidates: scope.bindings.keys,
18
+ )])
19
+
20
+ in symbol
21
+ Result.init(node.with(symbol:), scope)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,18 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module VariantDeclaration
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, _registry, scope, entry)
9
+ node => AST::VariantDeclaration(name:)
10
+
11
+ node
12
+ .with(symbol: entry.lookup_value(name).to_ref)
13
+ .then { Result.init(it, scope) }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,161 @@
1
+ require 'jade/frontend/semantic_analysis/error'
2
+
3
+ require 'jade/frontend/semantic_analysis/helper'
4
+ require 'jade/frontend/semantic_analysis/module_node'
5
+ require 'jade/frontend/semantic_analysis/import_declaration'
6
+ require 'jade/frontend/semantic_analysis/literal'
7
+ require 'jade/frontend/semantic_analysis/char_literal'
8
+ require 'jade/frontend/semantic_analysis/assign'
9
+ require 'jade/frontend/semantic_analysis/variable_reference'
10
+ require 'jade/frontend/semantic_analysis/constructor_reference'
11
+ require 'jade/frontend/semantic_analysis/body'
12
+ require 'jade/frontend/semantic_analysis/function_declaration'
13
+ require 'jade/frontend/semantic_analysis/function_call'
14
+ require 'jade/frontend/semantic_analysis/keyed_call/validation'
15
+ require 'jade/frontend/semantic_analysis/keyed_call'
16
+ require 'jade/frontend/semantic_analysis/type_declaration'
17
+ require 'jade/frontend/semantic_analysis/variant_declaration'
18
+ require 'jade/frontend/semantic_analysis/interop_import_declaration'
19
+ require 'jade/frontend/semantic_analysis/implementation'
20
+ require 'jade/frontend/semantic_analysis/implementation_function'
21
+ require 'jade/frontend/semantic_analysis/struct_declaration'
22
+ require 'jade/frontend/semantic_analysis/interface_declaration'
23
+ require 'jade/frontend/semantic_analysis/if_then_else'
24
+ require 'jade/frontend/semantic_analysis/member_access'
25
+ require 'jade/frontend/semantic_analysis/qualified_access'
26
+ require 'jade/frontend/semantic_analysis/record_access'
27
+ require 'jade/frontend/semantic_analysis/case_of'
28
+ require 'jade/frontend/semantic_analysis/case_of_branch'
29
+ require 'jade/frontend/semantic_analysis/pattern_wildcard'
30
+ require 'jade/frontend/semantic_analysis/pattern_literal'
31
+ require 'jade/frontend/semantic_analysis/pattern_binding'
32
+ require 'jade/frontend/semantic_analysis/pattern_constructor'
33
+ require 'jade/frontend/semantic_analysis/pattern_record'
34
+ require 'jade/frontend/semantic_analysis/pattern_list'
35
+ require 'jade/frontend/semantic_analysis/lambda'
36
+ require 'jade/frontend/semantic_analysis/grouping'
37
+ require 'jade/frontend/semantic_analysis/list'
38
+ require 'jade/frontend/semantic_analysis/record_literal'
39
+ require 'jade/frontend/semantic_analysis/record_update'
40
+ require 'jade/frontend/semantic_analysis/record_field'
41
+
42
+ module Jade
43
+ module Frontend
44
+ module SemanticAnalysis
45
+ extend self
46
+
47
+ def analyze(entry, registry)
48
+ initialize_scope(entry)
49
+ .then { analyze_node(entry.ast, registry, it, entry) }
50
+ .then { it.errors.any? ? Err[it.errors] : Ok[entry.with(ast: it.node)] }
51
+ end
52
+
53
+ def analyze_repl(ast, registry, scope, entry)
54
+ analyze_node(ast, registry, scope, entry)
55
+ .then { it.errors.any? ? Err[it.errors] : Ok[[it.node, it.scope]] }
56
+ end
57
+
58
+ def analyze_entry(entry, registry)
59
+ analyze(entry, registry)
60
+ end
61
+
62
+ private
63
+
64
+ def initialize_scope(entry)
65
+ entry
66
+ .values
67
+ .reduce(Scope.new) { |acc, (unq_name, sym)| acc.bind(unq_name, sym) }
68
+ end
69
+
70
+ def analyze_node(ast, registry, scope, entry)
71
+ case ast
72
+ in AST::Module then ModuleNode
73
+ in AST::ImportDeclaration then ImportDeclaration
74
+ in AST::InteropImportDeclaration then InteropImportDeclaration
75
+ in AST::Literal then Literal
76
+ in AST::CharLiteral then CharLiteral
77
+ in AST::Assign then Assign
78
+ in AST::VariableReference then VariableReference
79
+ in AST::ConstructorReference then ConstructorReference
80
+ in AST::Body then Body
81
+ in AST::FunctionDeclaration then FunctionDeclaration
82
+ in AST::FunctionCall then FunctionCall
83
+ in AST::KeyedCall then KeyedCall
84
+ in AST::TypeDeclaration then TypeDeclaration
85
+ in AST::VariantDeclaration then VariantDeclaration
86
+ in AST::Implementation then Implementation
87
+ in AST::ImplementationFunction then ImplementationFunction
88
+ in AST::StructDeclaration then StructDeclaration
89
+ in AST::InterfaceDeclaration then InterfaceDeclaration
90
+ in AST::IfThenElse then IfThenElse
91
+ in AST::MemberAccess then MemberAccess
92
+ in AST::QualifiedAccess then QualifiedAccess
93
+ in AST::RecordAccess then RecordAccess
94
+ in AST::CaseOf then CaseOf
95
+ in AST::CaseOfBranch then CaseOfBranch
96
+ in AST::Pattern::Wildcard then PatternWildcard
97
+ in AST::Pattern::Literal then PatternLiteral
98
+ in AST::Pattern::Binding then PatternBinding
99
+ in AST::Pattern::Constructor then PatternConstructor
100
+ in AST::Pattern::Record then PatternRecord
101
+ in AST::Pattern::List then PatternList
102
+ in AST::Lambda then Lambda
103
+ in AST::Grouping then Grouping
104
+ in AST::List then List
105
+ in AST::RecordLiteral then RecordLiteral
106
+ in AST::RecordUpdate then RecordUpdate
107
+ in AST::RecordField then RecordField
108
+ end
109
+ .analyze(ast, registry, scope, entry)
110
+ end
111
+
112
+ Result = Data.define(:node, :errors, :scope) do
113
+ def self.init(node, scope)
114
+ new(node:, errors: [], scope:)
115
+ end
116
+
117
+ # Combine a fixed set of child Results into a parent Result.
118
+ # `children` keys must match the parent node's `with` field
119
+ # names. Errors are unioned; the parent's `scope:` is whatever
120
+ # the caller decides (usually the input scope or a child's).
121
+ def self.combine(node, scope:, **children)
122
+ new(
123
+ node: node.with(**children.transform_values(&:node)),
124
+ errors: children.values.flat_map(&:errors),
125
+ scope:,
126
+ )
127
+ end
128
+
129
+ def add_errors(more)
130
+ with(errors: errors + more)
131
+ end
132
+
133
+ def map_node
134
+ with(node: yield(node))
135
+ end
136
+
137
+ def with_scope(s)
138
+ with(scope: s)
139
+ end
140
+
141
+ def to_result
142
+ errors.any? ? Err[errors] : Ok[node]
143
+ end
144
+ end
145
+
146
+ Scope = Data.define(:bindings) do
147
+ def initialize(bindings: {})
148
+ super
149
+ end
150
+
151
+ def bind(name, symbol)
152
+ with(bindings: bindings.merge(name => symbol))
153
+ end
154
+
155
+ def lookup(name)
156
+ bindings[name]
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,97 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ # Finalize-time pass that rewrites attached dictionary markers in place
5
+ # through the final substitution. Codegen then reads marker.type.id
6
+ # directly — dict_env keys (built from scheme.constraints) and marker
7
+ # ids both pass through the same final substitution, so they match.
8
+ #
9
+ # We do NOT pre-substitute scheme.type/constraints: substitution can map
10
+ # one quantified var to another (e.g. `b → c'` via body unification),
11
+ # which would leave the scheme's `quantified` list and type out of sync
12
+ # for downstream instantiations.
13
+ module Canonicalize
14
+ extend self
15
+
16
+ def run(ast, env, registry)
17
+ walk(ast, env.substitution, registry, env.entry_name)
18
+ env
19
+ end
20
+
21
+ private
22
+
23
+ def walk(node, sub, registry, entry_name)
24
+ case node
25
+ in AST::FunctionCall(callee:, args:)
26
+ canonicalize_dictionaries(node, sub, registry, entry_name)
27
+ walk(callee, sub, registry, entry_name)
28
+ args.each { walk(it, sub, registry, entry_name) }
29
+
30
+ in AST::QualifiedAccess | AST::VariableReference
31
+ canonicalize_dictionaries(node, sub, registry, entry_name)
32
+
33
+ in AST::Module(body:) then walk(body, sub, registry, entry_name)
34
+ in AST::Body(expressions:) then expressions.each { walk(it, sub, registry, entry_name) }
35
+ in AST::FunctionDeclaration(body:) then walk(body, sub, registry, entry_name)
36
+ in AST::Implementation(functions:) then functions.each { walk(it, sub, registry, entry_name) }
37
+ in AST::ImplementationFunction(fn:) then walk(fn, sub, registry, entry_name)
38
+ in AST::Assign(expression:) then walk(expression, sub, registry, entry_name)
39
+ in AST::Lambda(body:) then walk(body, sub, registry, entry_name)
40
+ in AST::Grouping(expression:) then walk(expression, sub, registry, entry_name)
41
+ in AST::List(items:) then items.each { walk(it, sub, registry, entry_name) }
42
+ in AST::RecordLiteral(fields:) then fields.each { walk(it, sub, registry, entry_name) }
43
+ in AST::RecordField(value:) then walk(value, sub, registry, entry_name)
44
+ in AST::RecordUpdate(base:, fields:)
45
+ walk(base, sub, registry, entry_name)
46
+ fields.each { walk(it, sub, registry, entry_name) }
47
+ in AST::RecordAccess(target:) then walk(target, sub, registry, entry_name)
48
+ in AST::IfThenElse(condition:, if_branch:, else_branch:)
49
+ walk(condition, sub, registry, entry_name)
50
+ walk(if_branch, sub, registry, entry_name)
51
+ walk(else_branch, sub, registry, entry_name)
52
+ in AST::CaseOf(expression:, branches:)
53
+ walk(expression, sub, registry, entry_name)
54
+ branches.each { walk(it, sub, registry, entry_name) }
55
+ in AST::CaseOfBranch(body:) then walk(body, sub, registry, entry_name)
56
+
57
+ # Leaves: cannot contain a FunctionCall. Listed explicitly so
58
+ # adding a new node type forces a decision here rather than
59
+ # silently skipping a subtree.
60
+ in AST::Literal |
61
+ AST::CharLiteral |
62
+ AST::ConstructorReference |
63
+ AST::ImportDeclaration |
64
+ AST::InteropImportDeclaration |
65
+ AST::TypeDeclaration |
66
+ AST::StructDeclaration |
67
+ AST::InterfaceDeclaration |
68
+ AST::Placeholder
69
+ nil
70
+ end
71
+ end
72
+
73
+ # Rewrite var-typed dictionary markers through the final substitution.
74
+ # If the var resolved to a concrete type (e.g. `Decodable α` where a
75
+ # pattern-binding unified α with Int), resolve the impl now so codegen
76
+ # can dispatch directly — previously this only handled var-stayed-var
77
+ # and the substituted-to-concrete case crashed codegen's dict lookup.
78
+ def canonicalize_dictionaries(node, sub, registry, entry_name)
79
+ node.dictionaries.each_with_index do |entry, i|
80
+ next unless entry.is_a?(Type::Constraint)
81
+
82
+ applied = sub.apply(entry.type)
83
+ resolved = entry.with(type: applied)
84
+
85
+ if applied.is_a?(Type::Var)
86
+ node.dictionaries[i] = resolved
87
+ else
88
+ Constraints
89
+ .resolve(resolved, registry, entry_name)
90
+ .map { node.dictionaries[i] = it }
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,144 @@
1
+ module Jade
2
+ module Frontend
3
+ module TypeChecking
4
+ module Constraints
5
+ module Deriving
6
+ module Decodable
7
+ extend self
8
+ include Helpers
9
+
10
+ INTERFACE = 'Decode.Decodable'
11
+
12
+ def supports?(interface) = interface == INTERFACE
13
+
14
+ def derive(constraint, registry, entry_name, &lookup)
15
+ case constraint.type
16
+ in Type::Application(constructor: Type::Constructor(name: 'List.List'), args: [inner])
17
+ derive_unary(constraint, inner, 'Decode.list', lookup, entry_name)
18
+
19
+ in Type::Application(constructor: Type::Constructor(name: 'Maybe.Maybe'), args: [inner])
20
+ derive_unary(constraint, inner, 'Decode.nullable', lookup, entry_name)
21
+
22
+ in Type::Application(constructor: Type::Constructor(name:), args:)
23
+ resolved_sym = Symbol
24
+ .type_ref_from_qualified_name(name)
25
+ .then { registry.lookup(it) }
26
+
27
+ case resolved_sym
28
+ in Symbol::Struct
29
+ derive_struct(constraint, resolved_sym, args, registry, lookup, entry_name)
30
+
31
+ else
32
+ failed(constraint, entry_name)
33
+ end
34
+
35
+ in Type::AnonymousRecord(fields:)
36
+ derive_anonymous_record(constraint, fields, lookup, entry_name)
37
+
38
+ else
39
+ failed(constraint, entry_name)
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def failed(constraint, entry_name)
46
+ Err[
47
+ Error::DerivationFailed.new(
48
+ entry_name,
49
+ constraint.origin&.range,
50
+ constraint:,
51
+ trace: [],
52
+ )
53
+ ]
54
+ end
55
+
56
+ def derive_unary(constraint, inner_type, stdlib_fn, lookup, entry_name)
57
+ dep = Type.constraint(INTERFACE, inner_type, nil)
58
+
59
+ resolve_dep(dep, lookup, entry_name).and_then do |dep_impl|
60
+ body = [:call,
61
+ [:stdlib_fn, stdlib_fn],
62
+ [
63
+ [:impl_arg, 0, 'decoder'],
64
+ ],
65
+ ]
66
+
67
+ Ok[implementation(constraint, body, [dep_impl])]
68
+ end
69
+ end
70
+
71
+ def derive_struct(constraint, struct_sym, type_args, registry, lookup, entry_name)
72
+ fields = struct_fields(struct_sym, type_args, registry)
73
+
74
+ [:struct_constructor, struct_sym.qualified_name, fields.size]
75
+ .then { derive_record(constraint, fields, it, lookup, entry_name) }
76
+ end
77
+
78
+ def derive_anonymous_record(constraint, fields, lookup, entry_name)
79
+ keys = fields.keys.map(&:to_s)
80
+
81
+ [:anon_record_constructor, keys]
82
+ .then { derive_record(constraint, fields.to_a, it, lookup, entry_name) }
83
+ end
84
+
85
+ def derive_record(constraint, fields, constructor_ref, lookup, entry_name)
86
+ field_deps = fields.map do |_, field_type|
87
+ Type.constraint(INTERFACE, field_type, nil)
88
+ end
89
+
90
+ resolved_deps = field_deps.map do |dep|
91
+ resolve_dep(dep, lookup, entry_name) => Ok[impl]
92
+ impl
93
+ end
94
+
95
+ seed = [:call, [:stdlib_fn, 'Decode.succeed'], [constructor_ref]]
96
+
97
+ body = fields.each_with_index.reduce(seed) do |acc, ((field_name, _), idx)|
98
+ field_decoder = [:call,
99
+ [:stdlib_fn, 'Decode.field'],
100
+ [
101
+ field_name.to_s,
102
+ [:impl_arg, idx, 'decoder'],
103
+ ],
104
+ ]
105
+
106
+ [:call, [:stdlib_fn, 'Decode.and_map'], [acc, field_decoder]]
107
+ end
108
+
109
+ Ok[implementation(constraint, body, resolved_deps)]
110
+ end
111
+
112
+ # Free-var inner constraints fall back to the constraint marker
113
+ # itself — codegen later resolves it from the caller's dict env.
114
+ # Without this, `Decodable(List(a))` with `a` free would bail
115
+ # with UnresolvedConstraint.
116
+ def resolve_dep(dep, lookup, entry_name)
117
+ lookup
118
+ .call(dep)
119
+ .on_err(Error::UnresolvedConstraint) {
120
+ dep.type.is_a?(Type::Var) ? Ok[dep] : Err[it]
121
+ }
122
+ end
123
+
124
+ def implementation(constraint, body, deps)
125
+ decoder_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: { 'decoder' => decoder_fn },
134
+ deps:,
135
+ extends: [],
136
+ decl_span: nil,
137
+ )
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end