firefly-compiler 0.4.4

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 (221) hide show
  1. package/.firefly-workspace +1 -0
  2. package/.vscode/settings.json +5 -0
  3. package/LICENSE.txt +21 -0
  4. package/README.md +96 -0
  5. package/bin/firefly.mjs +2 -0
  6. package/compiler/.firefly/package.ff +1 -0
  7. package/compiler/Builder.ff +218 -0
  8. package/compiler/Compiler.ff +241 -0
  9. package/compiler/Dependencies.ff +179 -0
  10. package/compiler/Deriver.ff +647 -0
  11. package/compiler/Dictionaries.ff +205 -0
  12. package/compiler/Environment.ff +166 -0
  13. package/compiler/Inference.ff +1117 -0
  14. package/compiler/JsEmitter.ff +861 -0
  15. package/compiler/JsImporter.ff +56 -0
  16. package/compiler/LspHook.ff +188 -0
  17. package/compiler/Main.ff +237 -0
  18. package/compiler/Parser.ff +1383 -0
  19. package/compiler/Patterns.ff +111 -0
  20. package/compiler/Resolver.ff +620 -0
  21. package/compiler/Substitution.ff +178 -0
  22. package/compiler/Syntax.ff +299 -0
  23. package/compiler/Token.ff +180 -0
  24. package/compiler/Tokenizer.ff +278 -0
  25. package/compiler/Unification.ff +220 -0
  26. package/compiler/Wildcards.ff +50 -0
  27. package/compiler/Workspace.ff +88 -0
  28. package/core/.firefly/package.ff +2 -0
  29. package/core/Any.ff +30 -0
  30. package/core/Array.ff +249 -0
  31. package/core/AssetSystem.ff +61 -0
  32. package/core/Atomic.ff +64 -0
  33. package/core/Bool.ff +13 -0
  34. package/core/BrowserSystem.ff +14 -0
  35. package/core/Buffer.ff +211 -0
  36. package/core/BuildSystem.ff +144 -0
  37. package/core/Channel.ff +131 -0
  38. package/core/Char.ff +18 -0
  39. package/core/Core.ff +58 -0
  40. package/core/Duration.ff +15 -0
  41. package/core/Equal.ff +52 -0
  42. package/core/Error.ff +20 -0
  43. package/core/FileHandle.ff +41 -0
  44. package/core/Float.ff +41 -0
  45. package/core/HttpClient.ff +84 -0
  46. package/core/Instant.ff +9 -0
  47. package/core/Int.ff +61 -0
  48. package/core/IntMap.ff +85 -0
  49. package/core/JsSystem.ff +66 -0
  50. package/core/JsValue.ff +240 -0
  51. package/core/List.ff +440 -0
  52. package/core/Lock.ff +144 -0
  53. package/core/Log.ff +24 -0
  54. package/core/Map.ff +126 -0
  55. package/core/NodeSystem.ff +88 -0
  56. package/core/Nothing.ff +1 -0
  57. package/core/Option.ff +133 -0
  58. package/core/Ordering.ff +157 -0
  59. package/core/Pair.ff +55 -0
  60. package/core/Path.ff +393 -0
  61. package/core/RbMap.ff +216 -0
  62. package/core/Serializable.ff +173 -0
  63. package/core/Set.ff +38 -0
  64. package/core/Show.ff +43 -0
  65. package/core/Stack.ff +263 -0
  66. package/core/Stream.ff +406 -0
  67. package/core/String.ff +175 -0
  68. package/core/StringMap.ff +85 -0
  69. package/core/Task.ff +138 -0
  70. package/core/Try.ff +81 -0
  71. package/core/Unit.ff +3 -0
  72. package/experimental/random/AltGeneric.ff +44 -0
  73. package/experimental/random/Async.ff +68 -0
  74. package/experimental/random/Buffer2.ff +77 -0
  75. package/experimental/random/Cat.ff +12 -0
  76. package/experimental/random/Dictionary.ff +52 -0
  77. package/experimental/random/Example.ff +46 -0
  78. package/experimental/random/Generic.ff +102 -0
  79. package/experimental/random/HappyEyeballs.ff +40 -0
  80. package/experimental/random/HashMap.ff +72 -0
  81. package/experimental/random/IfElseUnit.ff +9 -0
  82. package/experimental/random/InputOutput.ff +23 -0
  83. package/experimental/random/ListVsArray.ff +45 -0
  84. package/experimental/random/Main.ff +44 -0
  85. package/experimental/random/MapTest.ff +67 -0
  86. package/experimental/random/OldTaskSystem.ff +210 -0
  87. package/experimental/random/PatternTest.ff +39 -0
  88. package/experimental/random/Patterns.ff +226 -0
  89. package/experimental/random/ReadBytesTest.ff +10 -0
  90. package/experimental/random/RunLength.ff +65 -0
  91. package/experimental/random/Scrape.ff +51 -0
  92. package/experimental/random/Serialization.ff +217 -0
  93. package/experimental/random/SerializationTest.ff +46 -0
  94. package/experimental/random/Serializer.ff +36 -0
  95. package/experimental/random/StdInOutErr.ff +4 -0
  96. package/experimental/random/Symbols.ff +74 -0
  97. package/experimental/random/Tag.ff +49 -0
  98. package/experimental/random/Tensor.ff +52 -0
  99. package/experimental/random/Try.ff +56 -0
  100. package/experimental/random/Tsv.ff +9 -0
  101. package/experimental/random/TypesAreModules.ff +87 -0
  102. package/experimental/random/blueprints/Blueprint.ff +52 -0
  103. package/experimental/random/blueprints/Main.ff +11 -0
  104. package/experimental/random/blueprints/Pretty.ff +58 -0
  105. package/experimental/random/blueprints/User.ff +64 -0
  106. package/experimental/random/blueprintsystem/BlueprintSystem.ff +48 -0
  107. package/experimental/random/blueprintsystem/Deserialize.ff +53 -0
  108. package/experimental/random/blueprintsystem/ReadJs.ff +13 -0
  109. package/experimental/random/blueprintsystem/User.ff +2 -0
  110. package/experimental/random/kahrs/Kahrs.ff +112 -0
  111. package/experimental/random/kahrs/TestKahrs.ff +22 -0
  112. package/experimental/random/kahrs/TestMap.ff +18 -0
  113. package/experimental/random/streaming/Gzip.ff +3 -0
  114. package/experimental/random/streaming/Main.ff +34 -0
  115. package/experimental/random/streaming/S3Bucket.ff +11 -0
  116. package/experimental/random/streaming/Tar.ff +5 -0
  117. package/experimental/rhymeapp/Main.ff +81 -0
  118. package/experimental/rhymeapp/index.html +14 -0
  119. package/firefly.sh +5 -0
  120. package/fireflysite/Main.ff +13 -0
  121. package/httpserver/.firefly/package.ff +1 -0
  122. package/httpserver/HttpServer.ff +184 -0
  123. package/lsp/.firefly/package.ff +1 -0
  124. package/lsp/CompletionHandler.ff +814 -0
  125. package/lsp/Handler.ff +551 -0
  126. package/lsp/HoverHandler.ff +82 -0
  127. package/lsp/LanguageServer.ff +229 -0
  128. package/lsp/SignatureHelpHandler.ff +55 -0
  129. package/lsp/SymbolHandler.ff +167 -0
  130. package/output/js/ff/compiler/Builder.mjs +483 -0
  131. package/output/js/ff/compiler/Compiler.mjs +410 -0
  132. package/output/js/ff/compiler/Dependencies.mjs +388 -0
  133. package/output/js/ff/compiler/Deriver.mjs +1166 -0
  134. package/output/js/ff/compiler/Dictionaries.mjs +1305 -0
  135. package/output/js/ff/compiler/Environment.mjs +1005 -0
  136. package/output/js/ff/compiler/Inference.mjs +4264 -0
  137. package/output/js/ff/compiler/JsEmitter.mjs +5353 -0
  138. package/output/js/ff/compiler/JsImporter.mjs +262 -0
  139. package/output/js/ff/compiler/LspHook.mjs +789 -0
  140. package/output/js/ff/compiler/Main.mjs +1695 -0
  141. package/output/js/ff/compiler/Parser.mjs +4004 -0
  142. package/output/js/ff/compiler/Patterns.mjs +923 -0
  143. package/output/js/ff/compiler/Resolver.mjs +2303 -0
  144. package/output/js/ff/compiler/Substitution.mjs +1146 -0
  145. package/output/js/ff/compiler/Syntax.mjs +12430 -0
  146. package/output/js/ff/compiler/Token.mjs +3092 -0
  147. package/output/js/ff/compiler/Tokenizer.mjs +589 -0
  148. package/output/js/ff/compiler/Unification.mjs +1748 -0
  149. package/output/js/ff/compiler/Wildcards.mjs +604 -0
  150. package/output/js/ff/compiler/Workspace.mjs +683 -0
  151. package/output/js/ff/core/Any.mjs +139 -0
  152. package/output/js/ff/core/Array.mjs +594 -0
  153. package/output/js/ff/core/AssetSystem.mjs +270 -0
  154. package/output/js/ff/core/Atomic.mjs +186 -0
  155. package/output/js/ff/core/Bool.mjs +141 -0
  156. package/output/js/ff/core/BrowserSystem.mjs +122 -0
  157. package/output/js/ff/core/Buffer.mjs +467 -0
  158. package/output/js/ff/core/BuildSystem.mjs +320 -0
  159. package/output/js/ff/core/Channel.mjs +268 -0
  160. package/output/js/ff/core/Char.mjs +145 -0
  161. package/output/js/ff/core/Core.mjs +300 -0
  162. package/output/js/ff/core/Duration.mjs +112 -0
  163. package/output/js/ff/core/Equal.mjs +175 -0
  164. package/output/js/ff/core/Error.mjs +138 -0
  165. package/output/js/ff/core/FileHandle.mjs +164 -0
  166. package/output/js/ff/core/Float.mjs +214 -0
  167. package/output/js/ff/core/HttpClient.mjs +210 -0
  168. package/output/js/ff/core/Instant.mjs +105 -0
  169. package/output/js/ff/core/Int.mjs +254 -0
  170. package/output/js/ff/core/IntMap.mjs +282 -0
  171. package/output/js/ff/core/JsSystem.mjs +234 -0
  172. package/output/js/ff/core/JsValue.mjs +678 -0
  173. package/output/js/ff/core/List.mjs +2335 -0
  174. package/output/js/ff/core/Lock.mjs +322 -0
  175. package/output/js/ff/core/Log.mjs +159 -0
  176. package/output/js/ff/core/Map.mjs +358 -0
  177. package/output/js/ff/core/NodeSystem.mjs +288 -0
  178. package/output/js/ff/core/Nothing.mjs +100 -0
  179. package/output/js/ff/core/Option.mjs +1002 -0
  180. package/output/js/ff/core/Ordering.mjs +734 -0
  181. package/output/js/ff/core/Pair.mjs +318 -0
  182. package/output/js/ff/core/Path.mjs +768 -0
  183. package/output/js/ff/core/RbMap.mjs +1936 -0
  184. package/output/js/ff/core/Serializable.mjs +434 -0
  185. package/output/js/ff/core/Set.mjs +250 -0
  186. package/output/js/ff/core/Show.mjs +201 -0
  187. package/output/js/ff/core/Stack.mjs +595 -0
  188. package/output/js/ff/core/Stream.mjs +1300 -0
  189. package/output/js/ff/core/String.mjs +433 -0
  190. package/output/js/ff/core/StringMap.mjs +282 -0
  191. package/output/js/ff/core/Task.mjs +345 -0
  192. package/output/js/ff/core/Try.mjs +503 -0
  193. package/output/js/ff/core/Unit.mjs +103 -0
  194. package/package.json +29 -0
  195. package/postgresql/.firefly/include/package-lock.json +250 -0
  196. package/postgresql/.firefly/include/package.json +5 -0
  197. package/postgresql/.firefly/include/prepare.sh +2 -0
  198. package/postgresql/.firefly/package.ff +3 -0
  199. package/postgresql/Pg.ff +530 -0
  200. package/unsafejs/.firefly/package.ff +1 -0
  201. package/unsafejs/UnsafeJs.ff +19 -0
  202. package/vscode/.vscode/launch.json +18 -0
  203. package/vscode/.vscode/tasks.json +33 -0
  204. package/vscode/LICENSE.txt +21 -0
  205. package/vscode/Prepublish.ff +15 -0
  206. package/vscode/README.md +17 -0
  207. package/vscode/client/package-lock.json +544 -0
  208. package/vscode/client/package.json +22 -0
  209. package/vscode/client/src/extension.ts +64 -0
  210. package/vscode/client/tsconfig.json +12 -0
  211. package/vscode/icons/firefly-icon.png +0 -0
  212. package/vscode/icons/firefly-icon.svg +10 -0
  213. package/vscode/icons/firefly-logo-notext.png +0 -0
  214. package/vscode/icons/firefly-logo.png +0 -0
  215. package/vscode/language-configuration.json +39 -0
  216. package/vscode/package-lock.json +3623 -0
  217. package/vscode/package.json +144 -0
  218. package/vscode/snippets-none.json +1 -0
  219. package/vscode/snippets.json +241 -0
  220. package/vscode/syntaxes/firefly.tmLanguage.json +294 -0
  221. package/vscode/tsconfig.json +20 -0
