firefly-compiler 0.4.20 → 0.4.22
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.
- package/compiler/Builder.ff +23 -13
- package/compiler/Dictionaries.ff +10 -10
- package/compiler/Inference.ff +167 -148
- package/compiler/JsEmitter.ff +122 -78
- package/compiler/LspHook.ff +6 -3
- package/compiler/Main.ff +24 -10
- package/compiler/Patterns.ff +1 -1
- package/compiler/Resolver.ff +167 -159
- package/compiler/Substitution.ff +2 -2
- package/compiler/Syntax.ff +1 -0
- package/compiler/Unification.ff +1 -1
- package/core/Array.ff +6 -4
- package/core/Int.ff +12 -12
- package/core/List.ff +6 -4
- package/core/Map.ff +8 -0
- package/core/Set.ff +7 -0
- package/experimental/benchmarks/ListGrab.ff +23 -0
- package/experimental/benchmarks/ListGrab.java +55 -0
- package/experimental/benchmarks/Pyrotek45.ff +30 -0
- package/experimental/benchmarks/Pyrotek45.java +64 -0
- package/experimental/tests/TestJson.ff +26 -0
- package/lsp/Handler.ff +65 -61
- package/lsp/SignatureHelpHandler.ff +5 -4
- package/lsp/TestReferences.ff +15 -0
- package/lsp/TestReferencesCase.ff +8 -0
- package/output/js/ff/compiler/Builder.mjs +50 -44
- package/output/js/ff/compiler/Dependencies.mjs +0 -2
- package/output/js/ff/compiler/Deriver.mjs +16 -140
- package/output/js/ff/compiler/Dictionaries.mjs +24 -238
- package/output/js/ff/compiler/Environment.mjs +12 -154
- package/output/js/ff/compiler/Inference.mjs +207 -1069
- package/output/js/ff/compiler/JsEmitter.mjs +434 -2342
- package/output/js/ff/compiler/JsImporter.mjs +0 -12
- package/output/js/ff/compiler/LspHook.mjs +20 -446
- package/output/js/ff/compiler/Main.mjs +110 -553
- package/output/js/ff/compiler/Parser.mjs +36 -356
- package/output/js/ff/compiler/Patterns.mjs +24 -204
- package/output/js/ff/compiler/Resolver.mjs +428 -554
- package/output/js/ff/compiler/Substitution.mjs +6 -164
- package/output/js/ff/compiler/Syntax.mjs +449 -3293
- package/output/js/ff/compiler/Token.mjs +9 -1095
- package/output/js/ff/compiler/Tokenizer.mjs +4 -2
- package/output/js/ff/compiler/Unification.mjs +30 -364
- package/output/js/ff/compiler/Wildcards.mjs +0 -86
- package/output/js/ff/compiler/Workspace.mjs +8 -96
- package/output/js/ff/core/Array.mjs +15 -8
- package/output/js/ff/core/AssetSystem.mjs +4 -14
- package/output/js/ff/core/Bool.mjs +0 -12
- package/output/js/ff/core/Core.mjs +0 -30
- package/output/js/ff/core/Int.mjs +24 -24
- package/output/js/ff/core/IntMap.mjs +0 -8
- package/output/js/ff/core/Json.mjs +0 -40
- package/output/js/ff/core/List.mjs +23 -32
- package/output/js/ff/core/Lock.mjs +0 -10
- package/output/js/ff/core/Map.mjs +26 -24
- package/output/js/ff/core/Option.mjs +10 -286
- package/output/js/ff/core/Ordering.mjs +16 -158
- package/output/js/ff/core/Pair.mjs +2 -34
- package/output/js/ff/core/Path.mjs +2 -28
- package/output/js/ff/core/Random.mjs +4 -4
- package/output/js/ff/core/RbMap.mjs +56 -644
- package/output/js/ff/core/Set.mjs +16 -0
- package/output/js/ff/core/Show.mjs +0 -16
- package/output/js/ff/core/Stream.mjs +14 -144
- package/output/js/ff/core/StringMap.mjs +0 -8
- package/output/js/ff/core/Try.mjs +4 -108
- package/output/js/ff/core/Unit.mjs +2 -16
- package/package.json +1 -1
- package/postgresql/Pg.ff +23 -23
- package/vscode/package.json +1 -1
- package/bin/firefly.mjs +0 -2
- package/guide/Main.ff +0 -22
package/compiler/Resolver.ff
CHANGED
|
@@ -20,6 +20,12 @@ class ResolverState(
|
|
|
20
20
|
mutable nextUnificationVariableIndex: Int
|
|
21
21
|
)
|
|
22
22
|
|
|
23
|
+
data CaseVariable(
|
|
24
|
+
at: Location
|
|
25
|
+
name: String
|
|
26
|
+
asBound: Option[String]
|
|
27
|
+
)
|
|
28
|
+
|
|
23
29
|
make(packagePair: PackagePair, moduleName: String, lspHook: LspHook): Resolver {
|
|
24
30
|
Resolver(
|
|
25
31
|
variables = [].toMap()
|
|
@@ -49,16 +55,16 @@ extend self: Resolver {
|
|
|
49
55
|
|
|
50
56
|
resolveModule(module: Module, otherModules: List[Module]): Module {
|
|
51
57
|
let moduleNamespace =
|
|
52
|
-
module.file.replace("\\", "/").reverse().takeWhile {
|
|
58
|
+
module.file.replace("\\", "/").reverse().takeWhile {_ != '/'}.reverse().takeWhile {_ != '.'}
|
|
53
59
|
let self2 = self.processImports(module.imports, otherModules)
|
|
54
60
|
let self3 = self2.processDefinitions(module, None)
|
|
55
61
|
let module2 = module.Module(
|
|
56
|
-
types = module.types.map {
|
|
57
|
-
traits = module.traits.map {
|
|
58
|
-
instances = module.instances.map {
|
|
59
|
-
extends = module.extends.map {
|
|
60
|
-
lets = module.lets.map {
|
|
61
|
-
functions = module.functions.map {
|
|
62
|
+
types = module.types.map {self3.resolveTypeDefinition(_)}
|
|
63
|
+
traits = module.traits.map {self3.resolveTraitDefinition(_)}
|
|
64
|
+
instances = module.instances.map {self3.resolveInstanceDefinition(_)}
|
|
65
|
+
extends = module.extends.map {self3.resolveExtendDefinition(_)}
|
|
66
|
+
lets = module.lets.map {self3.resolveLetDefinition(_, True)}
|
|
67
|
+
functions = module.functions.map {self3.resolveFunctionDefinition(_, True, False)}
|
|
62
68
|
)
|
|
63
69
|
module2.instances.each {_.typeArguments.each {self3.checkInstanceType(_)}}
|
|
64
70
|
module2
|
|
@@ -77,8 +83,8 @@ extend self: Resolver {
|
|
|
77
83
|
|
|
78
84
|
processImports(imports: List[DImport], modules: List[Module]): Resolver {
|
|
79
85
|
mutable resolver = self
|
|
80
|
-
imports.each {
|
|
81
|
-
modules.find {
|
|
86
|
+
imports.each {import =>
|
|
87
|
+
modules.find {_.file.dropLast(3) == import.file}.{
|
|
82
88
|
| Some(module) =>
|
|
83
89
|
resolver = resolver.processDefinitions(module, Some(import.alias))
|
|
84
90
|
| None =>
|
|
@@ -95,7 +101,7 @@ extend self: Resolver {
|
|
|
95
101
|
module.file.dropLast(3) + "." + name
|
|
96
102
|
importAlias.{
|
|
97
103
|
| None => [Pair(name, full), Pair(full, full)]
|
|
98
|
-
| Some(alias) {
|
|
104
|
+
| Some(alias) {unqualified} => [Pair(alias + "." + name, full), Pair(name, full), Pair(full, full)]
|
|
99
105
|
| Some(alias) => [Pair(alias + "." + name, full), Pair(full, full)]
|
|
100
106
|
}
|
|
101
107
|
}
|
|
@@ -103,20 +109,20 @@ extend self: Resolver {
|
|
|
103
109
|
module.packagePair.group == "ff" &&
|
|
104
110
|
module.packagePair.name == "core" &&
|
|
105
111
|
module.file == "Core.ff"
|
|
106
|
-
let lets = module.lets.flatMap {
|
|
107
|
-
let letLocations = module.lets.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}}
|
|
108
|
-
let functions = module.functions.flatMap {
|
|
112
|
+
let lets = module.lets.flatMap {entry(_.name, isCore)}.toMap()
|
|
113
|
+
let letLocations = module.lets.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}}}.toMap()
|
|
114
|
+
let functions = module.functions.flatMap {entry(_.signature.name, isCore)}.toMap()
|
|
109
115
|
let functionLocations = module.functions.flatMap {d => entry(d.signature.name, True).map {_.mapSecond {_ => d.at}} }.toMap()
|
|
110
|
-
let traitMethods = module.traits.flatMap {
|
|
111
|
-
let traitMethodLocations = module.traits.flatMap {_.methods}.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}}
|
|
112
|
-
let traits = module.traits.flatMap {
|
|
113
|
-
let traitLocations = module.traits.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}}
|
|
114
|
-
let types = module.types.flatMap {
|
|
116
|
+
let traitMethods = module.traits.flatMap {_.methods }.flatMap {entry(_.name, False)}.toMap()
|
|
117
|
+
let traitMethodLocations = module.traits.flatMap {_.methods}.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}}}.toMap()
|
|
118
|
+
let traits = module.traits.flatMap {entry(_.name, True) }.toMap()
|
|
119
|
+
let traitLocations = module.traits.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}}}.toMap()
|
|
120
|
+
let types = module.types.flatMap {entry(_.name, True) }.toMap()
|
|
115
121
|
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}}
|
|
117
|
-
let asyncTypes = module.types.filter {
|
|
118
|
-
.flatMap {
|
|
119
|
-
let variants = module.types.flatMap {
|
|
122
|
+
let typeLocations = module.types.flatMap {d => entry(d.name, True).map {_.mapSecond {_ => d.at}}}.toMap()
|
|
123
|
+
let asyncTypes = module.types.filter {_.generics.first().any {_ == "Q$"}}
|
|
124
|
+
.flatMap {entry(_.name, True).map {_.first}}.toSet()
|
|
125
|
+
let variants = module.types.flatMap {_.variants }.flatMap {entry(_.name, True)}.toMap()
|
|
120
126
|
self.Resolver(
|
|
121
127
|
variables = self.variables.addAll(lets).addAll(functions).addAll(traitMethods)
|
|
122
128
|
variableLocations = self.variableLocations.addAll(letLocations).addAll(functionLocations).addAll(traitMethodLocations)
|
|
@@ -135,7 +141,7 @@ extend self: Resolver {
|
|
|
135
141
|
resolveTypeDefinition(definition: DType): DType {
|
|
136
142
|
if(self.lspHook.isAt(definition.at)) {
|
|
137
143
|
self.lspHook.emit(
|
|
138
|
-
ResolveSymbolHook(SymbolHook(definition.name, definition.at, definition.at), None)
|
|
144
|
+
ResolveSymbolHook(SymbolHook(definition.name, definition.at, definition.at), None, topLevel = True)
|
|
139
145
|
)
|
|
140
146
|
}
|
|
141
147
|
let generics = definition.generics.map {g => Pair(g, g)}.toMap()
|
|
@@ -168,7 +174,7 @@ extend self: Resolver {
|
|
|
168
174
|
variants = definition.variants.map {v =>
|
|
169
175
|
if(self.lspHook.isAt(v.at)) {
|
|
170
176
|
self.lspHook.emit(
|
|
171
|
-
ResolveSymbolHook(SymbolHook(v.name, v.at, v.at), None)
|
|
177
|
+
ResolveSymbolHook(SymbolHook(v.name, v.at, v.at), None, topLevel = True)
|
|
172
178
|
)
|
|
173
179
|
}
|
|
174
180
|
v.Variant(fields = v.fields.map {f =>
|
|
@@ -191,7 +197,7 @@ extend self: Resolver {
|
|
|
191
197
|
if(self.lspHook.isAt(definition.at) || self.lspHook.isDefinedAt(definition.at)) {
|
|
192
198
|
self.lspHook.emit(
|
|
193
199
|
ResolveSymbolHook(
|
|
194
|
-
SymbolHook(definition.name, definition.at, definition.at), None
|
|
200
|
+
SymbolHook(definition.name, definition.at, definition.at), None, topLevel = True
|
|
195
201
|
)
|
|
196
202
|
)
|
|
197
203
|
}
|
|
@@ -221,7 +227,7 @@ extend self: Resolver {
|
|
|
221
227
|
if(self.lspHook.isAt(definition.at) || self.lspHook.isDefinedAt(traitDefinedAt)) {
|
|
222
228
|
self.lspHook.emit(
|
|
223
229
|
ResolveSymbolHook(
|
|
224
|
-
SymbolHook(definition.traitName, definition.at, traitDefinedAt), None
|
|
230
|
+
SymbolHook(definition.traitName, definition.at, traitDefinedAt), None, topLevel = True
|
|
225
231
|
)
|
|
226
232
|
)
|
|
227
233
|
}
|
|
@@ -266,7 +272,7 @@ extend self: Resolver {
|
|
|
266
272
|
if(self.lspHook.isAt(definition.at) || self.lspHook.isDefinedAt(definition.at)) {
|
|
267
273
|
self.lspHook.emit(
|
|
268
274
|
ResolveSymbolHook(
|
|
269
|
-
SymbolHook(definition.name, definition.at, definition.at), None
|
|
275
|
+
SymbolHook(definition.name, definition.at, definition.at), None, topLevel = topLevel
|
|
270
276
|
)
|
|
271
277
|
)
|
|
272
278
|
}
|
|
@@ -276,132 +282,134 @@ extend self: Resolver {
|
|
|
276
282
|
)
|
|
277
283
|
}
|
|
278
284
|
|
|
279
|
-
resolveTerm(term: Term, topLevel: Bool): Term {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
self.lspHook.
|
|
289
|
-
|
|
290
|
-
|
|
285
|
+
resolveTerm(term: Term, topLevel: Bool, inField: Bool = False): Term {
|
|
286
|
+
term.{
|
|
287
|
+
| EString _ => term
|
|
288
|
+
| EChar _ => term
|
|
289
|
+
| EInt _ => term
|
|
290
|
+
| EFloat _ => term
|
|
291
|
+
| EVariable e =>
|
|
292
|
+
if(self.lspHook.isEnabled()) {
|
|
293
|
+
let at = self.variableLocations.get(e.name).else {e.at}
|
|
294
|
+
if(self.lspHook.isAt(e.at) || self.lspHook.isDefinedAt(at)) {
|
|
295
|
+
self.lspHook.emit(
|
|
296
|
+
ResolveSymbolHook(
|
|
297
|
+
SymbolHook(e.name, e.at, at), None, topLevel = True
|
|
298
|
+
)
|
|
291
299
|
)
|
|
292
|
-
|
|
300
|
+
}
|
|
293
301
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
)
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
302
|
+
self.variables.get(e.name).map {e.EVariable(name = _)}.else {term}
|
|
303
|
+
| EList(at, t, items) =>
|
|
304
|
+
EList(at, self.resolveType(t, topLevel), items.map {| Pair(item, spread) =>
|
|
305
|
+
Pair(self.resolveTerm(item, topLevel), spread)
|
|
306
|
+
})
|
|
307
|
+
| EVariant(at, name, typeArguments, arguments) =>
|
|
308
|
+
EVariant(
|
|
309
|
+
at = at
|
|
310
|
+
name = self.variants.get(name).else {name}
|
|
311
|
+
typeArguments = typeArguments.map {self.resolveType(_, topLevel)}
|
|
312
|
+
arguments = arguments.map {_.map {a => a.Argument(value = self.resolveTerm(a.value, topLevel))}}
|
|
313
|
+
)
|
|
314
|
+
| EVariantIs(at, name, typeArguments) =>
|
|
315
|
+
EVariantIs(
|
|
316
|
+
at = at
|
|
317
|
+
name = self.variants.get(name).else {throw(CompileError(at, "No such variant: " + name))}
|
|
318
|
+
typeArguments = typeArguments.map {self.resolveType(_, topLevel)}
|
|
319
|
+
)
|
|
320
|
+
| ECopy(at, name, record, arguments) =>
|
|
321
|
+
ECopy(
|
|
322
|
+
at = at
|
|
323
|
+
name = self.variants.get(name).else {name}
|
|
324
|
+
record = self.resolveTerm(record, topLevel, inField = True)
|
|
325
|
+
arguments = arguments.map {f => f.Field(value = self.resolveTerm(f.value, topLevel))}
|
|
326
|
+
)
|
|
327
|
+
| EField e =>
|
|
328
|
+
e.EField(record = self.resolveTerm(e.record, topLevel, inField = True))
|
|
329
|
+
| ELambda(at, Lambda(lambdaAt, _, cases)) =>
|
|
330
|
+
let effect = self.makeEffectArgument(lambdaAt, topLevel)
|
|
331
|
+
ELambda(at, Lambda(lambdaAt, effect, cases.map {self.resolveCase(_, topLevel)}))
|
|
332
|
+
| EPipe(at, value, effect, function) =>
|
|
333
|
+
EPipe(
|
|
334
|
+
at = at
|
|
335
|
+
value = self.resolveTerm(value, topLevel)
|
|
336
|
+
effect = self.resolveType(effect, topLevel)
|
|
337
|
+
function = self.resolveTerm(function, topLevel)
|
|
338
|
+
)
|
|
339
|
+
| ECall(at, DynamicCall target, effect, typeArguments, arguments, dictionaries) =>
|
|
340
|
+
ECall(
|
|
341
|
+
at = at
|
|
342
|
+
target = target.DynamicCall(function = self.resolveTerm(target.function, topLevel))
|
|
343
|
+
effect = self.resolveType(effect, topLevel)
|
|
344
|
+
typeArguments = typeArguments.map {self.resolveType(_, topLevel)}
|
|
345
|
+
arguments = arguments.map {a => a.Argument(value = self.resolveTerm(a.value, topLevel))}
|
|
346
|
+
dictionaries = dictionaries
|
|
347
|
+
)
|
|
348
|
+
| ECall(at, StaticCall _, _, _, _, _) =>
|
|
349
|
+
throw(CompileError(at, "Internal error: Static calls not expected in the Resolver phase"))
|
|
350
|
+
| ERecord(at, fields) =>
|
|
351
|
+
ERecord(
|
|
352
|
+
at = at
|
|
353
|
+
fields = fields.map {f => f.Field(value = self.resolveTerm(f.value, topLevel))}
|
|
354
|
+
)
|
|
355
|
+
| EWildcard e =>
|
|
356
|
+
if(e.index == 0) {throw(CompileError(e.at, "Unbound wildcard"))}
|
|
357
|
+
e.EWildcard()
|
|
358
|
+
| EFunctions(at, functions, body) =>
|
|
359
|
+
let functionMap = functions.map {_.signature.name}.map {name => Pair(name, name)}.toMap()
|
|
360
|
+
let locationMap = functions.map {_.signature}.map {s => Pair(s.name, s.at)}.toMap()
|
|
361
|
+
let self2 = self.Resolver(
|
|
362
|
+
variables = self.variables.addAll(functionMap)
|
|
363
|
+
variableLocations = self.variableLocations.addAll(locationMap)
|
|
364
|
+
)
|
|
365
|
+
EFunctions(
|
|
366
|
+
at = at
|
|
367
|
+
functions = functions.map {self2.resolveFunctionDefinition(_, topLevel, False)}
|
|
368
|
+
body = self2.resolveTerm(body, topLevel)
|
|
369
|
+
)
|
|
370
|
+
| ELet e =>
|
|
371
|
+
let self2 = self.Resolver(
|
|
372
|
+
variables = self.variables.add(e.name, e.name)
|
|
373
|
+
variableLocations = self.variableLocations.add(e.name, e.at)
|
|
374
|
+
)
|
|
375
|
+
if(self.lspHook.isEnabled()) {
|
|
376
|
+
if(self.lspHook.isAt(e.at) || self.lspHook.isDefinedAt(e.at)) {
|
|
377
|
+
self.lspHook.emit(
|
|
378
|
+
ResolveSymbolHook(
|
|
379
|
+
SymbolHook(e.name, e.at, e.at), None, topLevel = False
|
|
380
|
+
)
|
|
373
381
|
)
|
|
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))
|
|
382
|
+
}
|
|
394
383
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
384
|
+
e.ELet(
|
|
385
|
+
valueType = self.resolveType(e.valueType, topLevel)
|
|
386
|
+
value = self.resolveTerm(e.value, topLevel)
|
|
387
|
+
body = self2.resolveTerm(e.body, topLevel)
|
|
388
|
+
)
|
|
389
|
+
| ESequential(at, before, after) =>
|
|
390
|
+
ESequential(
|
|
391
|
+
at = at
|
|
392
|
+
before = self.resolveTerm(before, topLevel)
|
|
393
|
+
after = self.resolveTerm(after, topLevel)
|
|
394
|
+
)
|
|
395
|
+
| EAssign(at, operator, variable, value) =>
|
|
396
|
+
EAssign(
|
|
397
|
+
at = at
|
|
398
|
+
operator = operator
|
|
399
|
+
variable = self.variables.get(variable).else {
|
|
400
|
+
throw(CompileError(at, "No such variable: " + variable))
|
|
401
|
+
}
|
|
402
|
+
value = self.resolveTerm(value, topLevel)
|
|
403
|
+
)
|
|
404
|
+
| EAssignField(at, operator, record, field, value) =>
|
|
405
|
+
EAssignField(
|
|
406
|
+
at = at
|
|
407
|
+
operator = operator
|
|
408
|
+
record = self.resolveTerm(record, topLevel)
|
|
409
|
+
field = field
|
|
410
|
+
value = self.resolveTerm(value, topLevel)
|
|
411
|
+
)
|
|
412
|
+
}
|
|
405
413
|
}
|
|
406
414
|
|
|
407
415
|
resolveType(type: Type, topLevel: Bool): Type {
|
|
@@ -492,7 +500,7 @@ extend self: Resolver {
|
|
|
492
500
|
resolveSignature(signature: Signature, topLevel: Bool, isInstanceMethod: Bool): Signature {
|
|
493
501
|
if(self.lspHook.isAt(signature.at) || self.lspHook.isDefinedAt(signature.at)) {
|
|
494
502
|
self.lspHook.emit(
|
|
495
|
-
ResolveSignatureHook(signature, isInstanceMethod)
|
|
503
|
+
ResolveSignatureHook(signature, isInstanceMethod, topLevel = topLevel)
|
|
496
504
|
)
|
|
497
505
|
}
|
|
498
506
|
let newSignature = if(topLevel) {
|
|
@@ -535,7 +543,7 @@ extend self: Resolver {
|
|
|
535
543
|
}
|
|
536
544
|
|
|
537
545
|
resolveCase(case: MatchCase, topLevel: Bool): MatchCase {
|
|
538
|
-
function findVariables(pattern: MatchPattern): Map[String,
|
|
546
|
+
function findVariables(pattern: MatchPattern): Map[String, CaseVariable] {
|
|
539
547
|
| PString _ =>
|
|
540
548
|
Map.empty()
|
|
541
549
|
| PInt _ =>
|
|
@@ -543,22 +551,22 @@ extend self: Resolver {
|
|
|
543
551
|
| PChar _ =>
|
|
544
552
|
Map.empty()
|
|
545
553
|
| PVariable(at, Some(name)) =>
|
|
546
|
-
[Pair(name,
|
|
554
|
+
[Pair(name, CaseVariable(at, name, None))].toMap()
|
|
547
555
|
| PVariable(_, None) =>
|
|
548
556
|
Map.empty()
|
|
549
557
|
| PVariant(_, _, patterns) =>
|
|
550
558
|
patterns.map(findVariables).foldLeft(Map.empty()) {_.addAll(_)}
|
|
551
|
-
| PVariantAs(at,
|
|
552
|
-
variable.toList().map {x => Pair(x,
|
|
559
|
+
| PVariantAs(at, variant, variableAt, variable) =>
|
|
560
|
+
variable.toList().map {x => Pair(x, CaseVariable(variableAt, x, Some(variant)))}.toMap()
|
|
553
561
|
| PAlias(at, pattern, variable) =>
|
|
554
|
-
[Pair(variable,
|
|
562
|
+
[Pair(variable, CaseVariable(at, variable, None))].toMap().addAll(findVariables(pattern))
|
|
555
563
|
}
|
|
556
564
|
let variableMap = case.patterns.map(findVariables).foldLeft(Map.empty()) {_.addAll(_)}
|
|
557
565
|
mutable guards = []
|
|
558
566
|
let variableMap2 = case.guards.foldLeft(variableMap) {variableMap1, g =>
|
|
559
567
|
let self2 = self.Resolver(
|
|
560
|
-
variables = self.variables.addAll(variableMap1.mapValues {_, p => p.
|
|
561
|
-
variableLocations = self.variableLocations.addAll(variableMap1.mapValues {_, p => p.
|
|
568
|
+
variables = self.variables.addAll(variableMap1.mapValues {_, p => p.name})
|
|
569
|
+
variableLocations = self.variableLocations.addAll(variableMap1.mapValues {_, p => p.at})
|
|
562
570
|
)
|
|
563
571
|
let guard = g.MatchGuard(
|
|
564
572
|
term = self2.resolveTerm(g.term, topLevel)
|
|
@@ -568,8 +576,8 @@ extend self: Resolver {
|
|
|
568
576
|
variableMap1.addAll(findVariables(guard.pattern))
|
|
569
577
|
}
|
|
570
578
|
let self3 = self.Resolver(
|
|
571
|
-
variables = self.variables.addAll(variableMap2.mapValues {_, p => p.
|
|
572
|
-
variableLocations = self.variableLocations.addAll(variableMap2.mapValues {_, p => p.
|
|
579
|
+
variables = self.variables.addAll(variableMap2.mapValues {_, p => p.name})
|
|
580
|
+
variableLocations = self.variableLocations.addAll(variableMap2.mapValues {_, p => p.at})
|
|
573
581
|
)
|
|
574
582
|
MatchCase(
|
|
575
583
|
at = case.at
|
package/compiler/Substitution.ff
CHANGED
|
@@ -154,9 +154,9 @@ extend self: Substitution {
|
|
|
154
154
|
|
|
155
155
|
substituteType(type: Type): Type {
|
|
156
156
|
| TVariable(at, i) =>
|
|
157
|
-
if(self.has(i)) {
|
|
157
|
+
if(self.has(i)) {self.substituteType(self.get(i))} else {TConstructor(at, core("Nothing"), [])}
|
|
158
158
|
| TConstructor t =>
|
|
159
|
-
t.TConstructor(generics = t.generics.map {
|
|
159
|
+
t.TConstructor(generics = t.generics.map {g => self.substituteType(g)})
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
get(index: Int): Type {
|
package/compiler/Syntax.ff
CHANGED
package/compiler/Unification.ff
CHANGED
|
@@ -152,7 +152,7 @@ extend self: Unification {
|
|
|
152
152
|
substitute(type: Type): Type {
|
|
153
153
|
| TVariable(_, i) {self.get(i) | Some(t)} => self.substitute(t)
|
|
154
154
|
| TVariable(_, _) => type
|
|
155
|
-
| TConstructor t => t.TConstructor(generics = t.generics.map {
|
|
155
|
+
| TConstructor t => t.TConstructor(generics = t.generics.map {g => self.substitute(g)})
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
unify(at: Location, t1: Type, t2: Type): Unit {
|
package/core/Array.ff
CHANGED
|
@@ -35,10 +35,7 @@ extend self[T]: Array[T] {
|
|
|
35
35
|
|
|
36
36
|
grab(index: Int): T
|
|
37
37
|
target js sync """
|
|
38
|
-
|
|
39
|
-
ff_core_Try.internalThrowGrabException_()
|
|
40
|
-
}
|
|
41
|
-
return self_.array[index_]
|
|
38
|
+
return self_.array[index_] ?? internalGrab_(self_, index_);
|
|
42
39
|
"""
|
|
43
40
|
|
|
44
41
|
grabFirst(): T {self.grab(0)}
|
|
@@ -261,3 +258,8 @@ sortRange[T](array: Array[T], compare: (T, T) => Ordering, start: Int, end: Int)
|
|
|
261
258
|
}
|
|
262
259
|
}
|
|
263
260
|
}
|
|
261
|
+
|
|
262
|
+
internalGrab[T](self: Array[T], index: Int): T
|
|
263
|
+
target js sync """
|
|
264
|
+
return index_ < 0 || index_ >= self_.array.length ? ff_core_Try.internalThrowGrabException_() : self_.array[index_];
|
|
265
|
+
"""
|
package/core/Int.ff
CHANGED
|
@@ -27,23 +27,23 @@ extend self: Int {
|
|
|
27
27
|
target js sync "return signed_ ? self_ >> bits_ : self_ >>> bits_;"
|
|
28
28
|
|
|
29
29
|
to(inclusiveEnd: Int): List[Int] {
|
|
30
|
-
|
|
31
|
-
mutable n =
|
|
32
|
-
while {
|
|
33
|
-
result
|
|
34
|
-
n
|
|
30
|
+
let result = Array.make()
|
|
31
|
+
mutable n = self
|
|
32
|
+
while {n <= inclusiveEnd} {
|
|
33
|
+
result.push(n)
|
|
34
|
+
n += 1
|
|
35
35
|
}
|
|
36
|
-
result
|
|
36
|
+
result.drain()
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
until(exclusiveEnd: Int): List[Int] {
|
|
40
|
-
|
|
41
|
-
mutable n =
|
|
42
|
-
while {
|
|
43
|
-
result
|
|
44
|
-
n
|
|
40
|
+
let result = Array.make()
|
|
41
|
+
mutable n = self
|
|
42
|
+
while {n < exclusiveEnd} {
|
|
43
|
+
result.push(n)
|
|
44
|
+
n += 1
|
|
45
45
|
}
|
|
46
|
-
result
|
|
46
|
+
result.drain()
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
min(that: Int): Int {
|
package/core/List.ff
CHANGED
|
@@ -47,10 +47,7 @@ extend self[T]: List[T] {
|
|
|
47
47
|
|
|
48
48
|
grab(index: Int): T
|
|
49
49
|
target js sync """
|
|
50
|
-
|
|
51
|
-
ff_core_Try.internalThrowGrabException_()
|
|
52
|
-
}
|
|
53
|
-
return self_[index_]
|
|
50
|
+
return self_[index_] ?? internalGrab_(self_, index_);
|
|
54
51
|
"""
|
|
55
52
|
|
|
56
53
|
first(): Option[T] {self.get(0)}
|
|
@@ -411,3 +408,8 @@ instance List[T: Order]: Order {
|
|
|
411
408
|
|
|
412
409
|
internalSame[T](left: List[T], right: List[T]): Bool
|
|
413
410
|
target js sync "return left_ === right_"
|
|
411
|
+
|
|
412
|
+
internalGrab[T](self: List[T], index: Int): T
|
|
413
|
+
target js sync """
|
|
414
|
+
return index_ < 0 || index_ >= self_.length ? ff_core_Try.internalThrowGrabException_() : self_[index_];
|
|
415
|
+
"""
|
package/core/Map.ff
CHANGED
|
@@ -18,6 +18,14 @@ extend self[K: Order, V]: Map[K, V] {
|
|
|
18
18
|
Map(result)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
addList(that: List[Pair[K, V]]): Map[K, V] {
|
|
22
|
+
mutable result = self.redBlack
|
|
23
|
+
that.each {| Pair(k, v) =>
|
|
24
|
+
result = RbMap.insert(k, v, result)
|
|
25
|
+
}
|
|
26
|
+
Map(result)
|
|
27
|
+
}
|
|
28
|
+
|
|
21
29
|
get(key: K): Option[V] {
|
|
22
30
|
self.redBlack.get(key)
|
|
23
31
|
}
|
package/core/Set.ff
CHANGED
|
@@ -7,6 +7,13 @@ empty[T](): Set[T] {
|
|
|
7
7
|
extend self[T: Order]: Set[T] {
|
|
8
8
|
add(value: T): Set[T] {Set(self.map.add(value, Unit))}
|
|
9
9
|
addAll(that: Set[T]): Set[T] {Set(self.map.addAll(that.map))}
|
|
10
|
+
addList(that: List[T]): Set[T] {
|
|
11
|
+
mutable result = self.map
|
|
12
|
+
that.each {k =>
|
|
13
|
+
result = result.add(k, Unit)
|
|
14
|
+
}
|
|
15
|
+
Set(result)
|
|
16
|
+
}
|
|
10
17
|
remove(value: T): Set[T] {Set(self.map.remove(value))}
|
|
11
18
|
removeAll(that: Set[T]): Set[T] {Set(self.map.removeAll(that.map))}
|
|
12
19
|
contains(value: T): Bool {self.map.contains(value)}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
nodeMain(system: NodeSystem) {
|
|
2
|
+
let list = 1.to(10000)
|
|
3
|
+
benchmark(list, 100000)
|
|
4
|
+
let time = system.mainTask().time {
|
|
5
|
+
benchmark(list, 100000)
|
|
6
|
+
}
|
|
7
|
+
Log.trace(time.second.show())
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
benchmark(list: List[Int], iterations: Int): Int {
|
|
11
|
+
mutable sum = 0
|
|
12
|
+
mutable i = 0
|
|
13
|
+
while {i < iterations} {
|
|
14
|
+
mutable j = 0
|
|
15
|
+
sum = 0
|
|
16
|
+
while {j < 10000} {
|
|
17
|
+
sum += list.grab(j)
|
|
18
|
+
j += 1
|
|
19
|
+
}
|
|
20
|
+
i += 1
|
|
21
|
+
}
|
|
22
|
+
sum
|
|
23
|
+
}
|