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,315 @@
1
+ require 'jade/stdlib/intrinsics'
2
+ require 'jade/decode'
3
+
4
+ module Jade
5
+ module Stdlib
6
+ module Decode
7
+ extend Intrinsics
8
+
9
+ import Maybe
10
+ import Result
11
+ import List
12
+ import Dict
13
+
14
+ union :DecodeError
15
+ variant :MissingField, of: :DecodeError, args: ['String']
16
+ variant :WrongType, of: :DecodeError, args: ['String', 'String']
17
+ variant :AtField, of: :DecodeError, args: ['String', 'DecodeError']
18
+ variant :AtIndex, of: :DecodeError, args: ['Int', 'DecodeError']
19
+ variant :Multiple, of: :DecodeError, args: ['List(DecodeError)']
20
+ variant :Custom, of: :DecodeError, args: ['String']
21
+
22
+ union :Value
23
+ union :Decoder, 'a'
24
+
25
+ interface(
26
+ 'Decodable',
27
+ 'a',
28
+ { 'decoder' => 'Decoder(a)' },
29
+ )
30
+
31
+ # Primitives
32
+
33
+ function('string', {}, 'Decoder(String)') {
34
+ Jade::Decode::Decoder[Jade::Decode::Desc::Str[]]
35
+ }
36
+
37
+ function('int', {}, 'Decoder(Int)') {
38
+ Jade::Decode::Decoder[Jade::Decode::Desc::Int[]]
39
+ }
40
+
41
+ function('float', {}, 'Decoder(Float)') {
42
+ Jade::Decode::Decoder[Jade::Decode::Desc::Flt[]]
43
+ }
44
+
45
+ function('bool', {}, 'Decoder(Bool)') {
46
+ Jade::Decode::Decoder[Jade::Decode::Desc::Bool[]]
47
+ }
48
+
49
+ # Structural
50
+
51
+ function(
52
+ 'nullable',
53
+ { decoder: 'Decoder(a)' },
54
+ 'Decoder(Maybe(a))',
55
+ ) { |decoder|
56
+ Jade::Decode::Decoder[Jade::Decode::Desc::Nullable[decoder.desc]]
57
+ }
58
+
59
+ function(
60
+ 'field',
61
+ { key: 'String', decoder: 'Decoder(a)' },
62
+ 'Decoder(a)',
63
+ ) { |key, decoder|
64
+ Jade::Decode::Decoder[Jade::Decode::Desc::Field[key, decoder.desc]]
65
+ }
66
+
67
+ function(
68
+ 'optional_field',
69
+ { key: 'String', decoder: 'Decoder(a)' },
70
+ 'Decoder(Maybe(a))',
71
+ ) { |key, decoder|
72
+ Jade::Decode::Decoder[Jade::Decode::Desc::OptField[key, decoder.desc]]
73
+ }
74
+
75
+ function(
76
+ 'index',
77
+ { i: 'Int', decoder: 'Decoder(a)' },
78
+ 'Decoder(a)',
79
+ ) { |i, decoder|
80
+ Jade::Decode::Decoder[Jade::Decode::Desc::Idx[i, decoder.desc]]
81
+ }
82
+
83
+ function(
84
+ 'list',
85
+ { decoder: 'Decoder(a)' },
86
+ 'Decoder(List(a))',
87
+ ) { |decoder|
88
+ Jade::Decode::Decoder[Jade::Decode::Desc::Lst[decoder.desc]]
89
+ }
90
+
91
+ # Decodes either a Hash (natural Ruby/JSON object form) or a list
92
+ # of `[k, v]` pairs (what Encode.dict emits — also the only shape
93
+ # that round-trips non-String key types).
94
+ function(
95
+ 'dict',
96
+ { k_dec: 'Decoder(k)', v_dec: 'Decoder(v)' },
97
+ 'Decoder(Dict(k, v))',
98
+ ) { |k_dec, v_dec|
99
+ Jade::Decode::Decoder[Jade::Decode::Desc::Dct[k_dec.desc, v_dec.desc]]
100
+ }
101
+
102
+ # Mapping
103
+
104
+ function(
105
+ 'map',
106
+ { decoder: 'Decoder(a)', fn: 'a -> b' },
107
+ 'Decoder(b)',
108
+ ) { |decoder, fn|
109
+ Jade::Decode::Decoder[Jade::Decode::Desc::Map[fn, decoder.desc]]
110
+ }
111
+
112
+ # Pipeline
113
+
114
+ function(
115
+ 'succeed',
116
+ { value: 'a' },
117
+ 'Decoder(a)',
118
+ ) { |value|
119
+ Jade::Decode::Decoder[Jade::Decode::Desc::Succeed[value]]
120
+ }
121
+
122
+ function(
123
+ 'and_map',
124
+ { wrapped: 'Decoder(a -> b)', decoder: 'Decoder(a)' },
125
+ 'Decoder(b)',
126
+ ) { |wrapped, decoder|
127
+ Jade::Decode::Decoder[Jade::Decode::Desc::AndMap[wrapped.desc, decoder.desc]]
128
+ }
129
+
130
+ function(
131
+ 'required',
132
+ { wrapped: 'Decoder(a -> b)', key: 'String', field_decoder: 'Decoder(a)' },
133
+ 'Decoder(b)',
134
+ ) { |wrapped, key, field_decoder|
135
+ Jade::Decode::Desc::Field[key, field_decoder.desc]
136
+ .then { Jade::Decode::Decoder[Jade::Decode::Desc::AndMap[wrapped.desc, it]] }
137
+ }
138
+
139
+ function(
140
+ 'optional',
141
+ {
142
+ wrapped: 'Decoder(a -> b)',
143
+ key: 'String',
144
+ field_decoder: 'Decoder(a)',
145
+ default: 'a',
146
+ },
147
+ 'Decoder(b)',
148
+ ) { |wrapped, key, field_decoder, default|
149
+ Jade::Decode::Desc::Optional[key, field_decoder.desc, default]
150
+ .then { Jade::Decode::Decoder[Jade::Decode::Desc::AndMap[wrapped.desc, it]] }
151
+ }
152
+
153
+ function(
154
+ 'sequence',
155
+ { decoders: 'List(Decoder(a))' },
156
+ 'Decoder(List(a))',
157
+ ) { |decoders|
158
+ Jade::Decode::Decoder[Jade::Decode::Desc::Sequence[decoders.map(&:desc)]]
159
+ }
160
+
161
+ function(
162
+ 'one_of',
163
+ { decoders: 'List(Decoder(a))' },
164
+ 'Decoder(a)',
165
+ ) { |decoders|
166
+ Jade::Decode::Decoder[Jade::Decode::Desc::OneOf[decoders.map(&:desc)]]
167
+ }
168
+
169
+ function(
170
+ 'and_then',
171
+ { decoder: 'Decoder(a)', fn: 'a -> Decoder(b)' },
172
+ 'Decoder(b)',
173
+ ) { |decoder, fn|
174
+ Jade::Decode::Decoder[Jade::Decode::Desc::AndThen[fn, decoder.desc]]
175
+ }
176
+
177
+ function(
178
+ 'fail',
179
+ { msg: 'String' },
180
+ 'Decoder(a)',
181
+ ) { |msg|
182
+ Jade::Decode::Decoder[Jade::Decode::Desc::Fail[msg]]
183
+ }
184
+
185
+ function(
186
+ 'from_result',
187
+ { r: 'Result(a, String)' },
188
+ 'Decoder(a)',
189
+ ) { |r|
190
+ case r
191
+ in Jade::Result::Ok[v] then Jade::Decode::Decoder[Jade::Decode::Desc::Succeed[v]]
192
+ in Jade::Result::Err[e] then Jade::Decode::Decoder[Jade::Decode::Desc::Fail[e]]
193
+ end
194
+ }
195
+
196
+ # Entry points
197
+
198
+ function(
199
+ 'decode',
200
+ { decoder: 'Decoder(a)', value: 'Value' },
201
+ 'Result(a, DecodeError)',
202
+ ) { |decoder, value|
203
+ Jade::Decode::Runner.run(decoder, value)
204
+ }
205
+
206
+ function(
207
+ 'decode_string',
208
+ { decoder: 'Decoder(a)', json: 'String' },
209
+ 'Result(a, DecodeError)',
210
+ ) { |decoder, json|
211
+ Jade::Decode::Runner.from_json(decoder, json)
212
+ }
213
+
214
+ # Constrained helpers — pick the decoder via Decodable.
215
+
216
+ function(
217
+ 'from_value',
218
+ { value: 'Value' },
219
+ 'Result(a, DecodeError)',
220
+ constraints: [['Decode.Decodable', 'a']],
221
+ body: Symbol::DerivedFunction.new(
222
+ params: ['value'],
223
+ body: [:call,
224
+ [:stdlib_fn, 'Decode.decode'],
225
+ [
226
+ [:impl_arg, 0, 'decoder'],
227
+ [:var, 'value'],
228
+ ],
229
+ ],
230
+ ),
231
+ )
232
+
233
+ function(
234
+ 'from_json',
235
+ { json: 'String' },
236
+ 'Result(a, DecodeError)',
237
+ constraints: [['Decode.Decodable', 'a']],
238
+ body: Symbol::DerivedFunction.new(
239
+ params: ['json'],
240
+ body: [:call,
241
+ [:stdlib_fn, 'Decode.decode_string'],
242
+ [
243
+ [:impl_arg, 0, 'decoder'],
244
+ [:var, 'json'],
245
+ ],
246
+ ],
247
+ ),
248
+ )
249
+
250
+ # Builder seed for `[name, ...args]`-shape union decoding. Compose
251
+ # with `variant` via `|>`:
252
+ # Decode.type_
253
+ # |> Decode.variant("A", ...)
254
+ # |> Decode.variant("B", ...)
255
+ function('type_', {}, 'Decoder(a)') {
256
+ Jade::Decode::Decoder[Jade::Decode::Desc::Variant[{}]]
257
+ }
258
+
259
+ function(
260
+ 'variant',
261
+ { builder: 'Decoder(a)', name: 'String', decoder: 'Decoder(a)' },
262
+ 'Decoder(a)',
263
+ ) { |builder, name, decoder|
264
+ builder.desc => Jade::Decode::Desc::Variant[cases]
265
+ cases
266
+ .merge(name => decoder.desc)
267
+ .then { Jade::Decode::Desc::Variant[it] }
268
+ .then { Jade::Decode::Decoder[it] }
269
+ }
270
+
271
+ function(
272
+ 'tuple',
273
+ { a: 'Decoder(a)', b: 'Decoder(b)' },
274
+ 'Decoder(Tuple2(a, b))',
275
+ ) { |da, db|
276
+ Jade::Decode::Desc::Succeed[Jade::Tuple::Tuple2.method(:[]).curry(2)]
277
+ .then { Jade::Decode::Desc::AndMap[it, Jade::Decode::Desc::Idx[0, da.desc]] }
278
+ .then { Jade::Decode::Desc::AndMap[it, Jade::Decode::Desc::Idx[1, db.desc]] }
279
+ .then { Jade::Decode::Decoder[it] }
280
+ }
281
+
282
+ function(
283
+ 'tuple3',
284
+ { a: 'Decoder(a)', b: 'Decoder(b)', c: 'Decoder(c)' },
285
+ 'Decoder(Tuple3(a, b, c))',
286
+ ) { |da, db, dc|
287
+ Jade::Decode::Desc::Succeed[Jade::Tuple::Tuple3.method(:[]).curry(3)]
288
+ .then { Jade::Decode::Desc::AndMap[it, Jade::Decode::Desc::Idx[0, da.desc]] }
289
+ .then { Jade::Decode::Desc::AndMap[it, Jade::Decode::Desc::Idx[1, db.desc]] }
290
+ .then { Jade::Decode::Desc::AndMap[it, Jade::Decode::Desc::Idx[2, dc.desc]] }
291
+ .then { Jade::Decode::Decoder[it] }
292
+ }
293
+
294
+ function(
295
+ 'tuple4',
296
+ { a: 'Decoder(a)', b: 'Decoder(b)', c: 'Decoder(c)', d: 'Decoder(d)' },
297
+ 'Decoder(Tuple4(a, b, c, d))',
298
+ ) { |da, db, dc, dd|
299
+ Jade::Decode::Desc::Succeed[Jade::Tuple::Tuple4.method(:[]).curry(4)]
300
+ .then { Jade::Decode::Desc::AndMap[it, Jade::Decode::Desc::Idx[0, da.desc]] }
301
+ .then { Jade::Decode::Desc::AndMap[it, Jade::Decode::Desc::Idx[1, db.desc]] }
302
+ .then { Jade::Decode::Desc::AndMap[it, Jade::Decode::Desc::Idx[2, dc.desc]] }
303
+ .then { Jade::Decode::Desc::AndMap[it, Jade::Decode::Desc::Idx[3, dd.desc]] }
304
+ .then { Jade::Decode::Decoder[it] }
305
+ }
306
+
307
+ # Primitive Decodable impls.
308
+
309
+ implementation('Decodable', 'Basics.Int', 'decoder' => 'int')
310
+ implementation('Decodable', 'Basics.Float', 'decoder' => 'float')
311
+ implementation('Decodable', 'Basics.Bool', 'decoder' => 'bool')
312
+ implementation('Decodable', 'String.String', 'decoder' => 'string')
313
+ end
314
+ end
315
+ end
@@ -0,0 +1,134 @@
1
+ require 'jade/stdlib/intrinsics'
2
+
3
+ module Jade
4
+ module Stdlib
5
+ module Dict
6
+ extend Intrinsics
7
+
8
+ import Basics
9
+ import Maybe
10
+ import List
11
+ import Tuple
12
+
13
+ union :Dict, 'k', 'v'
14
+
15
+ native_type :Dict, Jade::Dict::Dict
16
+
17
+ implementation('Eq', 'Dict', '(==)' => 'dict_eq')
18
+
19
+ function(:empty, {}, 'Dict(k, v)')
20
+
21
+ function(
22
+ :singleton,
23
+ { key: 'k', value: 'v' },
24
+ 'Dict(k, v)',
25
+ constraints: [['Basics.Eq', 'k']],
26
+ )
27
+
28
+ function(:"empty?", { dict: 'Dict(k, v)' }, 'Bool')
29
+ function(:size, { dict: 'Dict(k, v)' }, 'Int')
30
+
31
+ function(
32
+ :get,
33
+ { dict: 'Dict(k, v)', key: 'k' },
34
+ 'Maybe(v)',
35
+ constraints: [['Basics.Eq', 'k']],
36
+ )
37
+
38
+ function(
39
+ :"member?",
40
+ { dict: 'Dict(k, v)', key: 'k' },
41
+ 'Bool',
42
+ constraints: [['Basics.Eq', 'k']],
43
+ )
44
+
45
+ function(
46
+ :insert,
47
+ { dict: 'Dict(k, v)', key: 'k', value: 'v' },
48
+ 'Dict(k, v)',
49
+ constraints: [['Basics.Eq', 'k']],
50
+ )
51
+
52
+ function(
53
+ :remove,
54
+ { dict: 'Dict(k, v)', key: 'k' },
55
+ 'Dict(k, v)',
56
+ constraints: [['Basics.Eq', 'k']],
57
+ )
58
+
59
+ function(
60
+ :update,
61
+ { dict: 'Dict(k, v)', key: 'k', fn: 'Maybe(v) -> Maybe(v)' },
62
+ 'Dict(k, v)',
63
+ constraints: [['Basics.Eq', 'k']],
64
+ ) do |dict, key, fn|
65
+ current = dict.hash.key?(key) ? Jade::Maybe::Just[dict.hash[key]] : Jade::Maybe::Nothing[]
66
+ case fn.call(current)
67
+ in Jade::Maybe::Just[v] then Jade::Dict::Dict[dict.hash.merge(key => v)]
68
+ in Jade::Maybe::Nothing then Jade::Dict::Dict[dict.hash.except(key)]
69
+ end
70
+ end
71
+
72
+ function(:keys, { dict: 'Dict(k, v)' }, 'List(k)')
73
+ function(:values, { dict: 'Dict(k, v)' }, 'List(v)')
74
+ function(:to_list, { dict: 'Dict(k, v)' }, 'List(Tuple2(k, v))')
75
+
76
+ function(
77
+ :from_list,
78
+ { pairs: 'List(Tuple2(k, v))' },
79
+ 'Dict(k, v)',
80
+ constraints: [['Basics.Eq', 'k']],
81
+ )
82
+
83
+ function(
84
+ :map,
85
+ { dict: 'Dict(k, v)', fn: 'k, v -> v2' },
86
+ 'Dict(k, v2)',
87
+ ) do |dict, fn|
88
+ dict.hash
89
+ .each_with_object({}) { |(k, v), h| h[k] = fn.call(k, v) }
90
+ .then { Jade::Dict::Dict[it] }
91
+ end
92
+
93
+ function(
94
+ :filter,
95
+ { dict: 'Dict(k, v)', fn: 'k, v -> Bool' },
96
+ 'Dict(k, v)',
97
+ ) do |dict, fn|
98
+ dict.hash
99
+ .select { |k, v| fn.call(k, v) }
100
+ .then { Jade::Dict::Dict[it] }
101
+ end
102
+
103
+ function(
104
+ :fold,
105
+ { dict: 'Dict(k, v)', initial: 'b', fn: 'k, v, b -> b' },
106
+ 'b',
107
+ ) do |dict, initial, fn|
108
+ dict.hash.reduce(initial) { |acc, (k, v)| fn.call(k, v, acc) }
109
+ end
110
+
111
+ function(
112
+ :union,
113
+ { left: 'Dict(k, v)', right: 'Dict(k, v)' },
114
+ 'Dict(k, v)',
115
+ constraints: [['Basics.Eq', 'k']],
116
+ )
117
+
118
+ function(
119
+ :merge,
120
+ { left: 'Dict(k, v)', right: 'Dict(k, v)', combine: 'v, v -> v' },
121
+ 'Dict(k, v)',
122
+ constraints: [['Basics.Eq', 'k']],
123
+ ) do |left, right, combine|
124
+ right.hash
125
+ .merge(left.hash) { |_k, r_val, l_val| combine.call(l_val, r_val) }
126
+ .then { Jade::Dict::Dict[it] }
127
+ end
128
+
129
+ default_importing('Dict')
130
+
131
+ function('dict_eq', { a: 'Dict(k, v)', b: 'Dict(k, v)' }, 'Bool')
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,143 @@
1
+ require 'json'
2
+ require 'jade/stdlib/intrinsics'
3
+
4
+ module Jade
5
+ module Stdlib
6
+ module Encode
7
+ extend Intrinsics
8
+
9
+ import Maybe
10
+ import List
11
+ import Tuple
12
+ import Dict
13
+
14
+ interface(
15
+ 'Encodable',
16
+ 'a',
17
+ { 'encoder' => 'a -> Value' },
18
+ )
19
+
20
+ # Primitives
21
+
22
+ function('string', { s: 'String' }, 'Value') { it.dup }
23
+ function('int', { i: 'Int' }, 'Value') { it }
24
+ function('float', { f: 'Float' }, 'Value') { it.to_f }
25
+ function('bool', { b: 'Bool' }, 'Value') { it }
26
+ function('null', {}, 'Value') { nil }
27
+
28
+ # Structural
29
+
30
+ function(
31
+ 'nullable',
32
+ { encoder: 'a -> Value', maybe: 'Maybe(a)' },
33
+ 'Value',
34
+ ) { |encoder, maybe|
35
+ case maybe
36
+ in Jade::Maybe::Just[v] then encoder.call(v)
37
+ in Jade::Maybe::Nothing then nil
38
+ end
39
+ }
40
+
41
+ function(
42
+ 'list',
43
+ { encoder: 'a -> Value', items: 'List(a)' },
44
+ 'Value',
45
+ ) { |encoder, items|
46
+ items.map { encoder.call(it) }
47
+ }
48
+
49
+ # Dict encodes as a list of `[k_encoded, v_encoded]` pairs — JSON
50
+ # objects only support String keys, so list-of-pairs is the only
51
+ # shape that survives non-String key types round-trip.
52
+ function(
53
+ 'dict',
54
+ { k_enc: 'k -> Value', v_enc: 'v -> Value', dict: 'Dict(k, v)' },
55
+ 'Value',
56
+ ) { |k_enc, v_enc, dict|
57
+ dict.hash.map { |k, v| [k_enc.call(k), v_enc.call(v)] }
58
+ }
59
+
60
+ function(
61
+ 'object',
62
+ { pairs: 'List(Tuple2(String, Value))' },
63
+ 'Value',
64
+ ) { |pairs|
65
+ pairs
66
+ .each_with_object({}) { |pair, acc| acc[pair._1] = pair._2 }
67
+ }
68
+
69
+ function(
70
+ 'field',
71
+ { key: 'String', encoder: 'a -> Value', value: 'a' },
72
+ 'Tuple2(String, Value)',
73
+ ) { |key, encoder, value|
74
+ Jade::Tuple::Tuple2[key.dup, encoder.call(value)]
75
+ }
76
+
77
+ function(
78
+ 'encode_to_string',
79
+ { value: 'Value' },
80
+ 'String',
81
+ ) { |value|
82
+ JSON.generate(value)
83
+ }
84
+
85
+ # Produces `[name, *args]` — the `[name, ...args]`-shape that
86
+ # boundary Task outcomes use, here generalised so users can encode
87
+ # their own union variants through the same shape. Pair with
88
+ # Decode.type_ + Decode.variant on the decode side.
89
+ function(
90
+ 'variant',
91
+ { name: 'String', args: 'List(Value)' },
92
+ 'Value',
93
+ ) { |name, args| [name, *args] }
94
+
95
+ function(
96
+ 'tuple',
97
+ { a_enc: 'a -> Value', b_enc: 'b -> Value', t: 'Tuple2(a, b)' },
98
+ 'Value',
99
+ ) { |a_enc, b_enc, t| [a_enc.call(t._1), b_enc.call(t._2)] }
100
+
101
+ function(
102
+ 'tuple3',
103
+ { a_enc: 'a -> Value', b_enc: 'b -> Value', c_enc: 'c -> Value', t: 'Tuple3(a, b, c)' },
104
+ 'Value',
105
+ ) { |a_enc, b_enc, c_enc, t| [a_enc.call(t._1), b_enc.call(t._2), c_enc.call(t._3)] }
106
+
107
+ function(
108
+ 'tuple4',
109
+ {
110
+ a_enc: 'a -> Value', b_enc: 'b -> Value',
111
+ c_enc: 'c -> Value', d_enc: 'd -> Value',
112
+ t: 'Tuple4(a, b, c, d)',
113
+ },
114
+ 'Value',
115
+ ) { |a_enc, b_enc, c_enc, d_enc, t|
116
+ [a_enc.call(t._1), b_enc.call(t._2), c_enc.call(t._3), d_enc.call(t._4)]
117
+ }
118
+
119
+ # Constrained — picks the encoder via Encodable.
120
+
121
+ function(
122
+ 'encode',
123
+ { x: 'a' },
124
+ 'Value',
125
+ constraints: [['Encode.Encodable', 'a']],
126
+ body: Symbol::DerivedFunction.new(
127
+ params: ['x'],
128
+ body: [:call,
129
+ [:impl_arg, 0, 'encoder'],
130
+ [[:var, 'x']],
131
+ ],
132
+ ),
133
+ )
134
+
135
+ # Primitive Encodable impls.
136
+
137
+ implementation('Encodable', 'Basics.Int', 'encoder' => 'int')
138
+ implementation('Encodable', 'Basics.Float', 'encoder' => 'float')
139
+ implementation('Encodable', 'Basics.Bool', 'encoder' => 'bool')
140
+ implementation('Encodable', 'String.String', 'encoder' => 'string')
141
+ end
142
+ end
143
+ end