@@ -0,0 +1,620 @@
1
+ import Syntax
2
+ import LspHook
3
+
4
+ class Resolver(
5
+ variables: Map[String, String]
6
+ variableLocations: Map[String, Location]
7
+ variants: Map[String, String]
8
+ types: Map[String, String]
9
+ typeGenerics: Map[String, List[String]]
10
+ typeLocations: Map[String, Location]
11
+ asyncTypes: Set[String]
12
+ typeParameters: Set[String]
13
+ traits: Map[String, String]
14
+ traitLocations: Map[String, Location]
15
+ state: ResolverState
16
+ lspHook: LspHook
17
+ )
18
+
19
+ class ResolverState(
20
+ mutable nextUnificationVariableIndex: Int
21
+ )
22
+
23
+ make(lspHook: LspHook): Resolver {
24
+ Resolver(
25
+ variables = [].toMap()
26
+ variableLocations = [].toMap()
27
+ variants = [].toMap()
28
+ types = [].toMap()
29
+ typeGenerics = [].toMap()
30
+ typeLocations = [].toMap()
31
+ asyncTypes = [].toSet()
32
+ typeParameters = [].toSet()
33
+ traits = [].toMap()
34
+ traitLocations = [].toMap()
35
+ state = ResolverState(
36
+ nextUnificationVariableIndex = 2
37
+ ) // To avoid collision with the parser and unification
38
+ lspHook = lspHook
39
+ )
40
+ }
41
+
42
+ extend self: Resolver {
43
+
44
+ freshUnificationVariable(at: Location): Type {
45
+ let result = TVariable(at, self.state.nextUnificationVariableIndex)
46
+ self.state.nextUnificationVariableIndex += 3
47
+ result
48
+ }
49
+
50
+ resolveModule(module: Module, otherModules: List[Module]): Module {
51
+ let moduleNamespace =
52
+ module.file.replace("\\", "/").reverse().takeWhile { _ != '/' }.reverse().takeWhile { _ != '.' }
53
+ let self2 = self.processImports(module.imports, otherModules)
54
+ let self3 = self2.processDefinitions(module, None)
55
+ let module2 = module.Module(
56
+ types = module.types.map { self3.resolveTypeDefinition(_) }
57
+ traits = module.traits.map { self3.resolveTraitDefinition(_) }
58
+ instances = module.instances.map { self3.resolveInstanceDefinition(_) }
59
+ extends = module.extends.map { self3.resolveExtendDefinition(_) }
60
+ lets = module.lets.map { self3.resolveLetDefinition(_, True) }
61
+ functions = module.functions.map { self3.resolveFunctionDefinition(_, True, False) }
62
+ )
63
+ module2.instances.each {_.typeArguments.each {self3.checkInstanceType(_)}}
64
+ module2
65
+ }
66
+
67
+ checkInstanceType(type: Type) {
68
+ type.{
69
+ | TConstructor(_, name, typeArguments) =>
70
+ if(self.asyncTypes.contains(name)) {
71
+ throw(CompileError(type.at, "Traits must not be instantiated for capability types"))
72
+ }
73
+ typeArguments.each {self.checkInstanceType(_)}
74
+ | _ =>
75
+ }
76
+ }
77
+
78
+ processImports(imports: List[DImport], modules: List[Module]): Resolver {
79
+ mutable resolver = self
80
+ imports.each { import =>
81
+ modules.find { _.file.dropLast(3) == import.file }.{
82
+ | Some(module) =>
83
+ resolver = resolver.processDefinitions(module, Some(import.alias))
84
+ | None =>
85
+ throw(CompileError(import.at, "No such module: " + import.file))
86
+ }
87
+ }
88
+ resolver
89
+ }
90
+
91
+ processDefinitions(module: Module, importAlias: Option[String]): Resolver {
92
+ function entry(name: String, unqualified: Bool): List[Pair[String, String]] {
93
+ let full =
94
+ module.packagePair.groupName() + "/" +
95
+ module.file.dropLast(3) + "." + name
96
+ importAlias.{
97
+ | None => [Pair(name, full), Pair(full, full)]
98
+ | Some(alias) { unqualified } => [Pair(alias + "." + name, full), Pair(name, full), Pair(full, full)]
99
+ | Some(alias) => [Pair(alias + "." + name, full), Pair(full, full)]
100
+ }
101
+ }
102
+ let isCore = // TODO: Extend imports to list unqualified symbols instead of this
103
+ module.packagePair.group == "ff" &&
104
+ module.packagePair.name == "core" &&
105
+ module.file == "Core.ff"
106
+ let lets = module.lets.flatMap { entry(_.name, isCore) }.toMap()
107
+ let letLocations = module.lets.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}} }.toMap()
108
+ let functions = module.functions.flatMap { entry(_.signature.name, isCore) }.toMap()
109
+ let functionLocations = module.functions.flatMap {d => entry(d.signature.name, True).map {_.mapSecond {_ => d.at}} }.toMap()
110
+ let traitMethods = module.traits.flatMap { _.methods }.flatMap { entry(_.name, False) }.toMap()
111
+ let traitMethodLocations = module.traits.flatMap {_.methods}.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}} }.toMap()
112
+ let traits = module.traits.flatMap { entry(_.name, True) }.toMap()
113
+ let traitLocations = module.traits.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}} }.toMap()
114
+ let types = module.types.flatMap { entry(_.name, True) }.toMap()
115
+ let typeGenerics = module.types.flatMap {d => entry(d.name, True).map {p => Pair(p.first, d.generics)}}.toMap()
116
+ let typeLocations = module.types.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}} }.toMap()
117
+ let asyncTypes = module.types.filter { _.generics.first().any {_ == "Q$"} }
118
+ .flatMap { entry(_.name, True).map {_.first} }.toSet()
119
+ let variants = module.types.flatMap { _.variants }.flatMap { entry(_.name, True) }.toMap()
120
+ self.Resolver(
121
+ variables = self.variables.addAll(lets).addAll(functions).addAll(traitMethods)
122
+ variableLocations = self.variableLocations.addAll(letLocations).addAll(functionLocations).addAll(traitMethodLocations)
123
+ variants = self.variants.addAll(variants)
124
+ types = self.types.addAll(types)
125
+ typeGenerics = self.typeGenerics.addAll(typeGenerics)
126
+ typeLocations = self.typeLocations.addAll(typeLocations)
127
+ asyncTypes = self.asyncTypes.addAll(asyncTypes)
128
+ typeParameters = [].toSet()
129
+ traits = self.traits.addAll(traits)
130
+ traitLocations = self.traitLocations.addAll(traitLocations)
131
+ state = self.state
132
+ )
133
+ }
134
+
135
+ resolveTypeDefinition(definition: DType): DType {
136
+ if(self.lspHook.isAt(definition.at)) {
137
+ self.lspHook.emit(
138
+ ResolveSymbolHook(SymbolHook(definition.name, definition.at, definition.at), None)
139
+ )
140
+ }
141
+ let generics = definition.generics.map {g => Pair(g, g)}.toMap()
142
+ let self2 = self.Resolver(
143
+ types = self.types.addAll(generics)
144
+ asyncTypes = self.asyncTypes.removeAll(definition.generics.toSet())
145
+ typeParameters = self.typeParameters.addAll(definition.generics.toSet())
146
+ )
147
+ if(!definition.generics.first().any {_ == "Q$"}) {
148
+ [...definition.commonFields, ...definition.variants.flatMap {_.fields}].each {f =>
149
+ if(self2.containsAsyncType(f.valueType)) {
150
+ throw(CompileError(f.at, "Only capabilities can contain fields of concrete capability types"))
151
+ }
152
+ }
153
+ }
154
+ definition.DType(
155
+ constraints = definition.constraints.map {self2.resolveConstraint(_, True)}
156
+ commonFields = definition.commonFields.map {f =>
157
+ let valueType = self2.resolveType(f.valueType, True)
158
+ if(self.lspHook.isAt(f.at) || self.lspHook.isDefinedAt(f.at)) {
159
+ self.lspHook.emit(
160
+ ResolveVariantFieldHook(SymbolHook(f.name, f.at, f.at), valueType, commonField = True)
161
+ )
162
+ }
163
+ f.Parameter(
164
+ valueType = valueType
165
+ default = f.default.map {self2.resolveTerm(_, True)}
166
+ )
167
+ }
168
+ variants = definition.variants.map {v =>
169
+ if(self.lspHook.isAt(v.at)) {
170
+ self.lspHook.emit(
171
+ ResolveSymbolHook(SymbolHook(v.name, v.at, v.at), None)
172
+ )
173
+ }
174
+ v.Variant(fields = v.fields.map {f =>
175
+ let valueType = self2.resolveType(f.valueType, True)
176
+ if(self.lspHook.isAt(f.at) || self.lspHook.isDefinedAt(f.at)) {
177
+ self.lspHook.emit(
178
+ ResolveVariantFieldHook(SymbolHook(f.name, f.at, f.at), valueType, commonField = False)
179
+ )
180
+ }
181
+ f.Parameter(
182
+ valueType = valueType
183
+ default = f.default.map {self2.resolveTerm(_, True) }
184
+ )
185
+ })
186
+ }
187
+ )
188
+ }
189
+
190
+ resolveTraitDefinition(definition: DTrait): DTrait {
191
+ if(self.lspHook.isAt(definition.at) || self.lspHook.isDefinedAt(definition.at)) {
192
+ self.lspHook.emit(
193
+ ResolveSymbolHook(
194
+ SymbolHook(definition.name, definition.at, definition.at), None
195
+ )
196
+ )
197
+ }
198
+ let generics = definition.generics.map {g => Pair(g, g)}.toMap()
199
+ let self2 = self.Resolver(
200
+ types = self.types.addAll(generics)
201
+ asyncTypes = self.asyncTypes.removeAll(definition.generics.toSet())
202
+ typeParameters = self.typeParameters.addAll(definition.generics.toSet())
203
+ )
204
+ definition.DTrait(
205
+ constraints = definition.constraints.map {self2.resolveConstraint(_, True)}
206
+ methods = definition.methods.map {self2.resolveSignature(_, True, False)}
207
+ methodDefaults = definition.methodDefaults.map {| Pair(name, lambda) =>
208
+ let signature = definition.methods.find {_.name == name}.grab()
209
+ let function1 = DFunction(signature.at, signature, FireflyTarget(lambda))
210
+ let function2 = self2.resolveFunctionDefinition(function1, True, False)
211
+ Pair(name, function2.body.{
212
+ | FireflyTarget(lambda) => lambda
213
+ | _ => throw(CompileError(signature.at, "Internal error: Expected method default to be a lambda"))
214
+ })
215
+ }
216
+ )
217
+ }
218
+
219
+ resolveInstanceDefinition(definition: DInstance): DInstance {
220
+ let traitDefinedAt = self.traitLocations.get(definition.traitName).else {definition.at}
221
+ if(self.lspHook.isAt(definition.at) || self.lspHook.isDefinedAt(traitDefinedAt)) {
222
+ self.lspHook.emit(
223
+ ResolveSymbolHook(
224
+ SymbolHook(definition.traitName, definition.at, traitDefinedAt), None
225
+ )
226
+ )
227
+ }
228
+ let generics = definition.generics.map {g => Pair(g, g) }.toMap()
229
+ let self2 = self.Resolver(
230
+ types = self.types.addAll(generics)
231
+ asyncTypes = self.asyncTypes.removeAll(definition.generics.toSet())
232
+ typeParameters = self.typeParameters.addAll(definition.generics.toSet())
233
+ )
234
+ let traitName = self2.traits.get(definition.traitName).else {
235
+ throw(CompileError(definition.at, "No such trait: " + definition.traitName))
236
+ }
237
+ definition.DInstance(
238
+ constraints = definition.constraints.map { self2.resolveConstraint(_, True) }
239
+ traitName = traitName
240
+ typeArguments = definition.typeArguments.map { self2.resolveType(_, True) }
241
+ methods = definition.methods.map { self2.resolveFunctionDefinition(_, True, True) }
242
+ )
243
+ }
244
+
245
+ resolveExtendDefinition(definition: DExtend): DExtend {
246
+ let generics = definition.generics.map {g => Pair(g, g)}.toMap()
247
+ let selfWithNoQ = self.Resolver(
248
+ types = self.types.addAll(generics)
249
+ asyncTypes = self.asyncTypes.removeAll(definition.generics.toSet())
250
+ typeParameters = self.typeParameters.addAll(definition.generics.toSet())
251
+ variables = self.variables.add(definition.name, definition.name)
252
+ variableLocations = self.variableLocations.add(definition.name, definition.at)
253
+ )
254
+ let selfWithQ = selfWithNoQ.Resolver(
255
+ types = selfWithNoQ.types.add("Q$", "Q$")
256
+ typeParameters = selfWithNoQ.typeParameters.add("Q$")
257
+ )
258
+ definition.DExtend(
259
+ constraints = definition.constraints.map {selfWithQ.resolveConstraint(_, True)}
260
+ type = selfWithQ.resolveType(definition.type, True)
261
+ methods = definition.methods.map {selfWithNoQ.resolveFunctionDefinition(_, True, False)}
262
+ )
263
+ }
264
+
265
+ resolveLetDefinition(definition: DLet, topLevel: Bool): DLet {
266
+ if(self.lspHook.isAt(definition.at) || self.lspHook.isDefinedAt(definition.at)) {
267
+ self.lspHook.emit(
268
+ ResolveSymbolHook(
269
+ SymbolHook(definition.name, definition.at, definition.at), None
270
+ )
271
+ )
272
+ }
273
+ definition.DLet(
274
+ variableType = self.resolveType(definition.variableType, topLevel)
275
+ value = self.resolveTerm(definition.value, True)
276
+ )
277
+ }
278
+
279
+ resolveTerm(term: Term, topLevel: Bool): Term {
280
+ | EString _, _ => term
281
+ | EChar _, _ => term
282
+ | EInt _, _ => term
283
+ | EFloat _, _ => term
284
+ | EVariable e, _ =>
285
+ if(self.lspHook.isEnabled()) {
286
+ let at = self.variableLocations.get(e.name).else {e.at}
287
+ if(self.lspHook.isAt(e.at) || self.lspHook.isDefinedAt(at)) {
288
+ self.lspHook.emit(
289
+ ResolveSymbolHook(
290
+ SymbolHook(e.name, e.at, at), None
291
+ )
292
+ )
293
+ }
294
+ }
295
+ self.variables.get(e.name).map {e.EVariable(name = _)}.else {term}
296
+ | EList(at, t, items), _ =>
297
+ EList(at, self.resolveType(t, topLevel), items.map {| Pair(item, spread) =>
298
+ Pair(self.resolveTerm(item, topLevel), spread)
299
+ })
300
+ | EVariant(at, name, typeArguments, arguments), _ =>
301
+ EVariant(
302
+ at = at
303
+ name = self.variants.get(name).else {name}
304
+ typeArguments = typeArguments.map {self.resolveType(_, topLevel)}
305
+ arguments = arguments.map {_.map {a => a.Argument(value = self.resolveTerm(a.value, topLevel))}}
306
+ )
307
+ | EVariantIs(at, name, typeArguments), _ =>
308
+ EVariantIs(
309
+ at = at
310
+ name = self.variants.get(name).else { throw(CompileError(at, "No such variant: " + name)) }
311
+ typeArguments = typeArguments.map { self.resolveType(_, topLevel) }
312
+ )
313
+ | ECopy(at, name, record, arguments), _ =>
314
+ ECopy(
315
+ at = at
316
+ name = self.variants.get(name).else {name}
317
+ record = self.resolveTerm(record, topLevel)
318
+ arguments = arguments.map {f => f.Field(value = self.resolveTerm(f.value, topLevel))}
319
+ )
320
+ | EField e, _ =>
321
+ e.EField(record = self.resolveTerm(e.record, topLevel))
322
+ | ELambda(at, Lambda(lambdaAt, _, cases)), _ =>
323
+ let effect = self.makeEffectArgument(lambdaAt, topLevel)
324
+ ELambda(at, Lambda(lambdaAt, effect, cases.map {self.resolveCase(_, topLevel)}))
325
+ | EPipe(at, value, effect, function), _ =>
326
+ EPipe(
327
+ at = at
328
+ value = self.resolveTerm(value, topLevel)
329
+ effect = self.resolveType(effect, topLevel)
330
+ function = self.resolveTerm(function, topLevel)
331
+ )
332
+ | ECall(at, DynamicCall target, effect, typeArguments, arguments, dictionaries), _ =>
333
+ ECall(
334
+ at = at
335
+ target = target.DynamicCall(function = self.resolveTerm(target.function, topLevel))
336
+ effect = self.resolveType(effect, topLevel)
337
+ typeArguments = typeArguments.map {self.resolveType(_, topLevel)}
338
+ arguments = arguments.map {a => a.Argument(value = self.resolveTerm(a.value, topLevel))}
339
+ dictionaries = dictionaries
340
+ )
341
+ | ECall(at, StaticCall _, _, _, _, _), _ =>
342
+ throw(CompileError(at, "Internal error: Static calls not expected in the Resolver phase"))
343
+ | ERecord(at, fields), _ =>
344
+ ERecord(
345
+ at = at
346
+ fields = fields.map {f => f.Field(value = self.resolveTerm(f.value, topLevel))}
347
+ )
348
+ | EWildcard e, _ =>
349
+ if(e.index == 0) {throw(CompileError(e.at, "Unbound wildcard"))}
350
+ e.EWildcard()
351
+ | EFunctions(at, functions, body), _ =>
352
+ let functionMap = functions.map {_.signature.name}.map {name => Pair(name, name)}.toMap()
353
+ let locationMap = functions.map {_.signature}.map {s => Pair(s.name, s.at)}.toMap()
354
+ let self2 = self.Resolver(
355
+ variables = self.variables.addAll(functionMap)
356
+ variableLocations = self.variableLocations.addAll(locationMap)
357
+ )
358
+ EFunctions(
359
+ at = at
360
+ functions = functions.map {self2.resolveFunctionDefinition(_, topLevel, False)}
361
+ body = self2.resolveTerm(body, topLevel)
362
+ )
363
+ | ELet e, _ =>
364
+ let self2 = self.Resolver(
365
+ variables = self.variables.add(e.name, e.name)
366
+ variableLocations = self.variableLocations.add(e.name, e.at)
367
+ )
368
+ if(self.lspHook.isEnabled()) {
369
+ if(self.lspHook.isAt(e.at) || self.lspHook.isDefinedAt(e.at)) {
370
+ self.lspHook.emit(
371
+ ResolveSymbolHook(
372
+ SymbolHook(e.name, e.at, e.at), None
373
+ )
374
+ )
375
+ }
376
+ }
377
+ e.ELet(
378
+ valueType = self.resolveType(e.valueType, topLevel)
379
+ value = self.resolveTerm(e.value, topLevel)
380
+ body = self2.resolveTerm(e.body, topLevel)
381
+ )
382
+ | ESequential(at, before, after), _ =>
383
+ ESequential(
384
+ at = at
385
+ before = self.resolveTerm(before, topLevel)
386
+ after = self.resolveTerm(after, topLevel)
387
+ )
388
+ | EAssign(at, operator, variable, value), _ =>
389
+ EAssign(
390
+ at = at
391
+ operator = operator
392
+ variable = self.variables.get(variable).else {
393
+ throw(CompileError(at, "No such variable: " + variable))
394
+ }
395
+ value = self.resolveTerm(value, topLevel)
396
+ )
397
+ | EAssignField(at, operator, record, field, value), _ =>
398
+ EAssignField(
399
+ at = at
400
+ operator = operator
401
+ record = self.resolveTerm(record, topLevel)
402
+ field = field
403
+ value = self.resolveTerm(value, topLevel)
404
+ )
405
+ }
406
+
407
+ resolveType(type: Type, topLevel: Bool): Type {
408
+ | TVariable _, _ =>
409
+ type
410
+ | TConstructor constructor, _ =>
411
+ if(self.lspHook.isEnabled()) {
412
+ let at = self.typeLocations.get(constructor.name).else {type.at}
413
+ if(self.lspHook.isAt(type.at) || self.lspHook.isDefinedAt(at)) {
414
+ self.lspHook.emit(
415
+ ResolveTypeHook(
416
+ self.types, self.typeGenerics
417
+ SymbolHook(constructor.name, type.at, at), type
418
+ )
419
+ )
420
+ }
421
+ }
422
+ let name = if(constructor.name.contains("$")) {
423
+ constructor.name
424
+ } else {
425
+ self.types.get(constructor.name).else {
426
+ if(!self.lspHook.isEnabled()) {
427
+ throw(CompileError(constructor.at, "No such type: " + constructor.name))
428
+ } else {
429
+ constructor.name
430
+ }
431
+ }
432
+ }
433
+ let isFunctionType = name.startsWith("Function$")
434
+ let effect = if(isFunctionType || self.asyncTypes.contains(constructor.name)) {
435
+ [self.makeEffectArgument(constructor.at, topLevel)]
436
+ } else {[]}
437
+ let generics = constructor.generics.map {self.resolveType(_, topLevel)}
438
+ if(isFunctionType) {
439
+ let arguments = generics.dropLast()
440
+ let returnType = generics.grabLast()
441
+ constructor.TConstructor(
442
+ name = name
443
+ generics = [...effect, ...arguments, returnType]
444
+ )
445
+ } else {
446
+ constructor.TConstructor(
447
+ name = name
448
+ generics = [...effect, ...generics]
449
+ )
450
+ }
451
+ }
452
+
453
+ makeEffectArgument(at: Location, topLevel: Bool): Type {
454
+ if(topLevel) {
455
+ if(!self.typeParameters.contains("Q$")) {
456
+ TConstructor(at, "ff:core/Nothing.Nothing", []) // Temporary workaround for top-level let
457
+ } else {
458
+ TConstructor(at, "Q$", [])
459
+ }
460
+ } else {
461
+ self.freshUnificationVariable(at)
462
+ }
463
+ }
464
+
465
+ resolveConstraint(constraint: Constraint, topLevel: Bool): Constraint {
466
+ let traitDefinedAt = self.traitLocations.get(constraint.name).else {constraint.at}
467
+ if(self.lspHook.isAt(constraint.at) || self.lspHook.isDefinedAt(traitDefinedAt)) {
468
+ self.lspHook.emit(
469
+ ResolveConstraintHook(SymbolHook(constraint.name, constraint.at, traitDefinedAt), constraint)
470
+ )
471
+ }
472
+ let name =
473
+ self.traits.get(constraint.name).else {
474
+ throw(CompileError(constraint.at, "No such trait: " + constraint.name))
475
+ }
476
+ constraint.Constraint(
477
+ name = name
478
+ generics = constraint.generics.map {self.resolveType(_, topLevel)}
479
+ )
480
+ }
481
+
482
+ resolveFunctionDefinition(definition: DFunction, topLevel: Bool, isInstanceMethod: Bool): DFunction {
483
+ let signature = self.resolveSignature(definition.signature, topLevel, isInstanceMethod)
484
+ let self2 = self.withSignature(signature)
485
+ let body = definition.body.mapFirefly {lambda => lambda.Lambda(
486
+ effect = signature.effect
487
+ cases = lambda.cases.map {self2.resolveCase(_, False)}
488
+ )}
489
+ DFunction(definition.at, signature, body)
490
+ }
491
+
492
+ resolveSignature(signature: Signature, topLevel: Bool, isInstanceMethod: Bool): Signature {
493
+ if(self.lspHook.isAt(signature.at) || self.lspHook.isDefinedAt(signature.at)) {
494
+ self.lspHook.emit(
495
+ ResolveSignatureHook(signature, isInstanceMethod)
496
+ )
497
+ }
498
+ let newSignature = if(topLevel) {
499
+ signature.Signature(
500
+ generics = ["Q$", ...signature.generics]
501
+ effect = TConstructor(signature.at, "Q$", [])
502
+ )
503
+ } else {
504
+ signature.Signature(
505
+ effect = self.freshUnificationVariable(signature.at)
506
+ )
507
+ }
508
+ newSignature.generics.find {name => self.typeParameters.contains(name)}.each {name =>
509
+ throw(CompileError(signature.at, "Type parameter " + name + " is already in scope"))
510
+ }
511
+ let self2 = self.withSignature(newSignature)
512
+ newSignature.Signature(
513
+ constraints = newSignature.constraints.map {self2.resolveConstraint(_, topLevel)}
514
+ parameters = newSignature.parameters.map {p =>
515
+ p.Parameter(
516
+ valueType = self2.resolveType(p.valueType, topLevel)
517
+ default = p.default.map {self2.resolveTerm(_, topLevel)}
518
+ )
519
+ }
520
+ returnType = self2.resolveType(newSignature.returnType, topLevel)
521
+ )
522
+ }
523
+
524
+ withSignature(signature: Signature): Resolver {
525
+ let variableMap = signature.parameters.map {_.name}.map {name => Pair(name, name)}.toMap()
526
+ let variableLocationMap = signature.parameters.map {p => Pair(p.name, p.at)}.toMap()
527
+ let typeMap = signature.generics.map {name => Pair(name, name)}.toMap()
528
+ self.Resolver(
529
+ variables = self.variables.addAll(variableMap)
530
+ variableLocations = self.variableLocations.addAll(variableLocationMap)
531
+ typeParameters = self.typeParameters.addAll(signature.generics.toSet())
532
+ types = self.types.addAll(typeMap)
533
+ asyncTypes = self.asyncTypes.removeAll(signature.generics.toSet())
534
+ )
535
+ }
536
+
537
+ resolveCase(case: MatchCase, topLevel: Bool): MatchCase {
538
+ function findVariables(pattern: MatchPattern): Map[String, Pair[Location, String]] {
539
+ | PString _ =>
540
+ Map.empty()
541
+ | PInt _ =>
542
+ Map.empty()
543
+ | PChar _ =>
544
+ Map.empty()
545
+ | PVariable(at, Some(name)) =>
546
+ [Pair(name, Pair(at, name))].toMap()
547
+ | PVariable(_, None) =>
548
+ Map.empty()
549
+ | PVariant(_, _, patterns) =>
550
+ patterns.map(findVariables).foldLeft(Map.empty()) {_.addAll(_)}
551
+ | PVariantAs(at, _, variableAt, variable) =>
552
+ variable.toList().map {x => Pair(x, Pair(variableAt, x))}.toMap()
553
+ | PAlias(at, pattern, variable) =>
554
+ [Pair(variable, Pair(at, variable))].toMap().addAll(findVariables(pattern))
555
+ }
556
+ let variableMap = case.patterns.map(findVariables).foldLeft(Map.empty()) {_.addAll(_)}
557
+ mutable guards = []
558
+ let variableMap2 = case.guards.foldLeft(variableMap) {variableMap1, g =>
559
+ let self2 = self.Resolver(
560
+ variables = self.variables.addAll(variableMap1.mapValues {_, p => p.second})
561
+ variableLocations = self.variableLocations.addAll(variableMap1.mapValues {_, p => p.first})
562
+ )
563
+ let guard = g.MatchGuard(
564
+ term = self2.resolveTerm(g.term, topLevel)
565
+ pattern = self2.resolvePattern(g.pattern)
566
+ )
567
+ guards = [guard, ...guards]
568
+ variableMap1.addAll(findVariables(guard.pattern))
569
+ }
570
+ let self3 = self.Resolver(
571
+ variables = self.variables.addAll(variableMap2.mapValues {_, p => p.second})
572
+ variableLocations = self.variableLocations.addAll(variableMap2.mapValues {_, p => p.first})
573
+ )
574
+ MatchCase(
575
+ at = case.at
576
+ patterns = case.patterns.map {self.resolvePattern(_)}
577
+ guards = guards.reverse()
578
+ body = self3.resolveTerm(case.body, topLevel)
579
+ )
580
+ }
581
+
582
+ resolvePattern(pattern: MatchPattern): MatchPattern {
583
+ | PString _ =>
584
+ pattern
585
+ | PInt _ =>
586
+ pattern
587
+ | PChar _ =>
588
+ pattern
589
+ | PVariable _ =>
590
+ pattern
591
+ | PVariant(at, name, patterns) =>
592
+ let newName = self.variants.get(name).else {name}
593
+ let newPatterns = patterns.map {self.resolvePattern(_)}
594
+ PVariant(at, newName, newPatterns)
595
+ | PVariantAs(at, name, variableAt, variable) =>
596
+ let newName = self.variants.get(name).else {name}
597
+ PVariantAs(at, newName, variableAt, variable)
598
+ | PAlias(at, pattern, variable) =>
599
+ let newPattern = self.resolvePattern(pattern)
600
+ PAlias(at, newPattern, variable)
601
+ }
602
+
603
+ containsAsyncType(type: Type): Bool {
604
+ | TVariable _ =>
605
+ False
606
+ | TConstructor constructor =>
607
+ let name = if(constructor.name.contains("$")) {
608
+ constructor.name
609
+ } else {
610
+ self.types.get(constructor.name).else {
611
+ if(self.lspHook.isEnabled()) {constructor.name} else:
612
+ throw(CompileError(constructor.at, "No such type: " + constructor.name))
613
+ }
614
+ }
615
+ let isFunctionType = name.startsWith("Function$")
616
+ isFunctionType || self.asyncTypes.contains(constructor.name) ||
617
+ constructor.generics.any {self.containsAsyncType(_)}
618
+ }
619
+
620
+ }