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,8 @@
1
+ module Jade
2
+ module Symbol
3
+ TypeApplication = Data.define(:constructor, :args, :span) do
4
+ include Base
5
+ end
6
+
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module Jade
2
+ module Symbol
3
+ TypeRef = Data.define(:module_name, :name) do
4
+ include Base
5
+
6
+ def to_ref
7
+ self
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Jade
2
+ module Symbol
3
+ Union = Data.define(:module_name, :name, :type_params, :variants, :decl_span) do
4
+ include Base
5
+
6
+ def to_ref
7
+ TypeRef[module_name, name]
8
+ end
9
+
10
+ def constructor_refs
11
+ variants
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Jade
2
+ module Symbol
3
+ ValueRef = Data.define(:module_name, :name) do
4
+ include Symbol
5
+
6
+ def to_ref
7
+ self
8
+ end
9
+
10
+ def qualified_name
11
+ [module_name, name].join('.')
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module Jade
2
+ module Symbol
3
+ Variable = Data.define(:name, :decl_span) do
4
+ include Base
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module Jade
2
+ module Symbol
3
+ Variant = Data.define(:module_name, :name, :args, :union, :decl_span) do
4
+ include Base
5
+
6
+ def to_ref
7
+ ValueRef[module_name, name]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,162 @@
1
+ require 'jade/symbol/base'
2
+ require 'jade/symbol/parser'
3
+
4
+ require 'jade/symbol/anonymous_record'
5
+ require 'jade/symbol/constructor'
6
+ require 'jade/symbol/derived_function'
7
+ require 'jade/symbol/function'
8
+ require 'jade/symbol/function_type'
9
+ require 'jade/symbol/implementation'
10
+ require 'jade/symbol/implementation_template'
11
+ require 'jade/symbol/interface'
12
+ require 'jade/symbol/interface_function'
13
+ require 'jade/symbol/interop_function'
14
+ require 'jade/symbol/lambda'
15
+ require 'jade/symbol/record_type'
16
+ require 'jade/symbol/stdlib_function'
17
+ require 'jade/symbol/stdlib_implementation'
18
+ require 'jade/symbol/struct'
19
+ require 'jade/symbol/type_application'
20
+ require 'jade/symbol/partial_application'
21
+ require 'jade/symbol/type_ref'
22
+ require 'jade/symbol/union'
23
+ require 'jade/symbol/variant'
24
+ require 'jade/symbol/value_ref'
25
+ require 'jade/symbol/variable'
26
+
27
+ module Jade
28
+ module Symbol
29
+ extend self
30
+
31
+ def module_name(qualified_name)
32
+ *module_parts, _ = qualified_name
33
+ module_parts.join('.')
34
+ end
35
+
36
+ def unqualified_name(qualified_name)
37
+ qualified_name.split('.').last
38
+ end
39
+
40
+ def anonymous_record(fields, row_var = nil)
41
+ fail('fields is expected to be an array') unless fields.is_a?(Array)
42
+
43
+ AnonymousRecord[fields, row_var]
44
+ end
45
+
46
+ def record_type(fields, row_var)
47
+ fail('fields is expected to be a hash') unless fields.is_a?(Hash)
48
+
49
+ RecordType[fields, row_var]
50
+ end
51
+
52
+ def union(name, type_params, variants, span)
53
+ Union[nil, name, type_params, variants.map(&:to_ref), span]
54
+ end
55
+
56
+ def variant(name, args, union, span)
57
+ Variant[nil, name, args, union, span]
58
+ end
59
+
60
+ def constructor(name, args, parent, span)
61
+ Constructor[nil, name, args, parent, span]
62
+ end
63
+
64
+ def predeclared_constructor(name, span)
65
+ Constructor[nil, name, [], nil, span]
66
+ end
67
+
68
+ def lambda(arity)
69
+ Lambda[arity]
70
+ end
71
+
72
+ def type_ref(module_name, name)
73
+ TypeRef[module_name, name]
74
+ end
75
+
76
+ def type_ref_from_qualified_name(q_name)
77
+ *qualified_parts, name = q_name.split('.')
78
+ TypeRef[qualified_parts.join('.'), name]
79
+ end
80
+
81
+ def value_ref(module_name, name)
82
+ ValueRef[module_name, name]
83
+ end
84
+
85
+ def var(name, span)
86
+ Variable[name, span]
87
+ end
88
+
89
+ def predeclared_function(name, decl_span = nil)
90
+ Function[nil, name, nil, nil, decl_span]
91
+ end
92
+
93
+ def function(name, params, return_type, decl_span = nil)
94
+ Function[nil, name, params, return_type, decl_span]
95
+ end
96
+
97
+ def function_type(params, return_type)
98
+ FunctionType[params, return_type]
99
+ end
100
+
101
+ def stdlib_function(name, params, return_type, codegen, constraints: [])
102
+ StdlibFunction[nil, name, params, return_type, codegen, constraints]
103
+ end
104
+
105
+ def predeclared_interop_function(name)
106
+ InteropFunction[nil, name, [], nil, nil, [], nil]
107
+ end
108
+
109
+ def interop_function(name, params, return_type, interop_module_name, constraints: [])
110
+ InteropFunction[nil, name, params, return_type, interop_module_name, constraints, nil]
111
+ end
112
+
113
+ def type_application(constructor, args, span)
114
+ TypeApplication[constructor, args, span]
115
+ end
116
+
117
+ def partial_application(constructor, args, span)
118
+ PartialApplication[constructor, args, span]
119
+ end
120
+
121
+ def predeclared_struct(name, type_params, span)
122
+ Struct[nil, name, type_params, nil, span]
123
+ end
124
+
125
+ def interface(name, type_var, functions, default, span)
126
+ Interface[nil, name, type_var, functions, default, span]
127
+ end
128
+
129
+ def interface_function(name, inteface, params, return_type, span)
130
+ InterfaceFunction[nil, name, inteface, params, return_type, span]
131
+ end
132
+
133
+ def implementation(
134
+ interface,
135
+ type,
136
+ type_params,
137
+ constraints,
138
+ functions,
139
+ deps,
140
+ span,
141
+ extends: []
142
+ )
143
+ Implementation[
144
+ nil,
145
+ interface,
146
+ type,
147
+ type_params,
148
+ constraints,
149
+ functions,
150
+ deps,
151
+ extends,
152
+ span,
153
+ ]
154
+ end
155
+
156
+ def parse(annotation)
157
+ Lexer
158
+ .tokenize(Source.new(uri: nil, text: annotation))
159
+ .then { Parser.parse(it) }
160
+ end
161
+ end
162
+ end
data/lib/jade/task.rb ADDED
@@ -0,0 +1,103 @@
1
+ require 'jade/tasks'
2
+
3
+ module Jade
4
+ module Task
5
+ Literal = Data.define(:result) do
6
+ include Task
7
+
8
+ def run
9
+ result
10
+ end
11
+ end
12
+
13
+ Dispatch = Data.define(:task_def, :args) do
14
+ include Task
15
+
16
+ def run
17
+ Jade::Tasks.dispatch(task_def, *args)
18
+ end
19
+ end
20
+
21
+ Map = Data.define(:task, :fn) do
22
+ include Task
23
+
24
+ def run
25
+ case task.run
26
+ in Jade::Result::Ok[value] then Jade::Result::Ok[fn.call(value)]
27
+ in Jade::Result::Err => err then err
28
+ end
29
+ end
30
+ end
31
+
32
+ AndThen = Data.define(:task, :fn) do
33
+ include Task
34
+
35
+ def run
36
+ case task.run
37
+ in Jade::Result::Ok[value] then fn.call(value).run
38
+ in Jade::Result::Err => err then err
39
+ end
40
+ end
41
+ end
42
+
43
+ OnError = Data.define(:task, :fn) do
44
+ include Task
45
+
46
+ def run
47
+ case task.run
48
+ in Jade::Result::Ok => ok then ok
49
+ in Jade::Result::Err[error] then fn.call(error).run
50
+ end
51
+ end
52
+ end
53
+
54
+ MapError = Data.define(:task, :fn) do
55
+ include Task
56
+
57
+ def run
58
+ case task.run
59
+ in Jade::Result::Ok => ok then ok
60
+ in Jade::Result::Err[error] then Jade::Result::Err[fn.call(error)]
61
+ end
62
+ end
63
+ end
64
+
65
+ Sequence = Data.define(:tasks) do
66
+ include Task
67
+
68
+ def run
69
+ values = []
70
+ tasks.each do |task|
71
+ case task.run
72
+ in Jade::Result::Ok[value] then values << value
73
+ in Jade::Result::Err => err then return err
74
+ end
75
+ end
76
+ Jade::Result::Ok[values]
77
+ end
78
+ end
79
+
80
+ Decoded = Data.define(:task, :ok_decoder, :err_decoder) do
81
+ include Task
82
+
83
+ def run
84
+ case task.run
85
+ in Jade::Result::Ok[value]
86
+ Jade::Result::Ok[decode(ok_decoder, value)]
87
+ in Jade::Result::Err[error]
88
+ Jade::Result::Err[decode(err_decoder, error)]
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def decode(decoder, value)
95
+ case Jade::Decode::Runner.run(decoder, value)
96
+ in Jade::Result::Ok[v] then v
97
+ in Jade::Result::Err[e] then fail Jade::Interop::DecodeError.new(e, value)
98
+ end
99
+ end
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,266 @@
1
+ require 'rspec/expectations'
2
+
3
+ require 'jade/tasks'
4
+
5
+ module Jade
6
+ module Tasks
7
+ Block = Data.define(:block)
8
+
9
+ class TestRegistry
10
+ attr_accessor :strict
11
+
12
+ def initialize
13
+ @persistent = {}
14
+ @queues = Hash.new { |h, k| h[k] = [] }
15
+ @calls = Hash.new { |h, k| h[k] = [] }
16
+ @strict = false
17
+ end
18
+
19
+ def queue_next(task_def, answer)
20
+ @queues[task_def] << answer
21
+ end
22
+
23
+ def set_persistent(task_def, answer)
24
+ @persistent[task_def] = answer
25
+ end
26
+
27
+ def dispatch(task_def, args)
28
+ @calls[task_def] << args
29
+
30
+ pick_answer(task_def)
31
+ .then { it || fail(Unbound.new(task_def, args, @strict)) }
32
+ .then { resolve(it, args) }
33
+ .tap { |value| fail ReturnedTask.new(task_def) if value.is_a?(Jade::Task) }
34
+ end
35
+
36
+ def calls_to(task_def)
37
+ @calls[task_def]
38
+ end
39
+
40
+ private
41
+
42
+ def pick_answer(task_def)
43
+ @queues[task_def].shift ||
44
+ @persistent[task_def] ||
45
+ (@strict ? nil : REGISTRATIONS[task_def]&.then { Block.new(it) })
46
+ end
47
+
48
+ def resolve(answer, args)
49
+ case answer
50
+ in Block(block) then block.call(Outcome, *args)
51
+ else Jade::Result::Ok[answer]
52
+ end
53
+ end
54
+ end
55
+
56
+ # Override production dispatch to route through the per-thread test registry.
57
+ def self.dispatch(task_def, *args)
58
+ test_registry.dispatch(task_def, args)
59
+ end
60
+
61
+ def self.test_registry
62
+ Thread.current[:jade_tasks_test_registry] ||= TestRegistry.new
63
+ end
64
+
65
+ def self.reset!(strict: false)
66
+ Thread.current[:jade_tasks_test_registry] = TestRegistry
67
+ .new
68
+ .tap { it.strict = strict }
69
+ end
70
+
71
+ # Test-mode Unbound carries an extra `strict` field for a more helpful
72
+ # message when a test forgot to stub.
73
+ remove_const(:Unbound)
74
+
75
+ class Unbound < StandardError
76
+ def initialize(task_def, args, strict)
77
+ kind = strict ? 'stub' : 'stub or registration'
78
+ super("No #{kind} for #{task_def}; called with #{args.inspect}")
79
+ end
80
+ end
81
+
82
+ module RSpec
83
+ def next_call_to(task_def, value = OMITTED, &block)
84
+ Jade::Tasks
85
+ .test_registry
86
+ .queue_next(task_def, answer_for(value, block))
87
+ end
88
+
89
+ def all_calls_to(task_def, value = OMITTED, &block)
90
+ Jade::Tasks
91
+ .test_registry
92
+ .set_persistent(task_def, answer_for(value, block))
93
+ end
94
+
95
+ OMITTED = Object.new.freeze
96
+ private_constant :OMITTED
97
+
98
+ private
99
+
100
+ def answer_for(value, block)
101
+ if block
102
+ Jade::Tasks::Block.new(block)
103
+ elsif value.equal?(OMITTED)
104
+ fail ArgumentError, "needs a value or a block"
105
+ else
106
+ value
107
+ end
108
+ end
109
+
110
+ def self.included(base)
111
+ base.before(:each) { Jade::Tasks.reset!(strict: true) }
112
+ end
113
+
114
+ module Loose
115
+ def self.included(base)
116
+ base.include(Jade::Tasks::RSpec)
117
+ base.before(:each) { Jade::Tasks.reset!(strict: false) }
118
+ end
119
+ end
120
+ end
121
+
122
+ module Matcher
123
+ extend self
124
+
125
+ def resolve(name)
126
+ case name
127
+ when ::Class, ::Module
128
+ name
129
+ when ::String
130
+ Object.const_get(name)
131
+ when ::Symbol
132
+ full_names = lookup_short_name(name.to_s).map(&:name).uniq
133
+ case full_names.length
134
+ when 1 then Object.const_get(full_names.first)
135
+ when 0
136
+ fail "No constant named #{name.inspect}; " \
137
+ "pass the class itself or a 'Module::Name' string"
138
+ else
139
+ fail "Ambiguous #{name.inspect}: #{full_names.join(', ')}; " \
140
+ "use the qualified 'Module::Name' string"
141
+ end
142
+ end
143
+ end
144
+
145
+ def match?(actual, name, positional, named)
146
+ klass = resolve(name)
147
+ return false unless actual.is_a?(klass)
148
+
149
+ if named.any?
150
+ return false if positional.any?
151
+
152
+ actual_kw = actual.deconstruct_keys(named.keys)
153
+ named.all? { |k, expected| arg_match?(actual_kw[k], expected) }
154
+ else
155
+ actual_args = actual.respond_to?(:deconstruct) ? actual.deconstruct : []
156
+ return false unless actual_args.length == positional.length
157
+
158
+ actual_args.zip(positional).all? { |a, e| arg_match?(a, e) }
159
+ end
160
+ end
161
+
162
+ def arg_match?(actual, expected)
163
+ return expected === actual || expected == actual unless expected.is_a?(::Array)
164
+
165
+ case expected
166
+ in [::Symbol | ::String | ::Module => name, *positional, ::Hash => named]
167
+ match?(actual, name, positional, named)
168
+
169
+ in [::Symbol | ::String | ::Module => name, *positional]
170
+ match?(actual, name, positional, {})
171
+
172
+ else
173
+ expected == actual
174
+ end
175
+ end
176
+
177
+ private
178
+
179
+ def lookup_short_name(short)
180
+ matches = ->(m) {
181
+ Module
182
+ .instance_method(:name)
183
+ .bind(m).call
184
+ .then { it && it.split('::').last == short }
185
+ }
186
+
187
+ ObjectSpace.each_object(Class).select(&matches) +
188
+ ObjectSpace.each_object(Module).select { |m| !m.is_a?(Class) && matches.call(m) }
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ ::RSpec::Matchers.define :have_been_called do
195
+ def matching_calls(task_def)
196
+ actual = Jade::Tasks.test_registry.calls_to(task_def)
197
+ @args ? actual.select { |a| a == @args } : actual
198
+ end
199
+
200
+ match do |task_def|
201
+ @task_def = task_def
202
+ @actual = Jade::Tasks.test_registry.calls_to(task_def)
203
+ matches = matching_calls(task_def)
204
+ @count ? matches.length == @count : matches.any?
205
+ end
206
+
207
+ match_when_negated do |task_def|
208
+ @task_def = task_def
209
+ @actual = Jade::Tasks.test_registry.calls_to(task_def)
210
+ matching_calls(task_def).empty?
211
+ end
212
+
213
+ chain(:with) { |*args| @args = args }
214
+ chain(:times) { |count| @count = count }
215
+ chain(:once) { @count = 1 }
216
+
217
+ failure_message do
218
+ suffix = @args ? " with #{@args.inspect}" : ""
219
+ suffix += " #{@count} time(s)" if @count
220
+ "expected #{@task_def} to have been called#{suffix}, but calls were #{@actual.inspect}"
221
+ end
222
+
223
+ failure_message_when_negated do
224
+ suffix = @args ? " with #{@args.inspect}" : ""
225
+ "expected #{@task_def} not to have been called#{suffix}, but calls were #{@actual.inspect}"
226
+ end
227
+ end
228
+
229
+ ::RSpec::Matchers.define :look_like do |name, *positional, **named|
230
+ match do |actual|
231
+ @actual = actual
232
+ Jade::Tasks::Matcher.match?(actual, name, positional, named)
233
+ end
234
+
235
+ failure_message do
236
+ args = (positional.map(&:inspect) + named.map { |k, v| "#{k}: #{v.inspect}" }).join(', ')
237
+ "expected #{@actual.inspect} to look like #{name}(#{args})"
238
+ end
239
+ end
240
+
241
+ {
242
+ ok: 'Jade::Result::Ok',
243
+ err: 'Jade::Result::Err',
244
+ just: 'Jade::Maybe::Just',
245
+ nothing: 'Jade::Maybe::Nothing',
246
+ }.each do |kind, full_name|
247
+ ::RSpec::Matchers.define :"be_#{kind}" do |*args, **named|
248
+ match do |actual|
249
+ @actual = actual
250
+ if args.empty? && named.empty?
251
+ actual.respond_to?(:"#{kind}?") && actual.public_send(:"#{kind}?")
252
+ else
253
+ Jade::Tasks::Matcher.match?(actual, full_name, args, named)
254
+ end
255
+ end
256
+
257
+ failure_message do
258
+ if args.empty? && named.empty?
259
+ "expected #{@actual.inspect} to respond truthy to .#{kind}?"
260
+ else
261
+ inner = (args.map(&:inspect) + named.map { |k, v| "#{k}: #{v.inspect}" }).join(', ')
262
+ "expected #{@actual.inspect} to be #{kind.to_s.capitalize}(#{inner})"
263
+ end
264
+ end
265
+ end
266
+ end
data/lib/jade/tasks.rb ADDED
@@ -0,0 +1,70 @@
1
+ module Jade
2
+ module Task; end
3
+
4
+ TaskDef = Data.define(:module_name, :name) do
5
+ def to_s
6
+ "#{module_name}.#{name}"
7
+ end
8
+
9
+ def inspect
10
+ "#<TaskDef #{self}>"
11
+ end
12
+ end
13
+
14
+ module Port
15
+ def task(name, &block)
16
+ Jade::TaskDef
17
+ .new(self.name, name.to_s)
18
+ .tap { Jade::Tasks.register(it, &block) }
19
+ .tap { |task_def| define_singleton_method(name) { task_def } }
20
+ end
21
+ end
22
+
23
+ module Tasks
24
+ extend self
25
+
26
+ REGISTRATIONS = {}
27
+
28
+ class Unbound < StandardError
29
+ def initialize(task_def, args)
30
+ super("No port registered for #{task_def}; called with #{args.inspect}")
31
+ end
32
+ end
33
+
34
+ class ReturnedTask < StandardError
35
+ def initialize(task_def)
36
+ super(
37
+ "Body of #{task_def} returned a Jade::Task — tasks must not return tasks; " \
38
+ "compose with map/and_then/sequence in Jade instead"
39
+ )
40
+ end
41
+ end
42
+
43
+ def register(task_def, &block)
44
+ REGISTRATIONS[task_def] = block
45
+ end
46
+
47
+ def dispatch(task_def, *args)
48
+ block = REGISTRATIONS[task_def]
49
+ fail Unbound.new(task_def, args) unless block
50
+
51
+ block.call(Outcome, *args).tap do |value|
52
+ fail ReturnedTask.new(task_def) if value.is_a?(Jade::Task)
53
+ end
54
+ end
55
+
56
+ module Outcome
57
+ extend self
58
+
59
+ def ok(value)
60
+ Jade::Result::Ok[value]
61
+ end
62
+
63
+ def err(error)
64
+ Jade::Result::Err[error]
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ require 'jade/task'
@@ -0,0 +1,33 @@
1
+ module Jade
2
+ module Type
3
+ AnonymousRecord = Data.define(:fields, :row_var) do
4
+ include Base
5
+
6
+ def to_s
7
+ row = row_var ? "#{row_var} | " : ""
8
+
9
+ fields
10
+ .map { |name, type| "#{name} : #{type}" }
11
+ .join(", ")
12
+ .then { "{ #{row}#{it} }" }
13
+ end
14
+
15
+ def unbound_vars
16
+ (row_var ? row_var.unbound_vars : []) +
17
+ fields.values.flat_map(&:unbound_vars).uniq
18
+ end
19
+
20
+ def open?
21
+ !closed?
22
+ end
23
+
24
+ def closed?
25
+ row_var.nil?
26
+ end
27
+
28
+ def field_names
29
+ fields.keys
30
+ end
31
+ end
32
+ end
33
+ end