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,121 @@
1
+ module Jade
2
+ module Frontend
3
+ module CommentAttacher
4
+ extend self
5
+
6
+ SKIP_FIELDS = %i[range symbol id leading_comments trailing_comments dangling_comments].freeze
7
+
8
+ def attach(ast, comments, source)
9
+ return ast if comments.empty?
10
+
11
+ collect_nodes(ast)
12
+ .reject { |n| n.range.nil? }
13
+ .sort_by { |n| n.range.begin }
14
+ .then { build_map(comments, it, source) }
15
+ .then { reattach(ast, it) }
16
+ end
17
+
18
+ private
19
+
20
+ def collect_nodes(node)
21
+ node
22
+ .to_h
23
+ .reject { |field, _| SKIP_FIELDS.include?(field) }
24
+ .values
25
+ .flat_map { walk_collect(it) }
26
+ .then { [node, *it] }
27
+ end
28
+
29
+ def walk_collect(val)
30
+ case val
31
+ in AST::Node then collect_nodes(val)
32
+ in Array then val.flat_map { walk_collect(it) }
33
+ else []
34
+ end
35
+ end
36
+
37
+ def build_map(comments, sorted_nodes, source)
38
+ comments
39
+ .filter_map { classify(it, sorted_nodes, source) }
40
+ .group_by(&:node_id)
41
+ .transform_values { CommentGroup.from_comments(it) }
42
+ end
43
+
44
+ def classify(comment, sorted_nodes, source)
45
+ comment_line = line_of(comment.range.begin, source)
46
+ prev_node = last_node_ending_before(comment.range.begin, sorted_nodes)
47
+ next_node = first_node_starting_after(comment.range.end, sorted_nodes)
48
+
49
+ if prev_node && line_of(prev_node.range.end - 1, source) == comment_line
50
+ CommentEntry::Trailing.new(node_id: prev_node.id, comment:)
51
+
52
+ elsif next_node
53
+ CommentEntry::Leading.new(node_id: next_node.id, comment:)
54
+
55
+ else
56
+ enclosing = smallest_enclosing(comment.range.begin, sorted_nodes)
57
+ CommentEntry::Dangling.new(node_id: enclosing.id, comment:) if enclosing
58
+ end
59
+ end
60
+
61
+ def line_of(pos, source)
62
+ idx = source.line_starts.bsearch_index { |ls| ls > pos }
63
+ idx ? idx - 1 : source.line_starts.length - 1
64
+ end
65
+
66
+ def last_node_ending_before(pos, sorted_nodes)
67
+ sorted_nodes
68
+ .select { |n| n.range.end <= pos }
69
+ .last
70
+ end
71
+
72
+ def first_node_starting_after(pos, sorted_nodes)
73
+ sorted_nodes.bsearch { |n| n.range.begin >= pos }
74
+ end
75
+
76
+ def smallest_enclosing(pos, sorted_nodes)
77
+ sorted_nodes
78
+ .select { |n| n.range.cover?(pos) }
79
+ .min_by { |n| n.range.size }
80
+ end
81
+
82
+ def reattach(node, map)
83
+ rebuilt_children = node
84
+ .to_h
85
+ .reject { |field, _| SKIP_FIELDS.include?(field) }
86
+ .transform_values { walk_reattach(it, map) }
87
+
88
+ node
89
+ .with(
90
+ **rebuilt_children,
91
+ **((map[node.id]&.to_h || {}).transform_keys { :"#{it}_comments" }),
92
+ )
93
+ end
94
+
95
+ def walk_reattach(val, map)
96
+ case val
97
+ in AST::Node then reattach(val, map)
98
+ in Array then val.map { walk_reattach(it, map) }
99
+ else val
100
+ end
101
+ end
102
+
103
+ module CommentEntry
104
+ Leading = Data.define(:node_id, :comment)
105
+ Trailing = Data.define(:node_id, :comment)
106
+ Dangling = Data.define(:node_id, :comment)
107
+ end
108
+
109
+ CommentGroup = Data.define(:leading, :trailing, :dangling) do
110
+ def self.from_comments(entries)
111
+ by_type = entries.group_by(&:class)
112
+ new(
113
+ leading: (by_type[CommentEntry::Leading] || []).map(&:comment),
114
+ trailing: (by_type[CommentEntry::Trailing] || []).map(&:comment),
115
+ dangling: (by_type[CommentEntry::Dangling] || []).map(&:comment),
116
+ )
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,39 @@
1
+ require 'jade/codegen/helpers'
2
+
3
+ module Jade
4
+ module Frontend
5
+ module Desugaring
6
+ module Placeholder
7
+ extend self
8
+ extend Codegen::Helpers
9
+
10
+ def lift(call)
11
+ return call unless call.args.any?(AST::Placeholder)
12
+
13
+ filled_args, names = call
14
+ .args
15
+ .reduce([[], []]) do |(args, names), arg|
16
+ case arg
17
+ in AST::Placeholder
18
+ param_synthetic_name(names.size)
19
+ .then { [args + [AST::VariableReference[it, nil]], names + [it]] }
20
+
21
+ else
22
+ [args + [arg], names]
23
+ end
24
+ end
25
+
26
+ names
27
+ .reverse
28
+ .reduce(call.with(args: filled_args)) do |body, name|
29
+ AST::Lambda[
30
+ [AST::Pattern::Binding[name, nil]],
31
+ AST::Body[[body], nil],
32
+ call.range,
33
+ ]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,63 @@
1
+ module Jade
2
+ module Frontend
3
+ module Desugaring
4
+ extend self
5
+
6
+ # Runs after SemanticAnalysis (which resolves names and attaches
7
+ # symbols). Add new post-resolution rewrites as `in` branches
8
+ # below; `map_children` handles transparent recursion.
9
+ def desugar_resolved_entry(entry, registry)
10
+ desugar_resolved(entry.ast, registry)
11
+ .then { entry.with(ast: it) }
12
+ end
13
+
14
+ def desugar_resolved(node, registry)
15
+ case node
16
+ in AST::VariableReference | AST::QualifiedAccess
17
+ zero_arg_fn?(node.symbol, registry) ? wrap_call(node) : node
18
+
19
+ else
20
+ map_children(node) { desugar_resolved(it, registry) }
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def map_children(node)
27
+ node
28
+ .to_h
29
+ .transform_values { walk_field(it) { yield(it) } }
30
+ .then { node.class.new(**it) }
31
+ end
32
+
33
+ # AST node fields are either an AST::Node, an array of AST::Nodes,
34
+ # or non-AST metadata (range, symbol, id, comments, bools). The
35
+ # block walks the first two; metadata passes through untouched.
36
+ def walk_field(value, &block)
37
+ case value
38
+ in AST::Node then block.call(value)
39
+ in [AST::Node, *] then value.map(&block)
40
+ else value
41
+ end
42
+ end
43
+
44
+ def wrap_call(ref)
45
+ AST::FunctionCall.new(
46
+ callee: ref,
47
+ args: [],
48
+ infix: false,
49
+ dictionaries: [],
50
+ range: ref.range,
51
+ )
52
+ end
53
+
54
+ def zero_arg_fn?(symbol, registry)
55
+ resolved = symbol.is_a?(Symbol::ValueRef) ? registry.lookup(symbol) : symbol
56
+ case resolved
57
+ in Symbol::Function | Symbol::StdlibFunction => fn then fn.constant?
58
+ else false
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,217 @@
1
+ require 'jade/frontend/desugaring/placeholder'
2
+
3
+ module Jade
4
+ module Frontend
5
+ module Desugaring
6
+ extend self
7
+
8
+ def desugar_entry(entry)
9
+ desugar(entry.ast)
10
+ .then { entry.with(ast: it) }
11
+ end
12
+
13
+ def desugar(node)
14
+ case node
15
+ in AST::Module(body:)
16
+ node.with(body: desugar(body))
17
+
18
+ in AST::Body(expressions:)
19
+ node.with(expressions: desugar_expressions(expressions))
20
+
21
+ in AST::InfixApplication(left:, right:, operator:)
22
+ case operator
23
+ in AST::InfixOperator(value: '|>')
24
+ case right
25
+ in AST::FunctionCall(args:)
26
+ right
27
+ .with(args: [left] + args)
28
+ .then { desugar(it) }
29
+
30
+ else
31
+ AST::FunctionCall.new(
32
+ callee: right,
33
+ args: [left],
34
+ infix: operator,
35
+ range: node.range,
36
+ )
37
+
38
+ end
39
+ .then { desugar(it) }
40
+
41
+ else
42
+ AST::FunctionCall.new(
43
+ callee: AST::VariableReference["(#{operator.value})", operator.range],
44
+ args: [desugar(left), desugar(right)],
45
+ infix: operator,
46
+ range: node.range,
47
+ )
48
+ end
49
+
50
+ in AST::FunctionCall(callee:, args:)
51
+ node
52
+ .with(callee: desugar(callee))
53
+ .with(args: args.map { desugar(it) })
54
+ .then { Placeholder.lift(it) }
55
+
56
+ in AST::KeyedCall(callee:, fields:)
57
+ node
58
+ .with(callee: desugar(callee))
59
+ .with(fields: fields.map { desugar(it) })
60
+
61
+ in AST::FunctionDeclaration(body:)
62
+ node
63
+ .with(body: desugar(body))
64
+
65
+ in AST::MemberAccess(target:)
66
+ node
67
+ .with(target: desugar(target))
68
+
69
+ in AST::CaseOf(expression:, branches:)
70
+ node
71
+ .with(expression: desugar(expression))
72
+ .with(branches: branches.map { desugar(it) })
73
+
74
+ in AST::CaseOfBranch(pattern:, body:)
75
+ node
76
+ .with(pattern: desugar(pattern))
77
+ .with(body: desugar(body))
78
+
79
+ in AST::IfThenElse(condition:, if_branch:, else_branch:)
80
+ node
81
+ .with(condition: desugar(condition))
82
+ .with(if_branch: desugar(if_branch))
83
+ .with(else_branch: desugar(else_branch))
84
+
85
+ in AST::Assign(pattern:, expression:)
86
+ node.with(pattern: desugar(pattern), expression: desugar(expression))
87
+
88
+ in AST::Grouping(expression:)
89
+ node.with(expression: desugar(expression))
90
+
91
+ in AST::Lambda(params:, body:)
92
+ node
93
+ .with(params: params.map { desugar(it) })
94
+ .with(body: desugar(body))
95
+
96
+ in AST::List(items:)
97
+ node
98
+ .with(items: items.map { desugar(it) })
99
+
100
+ in AST::RecordLiteral(fields:)
101
+ fields.map { desugar(it) }.then { node.with(fields: it) }
102
+
103
+ in AST::RecordUpdate(fields:)
104
+ fields.map { desugar(it) }.then { node.with(fields: it) }
105
+
106
+ in AST::RecordField(value:)
107
+ desugar(value).then { node.with(value: it) }
108
+
109
+ in AST::RecordAccessSugar(field_key:, range:)
110
+ AST::VariableReference['x', nil]
111
+ .then { AST::MemberAccess[it, AST::VariableReference[field_key, nil], range] }
112
+ .then { AST::Body[[it], nil] }
113
+ .then { AST::Lambda[[AST::Pattern::Binding['x', nil]], it, range] }
114
+
115
+ in AST::RecordUpdateSugar(field_key:, range:)
116
+ value_reference = AST::VariableReference['value', nil]
117
+
118
+ AST::VariableReference['x', nil]
119
+ .then { AST::RecordUpdate[it, [AST::RecordField[field_key, value_reference, nil]], range] }
120
+ .then { AST::Body[[it], nil] }
121
+ .then do |body|
122
+ AST::Lambda[
123
+ [
124
+ AST::Pattern::Binding['x', nil],
125
+ AST::Pattern::Binding[value_reference.name, nil],
126
+ ],
127
+ body,
128
+ range,
129
+ ]
130
+ end
131
+
132
+ in AST::Tuple(items:)
133
+ AST::FunctionCall.new(
134
+ callee: AST::ConstructorReference["Tuple.Tuple#{items.size}", node.range],
135
+ args: items.map { desugar(it) },
136
+ infix: false,
137
+ range: node.range,
138
+ )
139
+
140
+ in AST::Pattern::Tuple(patterns:)
141
+ AST::ConstructorReference[
142
+ "Tuple.Tuple#{patterns.size}",
143
+ node.range,
144
+ ]
145
+ .then do
146
+ AST::Pattern::Constructor.new(
147
+ constructor: it,
148
+ patterns: patterns.map { desugar(it) },
149
+ range: node.range,
150
+ )
151
+ end
152
+
153
+ in AST::Pattern::Constructor(patterns:)
154
+ node.with(patterns: patterns.map { desugar(it) })
155
+
156
+ in AST::Pattern::Record(fields:)
157
+ fields
158
+ .map { it.with(pattern: desugar(it.pattern)) }
159
+ .then { node.with(fields: it) }
160
+
161
+ in AST::Pattern::List(patterns:, rest:)
162
+ node
163
+ .with(patterns: patterns.map { desugar(it) })
164
+ .with(rest: rest && desugar(rest))
165
+
166
+ in AST::Implementation(functions:)
167
+ functions
168
+ .map { desugar(it) }
169
+ .then { node.with(functions: it) }
170
+
171
+ in AST::ImplementationFunction(fn:)
172
+ node.with(fn: desugar(fn))
173
+
174
+ in AST::Literal | AST::CharLiteral | AST::VariableReference | AST::ConstructorReference |
175
+ AST::TypeDeclaration | AST::ImportDeclaration |
176
+ AST::Pattern::Literal | AST::Pattern::Binding | AST::Pattern::Wildcard |
177
+ AST::Pattern::Record | AST::InteropImportDeclaration | AST::StructDeclaration |
178
+ AST::QualifiedAccess | AST::Placeholder | AST::InterfaceDeclaration
179
+
180
+ node
181
+ end
182
+ end
183
+
184
+ private
185
+
186
+ def desugar_expressions(expressions)
187
+ case expressions
188
+ in [AST::Bind(pattern:, expression: expr, range: bind_range), *rest]
189
+ AST::Lambda[
190
+ [pattern],
191
+ AST::Body[rest, nil],
192
+ nil,
193
+ ]
194
+ .then { [expr, it] }
195
+ .map { desugar(it) }
196
+ .then do
197
+ AST::FunctionCall.new(
198
+ callee: AST::VariableReference['and_then', nil],
199
+ args: it,
200
+ infix: false,
201
+ dictionaries: [],
202
+ range: bind_range,
203
+ )
204
+ end
205
+ .then { [it] }
206
+
207
+ in [expr, *rest]
208
+ [desugar(expr)] + desugar_expressions(rest)
209
+
210
+ in []
211
+ []
212
+ end
213
+ end
214
+
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,209 @@
1
+ module Jade
2
+ module Frontend
3
+ module FixityFixer
4
+ extend self
5
+
6
+ module SplitWhen
7
+ refine Enumerable do
8
+ def split_when
9
+ i = self.index { |x| !yield(x) } || self.length
10
+ [self.take(i), self.drop(i)]
11
+ end
12
+ end
13
+ end
14
+
15
+ using SplitWhen
16
+
17
+ Fixity = Data.define(:precedence, :assoc) do
18
+ # Compare the rank of two operators for shunting-yard purposes
19
+ # Returns:
20
+ # - negative if self has lower rank
21
+ # - zero if self and other are equal rank
22
+ # - positive if self has higher rank
23
+ def <=>(other)
24
+ # rank by precedence first
25
+ prec_cmp = precedence <=> other.precedence
26
+ return prec_cmp unless prec_cmp.zero?
27
+
28
+ # same precedence → rank by associativity
29
+ case assoc
30
+ when :left
31
+ 0 # equal rank: left-assoc
32
+ when :right
33
+ 1 # higher rank: right-assoc
34
+ when :none
35
+ raise "Non-associative operator cannot be chained"
36
+ end
37
+ end
38
+ end
39
+
40
+ FIXITY = {
41
+ '+' => Fixity[6, :left],
42
+ '-' => Fixity[6, :left],
43
+ '*' => Fixity[7, :left],
44
+ '/' => Fixity[7, :left],
45
+ '++' => Fixity[5, :right],
46
+ '|>' => Fixity[1, :left],
47
+ '<|' => Fixity[1, :right],
48
+ '==' => Fixity[4, :none],
49
+ '!=' => Fixity[4, :none],
50
+ '<=' => Fixity[4, :none],
51
+ '>=' => Fixity[4, :none],
52
+ '>' => Fixity[4, :none],
53
+ '<' => Fixity[4, :none],
54
+ '&&' => Fixity[3, :right],
55
+ '||' => Fixity[2, :right],
56
+ }.freeze
57
+
58
+ def fix_entry(entry)
59
+ fix(entry.ast)
60
+ .then { entry.with(ast: it) }
61
+ end
62
+
63
+ def fix(node)
64
+ case node
65
+ in AST::Module(body:)
66
+ fix(body)
67
+ .then { node.with(body: it) }
68
+
69
+ in AST::InfixApplication
70
+ flatten(node)
71
+ .then { shunting_yard(it) }
72
+ .then { unflatten(it) }
73
+
74
+ in AST::Assign(expression:)
75
+ node.with(expression: fix(expression))
76
+
77
+ in AST::FunctionDeclaration(body:)
78
+ node.with(body: fix(body))
79
+
80
+ in AST::Body(expressions:)
81
+ expressions
82
+ .map { fix(it) }
83
+ .then { node.with(expressions: it) }
84
+
85
+ in AST::FunctionCall(callee:, args:)
86
+ args
87
+ .map { fix(it) }
88
+ .then { node.with(args: it, callee: fix(callee)) }
89
+
90
+ in AST::KeyedCall(callee:, fields:)
91
+ fields
92
+ .map { fix(it) }
93
+ .then { node.with(fields: it, callee: fix(callee)) }
94
+
95
+ in AST::MemberAccess(target:)
96
+ fix(target)
97
+ .then { node.with(target: it) }
98
+
99
+ in AST::CaseOf(expression:, branches:)
100
+ branches.map { fix(it) }
101
+ .then { node.with(branches:, expression: fix(expression)) }
102
+
103
+ in AST::CaseOfBranch(body:)
104
+ node.with(body: fix(body))
105
+
106
+ in AST::IfThenElse(condition:, if_branch:, else_branch:)
107
+ node.with(
108
+ condition: fix(condition),
109
+ if_branch: fix(if_branch),
110
+ else_branch: fix(else_branch),
111
+ )
112
+
113
+ in AST::Lambda(body:)
114
+ node.with(body: fix(body))
115
+
116
+ in AST::ImplementationFunction(fn:)
117
+ node.with(fn: fix(fn))
118
+
119
+ in AST::Implementation(functions:)
120
+ functions
121
+ .map { fix(it) }
122
+ .then { node.with(functions: it) }
123
+
124
+ in AST::Grouping(expression:)
125
+ node.with(expression: fix(expression))
126
+
127
+ in AST::List(items:)
128
+ items
129
+ .map { fix(it) }
130
+ .then { node.with(items: it) }
131
+
132
+ in AST::RecordLiteral(fields:)
133
+ fields.map { fix(it) }.then { node.with(fields: it) }
134
+
135
+ in AST::RecordField(value:)
136
+ fix(value).then { node.with(value: it) }
137
+
138
+ in AST::RecordUpdate(fields:)
139
+ fields.map { fix(it) }.then { node.with(fields: it) }
140
+
141
+ in AST::Tuple(items:)
142
+ items.map { fix(it) }.then { node.with(items: it) }
143
+
144
+ in AST::Bind(expression:)
145
+ node.with(expression: fix(expression))
146
+
147
+ in AST::VariableReference | AST::ConstructorReference | AST::TypeDeclaration |
148
+ AST::ImportDeclaration | AST::Literal | AST::CharLiteral | AST::RecordAccessSugar | AST::InteropImportDeclaration |
149
+ AST::StructDeclaration | AST::QualifiedAccess | AST::Placeholder | AST::InterfaceDeclaration
150
+
151
+ node
152
+
153
+ in AST::RecordAccess(target:)
154
+ fix(target)
155
+ .then { node.with(target: it) }
156
+ end
157
+ end
158
+
159
+ private
160
+
161
+ def flatten(ast)
162
+ case ast
163
+ in AST::InfixApplication(left:, operator:, right:)
164
+ flatten(left) + [operator] + flatten(right)
165
+
166
+ else
167
+ [ast]
168
+ end
169
+ end
170
+
171
+ def shunting_yard(flat_infix)
172
+ flat_infix
173
+ .reduce([[], []]) do |(output, stack), node|
174
+ case node
175
+ in AST::InfixOperator(value:)
176
+ to_pop, to_keep = stack
177
+ .reverse
178
+ .split_when do |op|
179
+ (FIXITY[value] <=> FIXITY[op.value]) <= 0
180
+ end
181
+
182
+ [output + to_pop, to_keep.reverse + [node]]
183
+
184
+ else
185
+ [output + [node], stack]
186
+ end
187
+ end
188
+ .then { |(output, stack)| output + stack.reverse }
189
+ end
190
+
191
+ def unflatten(npr)
192
+ npr
193
+ .reduce([]) do |stack, node|
194
+ case node
195
+ in AST::InfixOperator
196
+ *rest, left, right = stack
197
+ AST
198
+ .infix_application.call(left, node, right)
199
+ .then { rest + [it] }
200
+
201
+ else
202
+ stack + [node]
203
+ end
204
+ end
205
+ .first
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,30 @@
1
+ module Jade
2
+ module Frontend
3
+ module ForwardDeclaration
4
+ module Body
5
+ extend self
6
+ extend Helper
7
+
8
+ def shallow(node, registry, entry)
9
+ walk(node, entry) { |acc, expr| shallow_declare_node(expr, registry, acc) }
10
+ end
11
+
12
+ def deep(node, entry, registry)
13
+ walk(node, entry) { |acc, expr| deep_declare_node(expr, acc, registry) }
14
+ end
15
+
16
+ private
17
+
18
+ def walk(node, entry, &block)
19
+ node => AST::Body(expressions:)
20
+
21
+ expressions
22
+ .reduce(Result[entry, []]) do |result, expression|
23
+ yield(result.entry, expression)
24
+ .add_errors(result.errors)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ module Jade
2
+ module Frontend
3
+ module ForwardDeclaration
4
+ module Error
5
+ class BadImport < Jade::Error
6
+ def initialize(entry, span, name:, module_name:)
7
+ @name = name
8
+ @module_name = module_name
9
+ super(entry:, span:)
10
+ end
11
+
12
+ def message
13
+ "The `#{@module_name}` module does not expose `#{@name}`"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end