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,280 @@
1
+ require 'jade/runtime'
2
+ require 'jade/symbol'
3
+ require 'jade/codegen/inlines'
4
+
5
+ module Jade
6
+ module Stdlib
7
+ module Intrinsics
8
+ def generate_entry(registry)
9
+ @entry = entry
10
+ .then { load_env(it, registry) }
11
+ end
12
+
13
+ def variant(name, of:, args: [])
14
+ parent = @symbols
15
+ &.find { it.is_a?(Symbol::Union) && it.name == of.to_s }
16
+
17
+ union_ref = Symbol.type_ref(module_name, of.to_s)
18
+ parsed_args = args.map { Symbol.parse(it) }
19
+
20
+ variant_sym = Symbol::Variant.new(
21
+ module_name:,
22
+ name: name.to_s,
23
+ args: parsed_args,
24
+ union: union_ref,
25
+ decl_span: nil,
26
+ )
27
+
28
+ constructor_sym = Symbol::Constructor.new(
29
+ module_name:,
30
+ name: name.to_s,
31
+ args: parsed_args,
32
+ parent: union_ref,
33
+ decl_span: nil,
34
+ )
35
+
36
+ store(variant_sym)
37
+ store(constructor_sym)
38
+
39
+ if parent
40
+ parent
41
+ .with(variants: parent.variants + [variant_sym.to_ref])
42
+ .then { @symbols[@symbols.index(parent)] = it }
43
+ end
44
+ end
45
+
46
+ def union(name, *type_params, constructor: false)
47
+ union_symbol = Symbol
48
+ .union(name.to_s, type_params.map { Symbol.var(it, nil) }, [], nil)
49
+ .with(module_name:)
50
+ .tap { store(it) }
51
+
52
+ constructor_symbol = if constructor
53
+ Symbol.constructor(
54
+ name.to_s,
55
+ type_params.map { Symbol.var(it, nil) },
56
+ union_symbol,
57
+ nil,
58
+ )
59
+ .with(module_name:)
60
+ .then { store(it) }
61
+ end
62
+ end
63
+
64
+ def function(name, params, ret, constraints: [], body: nil, private: false, &block)
65
+ qualified_fn_name = "#{module_name}.#{name}"
66
+
67
+ codegen = body || "Jade::Runtime.intr('#{qualified_fn_name}')"
68
+ impl = runtime_impl(qualified_fn_name, params.size, block, body)
69
+
70
+ Symbol
71
+ .stdlib_function(
72
+ name.to_s,
73
+ params.transform_values { Symbol.parse(it) },
74
+ Symbol.parse(ret),
75
+ codegen,
76
+ constraints:,
77
+ )
78
+ .with(module_name:)
79
+ .tap { store(it) unless private }
80
+ .tap { Runtime.register(qualified_fn_name, &impl) }
81
+ end
82
+
83
+ # Approach A: the inline template is the single source of truth for a
84
+ # function's behaviour. A hand-written block always wins. With no block
85
+ # and a `body:` codegen override the function is codegen/dictionary-only
86
+ # (e.g. derived comparisons) and has no runtime entry. Otherwise the
87
+ # runtime proc is synthesised from the same template codegen emits, so the
88
+ # compiled and interpreted paths can't drift — and the absence of both a
89
+ # block and an inline is a definition error, not a lazy runtime surprise.
90
+ def runtime_impl(qualified_fn_name, arity, block, body)
91
+ case [block, body]
92
+ in [Proc => block, _] then block
93
+ in [nil, nil]
94
+ derive_runtime(qualified_fn_name, arity) ||
95
+ fail("#{qualified_fn_name}: no runtime block and no inline to derive from")
96
+ else nil
97
+ end
98
+ end
99
+
100
+ # Evaluated at the top level — the same constant-resolution context the
101
+ # template lands in when codegen splices it into compiled output — so a
102
+ # bare `String` means `::String`, not `Jade::Stdlib::String`. Constants
103
+ # resolve at call time, so there's no stdlib load-order constraint.
104
+ def derive_runtime(qualified_fn_name, arity)
105
+ Codegen::Inlines.for(qualified_fn_name).then do |template|
106
+ next nil unless template
107
+
108
+ args = Array.new(arity) { "a#{it}" }
109
+ eval("->(#{args.join(', ')}) { #{template.call(*args)} }", TOPLEVEL_BINDING)
110
+ end
111
+ end
112
+
113
+ def interface(name, type_param, functions, default: {})
114
+ functions
115
+ .map { |k, v| Symbol.parse(v).then { to_interface_function(name, k, it) }.with(module_name:) }
116
+ .then { Symbol.interface(name, Symbol.parse(type_param), it, default, nil) }
117
+ .with(module_name:)
118
+ .then { store(it); it.functions.each { |fn| store(fn) } }
119
+ end
120
+
121
+ # Declares that a Jade type is backed by one or more native Ruby classes.
122
+ # This auto-registers runtime dispatch for every implementation declared
123
+ # after this call, so there's no need for manual Runtime.register_impl calls.
124
+ #
125
+ # Future direction: literals should eventually be wrapped in Jade's own
126
+ # Data.define types (e.g. Int[value: 42]) and only unwrapped at interop
127
+ # boundaries. That would make native_type unnecessary — implementation
128
+ # declarations would cover both compile-time and runtime dispatch on their
129
+ # own. It also opens up richer type definitions like:
130
+ # Int = InternalInt | Overflow
131
+ # Float = InternalFloat | NaN | Infinity | NegInfinity
132
+ # See Char for a preview of this direction: it's a distinct type from
133
+ # String even though it's still backed by a Ruby String at runtime.
134
+ def native_type(jade_type_name, *ruby_classes)
135
+ @native_types ||= {}
136
+ @native_types[jade_type_name.to_s] = ruby_classes
137
+ end
138
+
139
+ def implementation(interface_name, type, functions)
140
+ interface = imports
141
+ .map(&:symbols)
142
+ .then { [symbols, *it] }
143
+ .flatten
144
+ .find { it.is_a?(Symbol::Interface) && it.name == interface_name }
145
+
146
+ interface_ref = interface ? interface.to_ref : interface_to_ref(interface_name)
147
+ default = interface ? interface.default : {}
148
+ type_ref = impl_type_ref(type)
149
+
150
+ Symbol
151
+ .implementation(
152
+ interface_ref,
153
+ type_ref,
154
+ [],
155
+ [],
156
+ functions
157
+ .transform_values { Symbol.value_ref(module_name, it) }
158
+ .merge(default),
159
+ [],
160
+ nil,
161
+ )
162
+ .then { store(it) }
163
+
164
+ if (ruby_classes = @native_types&.[](type))
165
+ qualified_iface = "#{interface_to_ref(interface_name).module_name}.#{interface_name}"
166
+ qualified_fns = functions.transform_values { "#{module_name}.#{it}" }
167
+ ruby_classes.each { Runtime.register_impl(qualified_iface, it, qualified_fns) }
168
+ end
169
+ end
170
+
171
+ # Accepts both bare/qualified names ('Int', 'Basics.Int') and full type
172
+ # expressions with vars ('Maybe(a)', 'Result(a, e)'). The impl record
173
+ # stores only the constructor ref (matching the forward-declaration
174
+ # convention at frontend/forward_declaration/implementation.rb:44).
175
+ def impl_type_ref(type)
176
+ Symbol.parse(type) => Symbol::TypeApplication(constructor:)
177
+ constructor
178
+ end
179
+
180
+ def symbols
181
+ @symbols || []
182
+ end
183
+
184
+ def entry
185
+ @entry || symbols
186
+ .reduce(Registry.entry(module_name)) do |acc, sym|
187
+ acc.define(sym)
188
+ end
189
+ .with(exposes:)
190
+ .then { resolve_imports(it) }
191
+ end
192
+
193
+ def import(module_name)
194
+ @imports = imports + [module_name]
195
+ end
196
+
197
+ def imports
198
+ @imports || []
199
+ end
200
+
201
+ def default_importing(imports)
202
+ @default_imports = if imports == :*
203
+ exposes
204
+ else
205
+ exposes.select { imports.include? it.name }
206
+ end
207
+ end
208
+
209
+ def default_imports
210
+ @default_imports || {}
211
+ end
212
+
213
+ def default_implementation(params:, body:)
214
+ Symbol::StdlibImplementation[params, body]
215
+ end
216
+
217
+ private
218
+
219
+ def exposes
220
+ @symbols
221
+ .reject { it.is_a?(Symbol::Implementation) }
222
+ .map { it.to_ref }
223
+ end
224
+
225
+ def resolve_imports(entry)
226
+ # TODO: This is the same code from stdlib that auto imports stuff.
227
+ imports
228
+ .reduce(entry) do |acc, stdlib|
229
+ ImportEntry[stdlib.entry.name, stdlib.entry.name, stdlib.default_imports, stdlib.entry.exposes]
230
+ .then { acc.import(it) }
231
+ end
232
+ end
233
+
234
+ def store(symbol)
235
+ @symbols ||= []
236
+ @symbols.concat << symbol
237
+ end
238
+
239
+ def module_name
240
+ "#{self.name.split('::').last}"
241
+ end
242
+
243
+ def load_env(entry, registry)
244
+ Frontend::TypeChecking::Loader
245
+ .load(entry, registry.add_module(entry))
246
+ .then { entry.with(env: it) }
247
+ end
248
+
249
+ def interface_to_ref(interface)
250
+ case interface
251
+ in 'Eq' | 'Comparable' | 'Appendable' | 'Mappable' | 'Chainable' | 'Numeric'
252
+ 'Basics'
253
+
254
+ in 'Decodable'
255
+ 'Decode'
256
+
257
+ in 'Encodable'
258
+ 'Encode'
259
+ end
260
+ .then { Symbol.type_ref(it, interface.to_s) }
261
+ end
262
+
263
+ def to_interface_function(interface_name, fn_name, fn)
264
+ params, return_type =
265
+ case fn
266
+ in Symbol::FunctionType then [fn.params, fn.return_type]
267
+ else [[], fn]
268
+ end
269
+
270
+ Symbol.interface_function(
271
+ fn_name,
272
+ interface_to_ref(interface_name),
273
+ params,
274
+ return_type,
275
+ nil,
276
+ )
277
+ end
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,214 @@
1
+ require 'jade/stdlib/intrinsics'
2
+
3
+ module Jade
4
+ module Stdlib
5
+ module List
6
+ extend Intrinsics
7
+
8
+ import Maybe
9
+ import Tuple
10
+
11
+ union :List, 'a'
12
+
13
+ function(:singleton, { element: 'a' }, 'List(a)')
14
+ function(:repeat, { element: 'a', times: 'Int' }, 'List(a)')
15
+ function(:range, { begin_: 'Int', end_: 'Int' }, 'List(a)')
16
+ function(:"empty?", { list: 'List(a)' }, 'Bool')
17
+ function(:head, { list: 'List(a)' }, 'Maybe(a)')
18
+ function(:tail, { list: 'List(a)' }, 'List(a)')
19
+ function(:length, { list: 'List(a)' }, 'Int')
20
+ function(:reverse, { list: 'List(a)' }, 'List(a)')
21
+
22
+ # Transform
23
+
24
+ function(:map, { list: 'List(a)', fn: 'a -> b' }, 'List(b)')
25
+ function(:and_then, { list: 'List(a)', fn: 'a -> List(b)' }, 'List(b)')
26
+ function(:indexed_map, { list: 'List(a)', fn: 'Int, a -> b' }, 'List(b)')
27
+ function(:fold, { list: 'List(a)', initial: 'b', fn: 'b, a -> b' }, 'b')
28
+ function(:filter, { list: 'List(a)', fn: 'a -> Bool' }, 'List(a)')
29
+
30
+ function(
31
+ :sort,
32
+ { list: 'List(a)' },
33
+ 'List(a)',
34
+ constraints: [['Basics.Comparable', 'a']],
35
+ body: Symbol::DerivedFunction.new(
36
+ params: ['list'],
37
+ body: [:call,
38
+ [:stdlib_fn, 'List.sort_with'],
39
+ [[:var, 'list'], [:impl_arg, 0, 'compare']],
40
+ ],
41
+ ),
42
+ )
43
+
44
+ function(
45
+ :sort_by,
46
+ { list: 'List(a)', key: 'a -> b' },
47
+ 'List(a)',
48
+ constraints: [['Basics.Comparable', 'b']],
49
+ body: Symbol::DerivedFunction.new(
50
+ params: ['list', 'key'],
51
+ body: [:call,
52
+ [:stdlib_fn, 'List.sort_by_with'],
53
+ [[:var, 'list'], [:var, 'key'], [:impl_arg, 0, 'compare']],
54
+ ],
55
+ ),
56
+ )
57
+
58
+ function(
59
+ 'sort_with',
60
+ { list: 'List(a)', cmp: 'a, a -> Ordering' },
61
+ 'List(a)',
62
+ private: true,
63
+ ) do |list, cmp|
64
+ list.sort do |x, y|
65
+ case cmp.call(x, y)
66
+ in Jade::Basics::LT then -1
67
+ in Jade::Basics::GT then 1
68
+ else 0
69
+ end
70
+ end
71
+ end
72
+
73
+ function(
74
+ 'sort_by_with',
75
+ { list: 'List(a)', key: 'a -> b', cmp: 'b, b -> Ordering' },
76
+ 'List(a)',
77
+ private: true,
78
+ ) do |list, key, cmp|
79
+ list
80
+ .map { |x| [x, key.call(x)] }
81
+ .sort do |(_, ka), (_, kb)|
82
+ case cmp.call(ka, kb)
83
+ in Jade::Basics::LT then -1
84
+ in Jade::Basics::GT then 1
85
+ else 0
86
+ end
87
+ end
88
+ .map(&:first)
89
+ end
90
+
91
+ function(:"any?", { list: 'List(a)', fn: 'a -> Bool' }, 'Bool')
92
+ function(:"all?", { list: 'List(a)', fn: 'a -> Bool' }, 'Bool')
93
+ function(:find, { list: 'List(a)', fn: 'a -> Bool' }, 'Maybe(a)')
94
+
95
+ function(
96
+ :filter_map,
97
+ { list: 'List(a)', fn: 'a -> Maybe(b)' },
98
+ 'List(b)',
99
+ ) do |list, fn|
100
+ list.flat_map do |x|
101
+ case fn.call(x)
102
+ in Jade::Maybe::Just[v] then [v]
103
+ else []
104
+ end
105
+ end
106
+ end
107
+
108
+ function(:take, { list: 'List(a)', n: 'Int' }, 'List(a)')
109
+ function(:drop, { list: 'List(a)', n: 'Int' }, 'List(a)')
110
+ function(:partition, { list: 'List(a)', fn: 'a -> Bool' }, 'Tuple2(List(a), List(a))')
111
+ function(:concat, { lists: 'List(List(a))' }, 'List(a)')
112
+
113
+ function(
114
+ :zip,
115
+ { left: 'List(a)', right: 'List(b)' },
116
+ 'List(Tuple2(a, b))',
117
+ ) do |left, right|
118
+ len = [left.length, right.length].min
119
+ left.first(len).zip(right.first(len)).map { |(x, y)| Jade::Tuple::Tuple2[x, y] }
120
+ end
121
+
122
+ function(:unzip, { list: 'List(Tuple2(a, b))' }, 'Tuple2(List(a), List(b))')
123
+
124
+ function(
125
+ :"member?",
126
+ { list: 'List(a)', element: 'a' },
127
+ 'Bool',
128
+ constraints: [['Basics.Eq', 'a']],
129
+ body: Symbol::DerivedFunction.new(
130
+ params: ['list', 'element'],
131
+ body: [:call,
132
+ [:stdlib_fn, 'List.member_with'],
133
+ [[:var, 'list'], [:var, 'element'], [:impl_arg, 0, '(==)']],
134
+ ],
135
+ ),
136
+ )
137
+
138
+ function(
139
+ 'member_with',
140
+ { list: 'List(a)', element: 'a', eq: 'a, a -> Bool' },
141
+ 'Bool',
142
+ private: true,
143
+ ) { |list, element, eq| list.any? { |x| eq.call(x, element) } }
144
+
145
+ function(
146
+ :maximum,
147
+ { list: 'List(a)' },
148
+ 'Maybe(a)',
149
+ constraints: [['Basics.Comparable', 'a']],
150
+ body: Symbol::DerivedFunction.new(
151
+ params: ['list'],
152
+ body: [:call,
153
+ [:stdlib_fn, 'List.maximum_with'],
154
+ [[:var, 'list'], [:impl_arg, 0, 'compare']],
155
+ ],
156
+ ),
157
+ )
158
+
159
+ function(
160
+ :minimum,
161
+ { list: 'List(a)' },
162
+ 'Maybe(a)',
163
+ constraints: [['Basics.Comparable', 'a']],
164
+ body: Symbol::DerivedFunction.new(
165
+ params: ['list'],
166
+ body: [:call,
167
+ [:stdlib_fn, 'List.minimum_with'],
168
+ [[:var, 'list'], [:impl_arg, 0, 'compare']],
169
+ ],
170
+ ),
171
+ )
172
+
173
+ function(
174
+ 'maximum_with',
175
+ { list: 'List(a)', cmp: 'a, a -> Ordering' },
176
+ 'Maybe(a)',
177
+ private: true,
178
+ ) do |list, cmp|
179
+ if list.empty?
180
+ Jade::Maybe::Nothing[]
181
+ else
182
+ best = list.reduce do |acc, x|
183
+ cmp.call(x, acc).is_a?(Jade::Basics::GT) ? x : acc
184
+ end
185
+ Jade::Maybe::Just[best]
186
+ end
187
+ end
188
+
189
+ function(
190
+ 'minimum_with',
191
+ { list: 'List(a)', cmp: 'a, a -> Ordering' },
192
+ 'Maybe(a)',
193
+ private: true,
194
+ ) do |list, cmp|
195
+ if list.empty?
196
+ Jade::Maybe::Nothing[]
197
+ else
198
+ best = list.reduce do |acc, x|
199
+ cmp.call(x, acc).is_a?(Jade::Basics::LT) ? x : acc
200
+ end
201
+ Jade::Maybe::Just[best]
202
+ end
203
+ end
204
+
205
+ implementation('Appendable', 'List', '(++)' => 'list_append')
206
+ implementation('Mappable', 'List', 'map' => 'map')
207
+ implementation('Chainable', 'List', 'and_then' => 'and_then')
208
+
209
+ function('list_append', { a: 'List(a)', b: 'List(a)' }, 'List(a)')
210
+
211
+ default_importing('List')
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,73 @@
1
+ require 'jade/stdlib/compiled'
2
+
3
+ module Jade
4
+ module Stdlib
5
+ module Maybe
6
+ extend self
7
+ extend Compiled
8
+
9
+ def uri
10
+ 'maybe.jd'
11
+ end
12
+
13
+ def imports
14
+ [Basics]
15
+ end
16
+
17
+ def default_imports
18
+ [
19
+ Symbol.type_ref('Maybe', 'Maybe'),
20
+ Symbol.value_ref('Maybe', 'Just'),
21
+ Symbol.value_ref('Maybe', 'Nothing'),
22
+ ]
23
+ end
24
+
25
+ def code
26
+ <<~JADE
27
+ module Maybe exposing (Maybe(..), and_then, map, with_default)
28
+
29
+ type Maybe(a)
30
+ = Just(a)
31
+ | Nothing
32
+
33
+
34
+ def with_default(maybe: Maybe(a), default: a) -> a
35
+ case maybe
36
+ in Just(something) then something
37
+ in Nothing then default
38
+ end
39
+ end
40
+
41
+
42
+ def map(maybe: Maybe(a), fn: a -> b) -> Maybe(b)
43
+ case maybe
44
+ in Just(something)
45
+ something
46
+ |> fn
47
+ |> Just
48
+ in Nothing then Nothing
49
+ end
50
+ end
51
+
52
+
53
+ def and_then(maybe: Maybe(a), fn: a -> Maybe(b)) -> Maybe(b)
54
+ case maybe
55
+ in Just(something) then something |> fn
56
+ in Nothing then Nothing
57
+ end
58
+ end
59
+
60
+
61
+ implements Mappable(Maybe(a)) with
62
+ map: map
63
+ end
64
+
65
+
66
+ implements Chainable(Maybe(a)) with
67
+ and_then: and_then
68
+ end
69
+ JADE
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,131 @@
1
+ require 'jade/stdlib/compiled'
2
+
3
+ module Jade
4
+ module Stdlib
5
+ module Result
6
+ extend self
7
+ extend Compiled
8
+
9
+ def uri
10
+ 'result.jd'
11
+ end
12
+
13
+ def imports
14
+ [Basics, Maybe, List]
15
+ end
16
+
17
+ def default_imports
18
+ [
19
+ Symbol.type_ref('Result', 'Result'),
20
+ Symbol.value_ref('Result', 'Ok'),
21
+ Symbol.value_ref('Result', 'Err'),
22
+ ]
23
+ end
24
+
25
+ def code
26
+ <<~JADE
27
+ module Result exposing (
28
+ Result(..),
29
+ and_then,
30
+ from_maybe,
31
+ map,
32
+ map_error,
33
+ on_error,
34
+ sequence,
35
+ to_maybe,
36
+ with_default,
37
+ )
38
+
39
+ type Result(value, error)
40
+ = Ok(value)
41
+ | Err(error)
42
+
43
+
44
+ def map(result: Result(a, e), fn: a -> b) -> Result(b, e)
45
+ case result
46
+ in Ok(something)
47
+ something
48
+ |> fn
49
+ |> Ok
50
+ in Err(error) then Err(error)
51
+ end
52
+ end
53
+
54
+
55
+ def and_then(result: Result(a, e), fn: a -> Result(b, e)) -> Result(b, e)
56
+ case result
57
+ in Ok(something) then something |> fn
58
+ in Err(error) then Err(error)
59
+ end
60
+ end
61
+
62
+
63
+ def with_default(result: Result(a, e), default: a) -> a
64
+ case result
65
+ in Ok(something) then something
66
+ else default
67
+ end
68
+ end
69
+
70
+
71
+ def to_maybe(result: Result(a, e)) -> Maybe(a)
72
+ case result
73
+ in Ok(something) then Just(something)
74
+ else Nothing
75
+ end
76
+ end
77
+
78
+
79
+ def from_maybe(maybe: Maybe(a), error: e) -> Result(a, e)
80
+ case maybe
81
+ in Just(something) then Ok(something)
82
+ in Nothing then Err(error)
83
+ end
84
+ end
85
+
86
+
87
+ def map_error(result: Result(a, e), fn: e -> x) -> Result(a, x)
88
+ case result
89
+ in Err(error)
90
+ error
91
+ |> fn
92
+ |> Err
93
+ in Ok(something) then Ok(something)
94
+ end
95
+ end
96
+
97
+
98
+ def sequence(results: List(Result(a, e))) -> Result(List(a), e)
99
+ List.fold(
100
+ results,
101
+ Ok([]),
102
+ (acc, result) -> {
103
+ list <- acc
104
+ value <- result
105
+ Ok(list ++ [value])
106
+ },
107
+ )
108
+ end
109
+
110
+
111
+ def on_error(result: Result(a, e), fn: e -> Result(a, f)) -> Result(a, f)
112
+ case result
113
+ in Err(error) then error |> fn
114
+ in Ok(_) then result
115
+ end
116
+ end
117
+
118
+
119
+ implements Mappable(Result(a, e)) with
120
+ map: map
121
+ end
122
+
123
+
124
+ implements Chainable(Result(a, e)) with
125
+ and_then: and_then
126
+ end
127
+ JADE
128
+ end
129
+ end
130
+ end
131
+ end