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,24 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module Error
5
+ class UnusedInterfaceTypeParam < Jade::Error
6
+ def initialize(entry, span, interface:, type_param:)
7
+ super(entry:, span:)
8
+ @interface = interface
9
+ @type_param = type_param
10
+ end
11
+
12
+ def message
13
+ "Interface `#{@interface}` declares type parameter `#{@type_param}` " \
14
+ "but no function uses it: there is nothing to dispatch on"
15
+ end
16
+
17
+ def label
18
+ "unused type parameter `#{@type_param}`"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module Error
5
+ class ValueNotExposed < 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
+ "#{@module_name} does not a expose `#{@name}`"
14
+ end
15
+
16
+ def label
17
+ "not exposed by #{@module_name}"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module Error
5
+ class VariableNotFound < Jade::Error
6
+ attr_reader :causes
7
+
8
+ def initialize(entry, span, name:, causes: [])
9
+ @name = name
10
+ @causes = causes
11
+ super(entry:, span:)
12
+ end
13
+
14
+ def message
15
+ "I cannot find a `#{@name}` variable"
16
+ end
17
+
18
+ def label
19
+ "not found"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,40 @@
1
+ require 'jade/error'
2
+
3
+ require 'jade/frontend/semantic_analysis/error/circular_extends'
4
+ require 'jade/frontend/semantic_analysis/error/constant_not_callable'
5
+ require 'jade/frontend/semantic_analysis/error/constructor_not_found'
6
+ require 'jade/frontend/semantic_analysis/error/constructor_pattern_arity_mismatch'
7
+ require 'jade/frontend/semantic_analysis/error/duplicate_field'
8
+ require 'jade/frontend/semantic_analysis/error/duplicate_function_declaration'
9
+ require 'jade/frontend/semantic_analysis/error/duplicate_record_field'
10
+ require 'jade/frontend/semantic_analysis/error/invalid_list_rest_pattern'
11
+ require 'jade/frontend/semantic_analysis/error/kwargs_on_non_constructor'
12
+ require 'jade/frontend/semantic_analysis/error/missing_exposing_clause'
13
+ require 'jade/frontend/semantic_analysis/error/missing_extends_implementation'
14
+ require 'jade/frontend/semantic_analysis/error/missing_field'
15
+ require 'jade/frontend/semantic_analysis/error/missing_implementation_function'
16
+ require 'jade/frontend/semantic_analysis/error/module_not_found'
17
+ require 'jade/frontend/semantic_analysis/error/nested_task_port'
18
+ require 'jade/frontend/semantic_analysis/error/non_task_port'
19
+ require 'jade/frontend/semantic_analysis/error/orphan_implementation'
20
+ require 'jade/frontend/semantic_analysis/error/predicate_must_return_bool'
21
+ require 'jade/frontend/semantic_analysis/error/predicate_name_not_allowed'
22
+ require 'jade/frontend/semantic_analysis/error/shadowing_error'
23
+ require 'jade/frontend/semantic_analysis/error/type_args_mismatch'
24
+ require 'jade/frontend/semantic_analysis/error/type_param_required'
25
+ require 'jade/frontend/semantic_analysis/error/unbound_type_variable'
26
+ require 'jade/frontend/semantic_analysis/error/undefined_variable'
27
+ require 'jade/frontend/semantic_analysis/error/unknown_field'
28
+ require 'jade/frontend/semantic_analysis/error/unknown_implementation_function'
29
+ require 'jade/frontend/semantic_analysis/error/unused_interface_type_param'
30
+ require 'jade/frontend/semantic_analysis/error/value_not_exposed'
31
+ require 'jade/frontend/semantic_analysis/error/variable_not_found'
32
+
33
+ module Jade
34
+ module Frontend
35
+ module SemanticAnalysis
36
+ module Error
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,60 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module FunctionCall
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::FunctionCall(callee:, args:)
10
+
11
+ callee_r = analyze_node(callee, registry, scope, entry)
12
+ args_r = analyze_in_parallel(args, registry, scope, entry)
13
+
14
+ Result
15
+ .combine(node, scope:, callee: callee_r, args: args_r)
16
+ .add_errors(
17
+ calling_a_constant?(callee_r.node, args_r.node, registry) ?
18
+ [constant_not_callable(callee_r.node, entry)] :
19
+ [],
20
+ )
21
+ end
22
+
23
+ private
24
+
25
+ def calling_a_constant?(callee, args, registry)
26
+ return false unless args.empty?
27
+
28
+ case callee_symbol(callee, registry)
29
+ in Symbol::Function | Symbol::StdlibFunction => fn then fn.constant?
30
+ in Symbol::Constructor(args: []) then true
31
+ else false
32
+ end
33
+ end
34
+
35
+ def callee_symbol(callee, registry)
36
+ case callee.symbol
37
+ in Symbol::ValueRef => ref then registry.lookup(ref)
38
+ in symbol then symbol
39
+ end
40
+ end
41
+
42
+ def constant_not_callable(callee, entry)
43
+ Error::ConstantNotCallable.new(
44
+ entry.name,
45
+ callee.range,
46
+ name: callee_display_name(callee),
47
+ )
48
+ end
49
+
50
+ def callee_display_name(callee)
51
+ case callee
52
+ in AST::VariableReference(name:) then name
53
+ in AST::ConstructorReference(name:) then name
54
+ in AST::QualifiedAccess(target:, name:) then "#{target.name}.#{name.name}"
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,58 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module FunctionDeclaration
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::FunctionDeclaration(name:, body:, params:, return_type:)
10
+
11
+ symbol_ref = entry.lookup_value(name).to_ref
12
+
13
+ params_r = params.reduce(Result[nil, [], scope]) do |acc, param|
14
+ bind(acc.scope, Symbol.var(param.name, param.range), entry)
15
+ .add_errors(acc.errors)
16
+ end
17
+
18
+ Result
19
+ .combine(node, scope:,
20
+ body: analyze_node(body, registry, params_r.scope, entry),
21
+ )
22
+ .map_node { it.with(symbol: symbol_ref) }
23
+ .add_errors(params_r.errors)
24
+ .add_errors(validate_type_symbol(symbol_ref, registry, entry))
25
+ .add_errors(validate_predicate_return(name, return_type, symbol_ref, registry, entry))
26
+ .add_errors(params.flat_map { validate_no_predicate_param(it, entry) })
27
+ end
28
+
29
+ # `?` suffix is reserved for function declaration names. Forbid
30
+ # it on parameters so `def f(empty?: Bool) -> Bool` doesn't bind
31
+ # `empty?` as a value.
32
+ def validate_no_predicate_param(param, entry)
33
+ return [] unless param.name.end_with?('?')
34
+
35
+ [Error::PredicateNameNotAllowed.new(entry.name, param.range, name: param.name)]
36
+ end
37
+
38
+ # `?`-suffixed function names must declare a `Bool` return type.
39
+ # Catches `def empty? -> Int` at semantic analysis.
40
+ def validate_predicate_return(name, return_type_ast, symbol, registry, entry)
41
+ return [] unless name.end_with?('?')
42
+
43
+ case registry.lookup(symbol).return_type
44
+ in Symbol::TypeRef['Basics', 'Bool'] |
45
+ Symbol::TypeApplication(constructor: Symbol::TypeRef['Basics', 'Bool'], args: [])
46
+ []
47
+ else
48
+ [Error::PredicateMustReturnBool.new(
49
+ entry.name,
50
+ return_type_ast.range,
51
+ fn_name: name,
52
+ )]
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,17 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module Grouping
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::Grouping(expression:)
10
+
11
+ analyze_node(expression, registry, scope, entry)
12
+ .map_node { node.with(expression: it) }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,152 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module Helper
5
+ def analyze_node(node, registry, scope, entry)
6
+ SemanticAnalysis.send(:analyze_node, node, registry, scope, entry)
7
+ end
8
+
9
+ def bind(scope, symbol, entry)
10
+ name = symbol.name
11
+ if scope.lookup(name)
12
+ Error::ShadowingError
13
+ .new(entry.name, symbol.decl_span, name:)
14
+ .then { Result[nil, [it], scope] }
15
+
16
+ else
17
+ Result[nil, [], scope.bind(name, symbol)]
18
+ end
19
+ end
20
+
21
+ def lookup(scope, name, entry, span)
22
+ if (decl = scope.lookup(name))
23
+ Result[decl, [], scope]
24
+
25
+ else
26
+ Error::UndefinedVariable
27
+ .new(entry.name, span, var_ref: name)
28
+ .then { Result[nil, [it], scope] }
29
+ end
30
+ end
31
+
32
+ # Threaded: child N analyzed with the scope produced by child N-1;
33
+ # the returned scope is the last child's. Use when later siblings
34
+ # depend on bindings introduced by earlier ones — body statements,
35
+ # lambda/function params, sequential pattern bindings.
36
+ def analyze_in_sequence(nodes, registry, scope, entry)
37
+ nodes.reduce(Result[[], [], scope]) do |acc, node|
38
+ r = analyze_node(node, registry, acc.scope, entry)
39
+ Result[acc.node + [r.node], acc.errors + r.errors, r.scope]
40
+ end
41
+ end
42
+
43
+ # Independent: every child analyzed with the input scope; the
44
+ # returned scope is the input scope (no bindings leak). Use when
45
+ # children don't see each other — record fields, list items,
46
+ # function-call args, if/case branches.
47
+ def analyze_in_parallel(nodes, registry, scope, entry)
48
+ results = nodes.map { analyze_node(it, registry, scope, entry) }
49
+ Result[results.map(&:node), results.flat_map(&:errors), scope]
50
+ end
51
+
52
+ def analyze_duplicate_fields(fields, entry)
53
+ fields
54
+ .group_by(&:key)
55
+ .select { |_, v| v.size > 1 }
56
+ .map do |k, v|
57
+ first, *rest = v
58
+ Error::DuplicateRecordField
59
+ .new(entry.name, first.range, field_name: k, duplicate_spans: rest.map(&:range))
60
+ end
61
+ end
62
+
63
+ def collect_vars(symbol, registry)
64
+ case symbol
65
+ in Symbol::TypeRef | Symbol::ValueRef
66
+ registry
67
+ .lookup(symbol)
68
+ .then { collect_vars(it, registry) }
69
+
70
+ in Symbol::Constructor(args:)
71
+ args
72
+ .flat_map { collect_vars(it, registry) }
73
+
74
+ in Symbol::Variable
75
+ [symbol]
76
+
77
+ in Symbol::TypeApplication | Symbol::PartialApplication
78
+ symbol
79
+ .args
80
+ .flat_map { collect_vars(it, registry) }
81
+
82
+ in Symbol::FunctionType | Symbol::InterfaceFunction
83
+ symbol
84
+ .params
85
+ .flat_map { collect_vars(it, registry) } +
86
+ collect_vars(symbol.return_type, registry)
87
+
88
+ in Symbol::RecordType(row_var:)
89
+ row_var.nil? ? [] : [row_var]
90
+ end
91
+ end
92
+
93
+ def validate_type_symbol(symbol, registry, entry)
94
+ case symbol
95
+ in Symbol::Union(variants:, type_params:)
96
+ variants.flat_map { validate_type_symbol(it, registry, entry) } +
97
+ type_params.flat_map { validate_type_symbol(it, registry, entry) }
98
+
99
+ in Symbol::Constructor(args:)
100
+ args.flat_map { validate_type_symbol(it, registry, entry) }
101
+
102
+ in Symbol::TypeRef
103
+ registry.lookup(symbol)
104
+ .then { validate_type_symbol(it, registry, entry) }
105
+
106
+ in Symbol::ValueRef
107
+ registry.lookup(symbol)
108
+ .then { validate_type_symbol(it, registry, entry) }
109
+
110
+ in Symbol::Variable
111
+ []
112
+
113
+ in Symbol::PartialApplication(constructor:, args:)
114
+ args.flat_map { validate_type_symbol(it, registry, entry) }
115
+
116
+ in Symbol::TypeApplication(constructor:, args:)
117
+ constructor_symbol = registry.lookup(constructor)
118
+
119
+ if constructor_symbol.type_params.size != args.size
120
+ [Error::TypeArgsMismatch.new(
121
+ entry.name,
122
+ symbol.span,
123
+ type_name: constructor.name,
124
+ expected: constructor_symbol.type_params.size,
125
+ actual: args.size
126
+ )]
127
+ else
128
+ []
129
+ end + args.flat_map { validate_type_symbol(it, registry, entry) }
130
+
131
+ in Symbol::FunctionType | Symbol::InterfaceFunction | Symbol::InteropFunction
132
+ validate_type_symbol(symbol.return_type, registry, entry) +
133
+ symbol.params.flat_map { validate_type_symbol(it, registry, entry) }
134
+
135
+ in Symbol::Function(params:, return_type:)
136
+ validate_type_symbol(return_type, registry, entry) +
137
+ params.values.flat_map { validate_type_symbol(it, registry, entry) }
138
+
139
+ in Symbol::RecordType(fields:)
140
+ fields.reduce([]) do |acc, (k, v)|
141
+ acc + validate_type_symbol(v, registry, entry)
142
+ end
143
+
144
+ in Symbol::Struct(type_params:, record_type:)
145
+ validate_type_symbol(record_type, registry, entry) +
146
+ type_params.flat_map { validate_type_symbol(it, registry, entry) }
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,20 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module IfThenElse
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::IfThenElse(condition:, if_branch:, else_branch:)
10
+
11
+ Result.combine(node, scope:,
12
+ condition: analyze_node(condition, registry, scope, entry),
13
+ if_branch: analyze_node(if_branch, registry, scope, entry),
14
+ else_branch: analyze_node(else_branch, registry, scope, entry),
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,143 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module Implementation
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::Implementation(interface:, applied_type:, extends:, functions:)
10
+
11
+ interface_ref = entry.lookup_type(interface).to_ref
12
+ type_sym = lookup_applied_type(applied_type, entry)
13
+ type_ref = type_sym.to_ref
14
+
15
+ impl_symbol = entry.implementations[[
16
+ interface_ref.qualified_name,
17
+ type_ref.qualified_name,
18
+ ]]
19
+
20
+ functions_r = analyze_in_parallel(functions, registry, scope, entry)
21
+
22
+ make_error = ->(klass, **kw) { klass.new(entry.name, node.range, **kw) }
23
+ type_is_local = entry.defined_types.key?(local_type_name(applied_type))
24
+
25
+ unless entry.defined_types.key?(interface) || type_is_local
26
+ return make_error
27
+ .(
28
+ Error::OrphanImplementation,
29
+ interface: entry.lookup_type(interface).qname,
30
+ type: type_sym.qname,
31
+ )
32
+ .then { Result[node, [it], scope] }
33
+ end
34
+
35
+ iface_sym = registry.lookup(interface_ref)
36
+
37
+ extends_errors = extends
38
+ .flat_map do |iface_name|
39
+ ext_sym = entry.lookup_type(iface_name)
40
+ next [] if entry.implementations.key?([ext_sym.qname, type_sym.qname])
41
+
42
+ [make_error.(
43
+ Error::MissingExtendsImplementation,
44
+ interface: ext_sym.qname,
45
+ type: type_sym.qname,
46
+ required_by: iface_sym.qname,
47
+ )]
48
+ end
49
+
50
+ cycle_errors =
51
+ if extends_errors.empty? && cycle_in_extends?(iface_sym.qname, type_sym.qname, entry)
52
+ [make_error.(Error::CircularExtends, interface: iface_sym.qname, type: type_sym.qname)]
53
+ else
54
+ []
55
+ end
56
+
57
+ type_param_errors =
58
+ case [parameterized_interface?(iface_sym), type_sym]
59
+ in [true, { type_params: [] }]
60
+ [make_error.(Error::TypeParamRequired, interface: iface_sym.qname, type: type_sym.qname)]
61
+ else
62
+ []
63
+ end
64
+
65
+ Result
66
+ .combine(node, scope:, functions: functions_r)
67
+ .map_node { it.with(symbol: impl_symbol) }
68
+ .add_errors(
69
+ fn_name_errors(functions, iface_sym, &make_error) +
70
+ extends_errors + cycle_errors + type_param_errors,
71
+ )
72
+ end
73
+
74
+ private
75
+
76
+ def lookup_applied_type(applied_type, entry)
77
+ case applied_type.constructor
78
+ in AST::TypeName(type:)
79
+ entry.lookup_type(type)
80
+ in AST::QualifiedTypeName(path:)
81
+ *module_parts, type_name = path
82
+ entry.lookup_qualified_type(module_parts.join('.'), type_name)
83
+ end
84
+ end
85
+
86
+ def local_type_name(applied_type)
87
+ case applied_type.constructor
88
+ in AST::TypeName(type:) then type
89
+ in AST::QualifiedTypeName then nil
90
+ end
91
+ end
92
+
93
+ def parameterized_interface?(iface_sym)
94
+ iface_sym.functions.any? { contains_partial_application?(it) }
95
+ end
96
+
97
+ def contains_partial_application?(sym)
98
+ case sym
99
+ in Symbol::PartialApplication
100
+ true
101
+ in { params:, return_type: }
102
+ params.any? { contains_partial_application?(it) } || contains_partial_application?(return_type)
103
+ else
104
+ false
105
+ end
106
+ end
107
+
108
+ def fn_name_errors(functions, iface_sym, &make_error)
109
+ impl_names = functions.map(&:name).to_set
110
+ iface_names = iface_sym.functions.map(&:name).to_set
111
+ unknown = impl_names.difference(iface_names)
112
+
113
+ if unknown.any?
114
+ unknown.map { make_error.(Error::UnknownImplementationFunction, interface: iface_sym.qname, fn_name: it) }
115
+ else
116
+ iface_names
117
+ .difference(impl_names)
118
+ .map { make_error.(Error::MissingImplementationFunction, interface: iface_sym.qname, fn_name: it) }
119
+ end
120
+ end
121
+
122
+ def cycle_in_extends?(interface_qname, type_qname, entry, visited: ::Set.new)
123
+ key = [interface_qname, type_qname]
124
+ return true if visited.include?(key)
125
+
126
+ impl = entry.implementations[key]
127
+ return false unless impl&.extends&.any?
128
+
129
+ impl
130
+ .extends
131
+ .any? do
132
+ cycle_in_extends?(
133
+ it.qualified_name,
134
+ type_qname,
135
+ entry,
136
+ visited: visited | [key],
137
+ )
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,16 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module ImplementationFunction
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::ImplementationFunction(fn:)
10
+
11
+ Result.combine(node, scope:, fn: analyze_node(fn, registry, scope, entry))
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module ImportDeclaration
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, _registry, scope, _entry)
9
+ Result.init(node, scope)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,45 @@
1
+ module Jade
2
+ module Frontend
3
+ module SemanticAnalysis
4
+ module InterfaceDeclaration
5
+ extend self
6
+ extend Helper
7
+
8
+ def analyze(node, registry, scope, entry)
9
+ node => AST::InterfaceDeclaration(name:)
10
+
11
+ symbol_ref = entry.lookup_type(name).to_ref
12
+ interface = registry.lookup(symbol_ref)
13
+
14
+ Result
15
+ .init(node.with(symbol: symbol_ref), scope)
16
+ .add_errors(
17
+ interface.functions.flat_map { validate_type_symbol(it, registry, entry) } +
18
+ validate_type_param_used(interface, registry, entry),
19
+ )
20
+ end
21
+
22
+ private
23
+
24
+ def validate_type_param_used(interface, registry, entry)
25
+ used_names = interface
26
+ .functions
27
+ .flat_map { collect_vars(it, registry) }
28
+ .map(&:name)
29
+ .to_set
30
+
31
+ return [] if used_names.include?(interface.type_param.name)
32
+
33
+ [
34
+ Error::UnusedInterfaceTypeParam.new(
35
+ entry.name,
36
+ interface.decl_span,
37
+ interface: interface.name,
38
+ type_param: interface.type_param.name,
39
+ )
40
+ ]
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end