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.
Files changed (72) hide show
  1. package/compiler/Builder.ff +23 -13
  2. package/compiler/Dictionaries.ff +10 -10
  3. package/compiler/Inference.ff +167 -148
  4. package/compiler/JsEmitter.ff +122 -78
  5. package/compiler/LspHook.ff +6 -3
  6. package/compiler/Main.ff +24 -10
  7. package/compiler/Patterns.ff +1 -1
  8. package/compiler/Resolver.ff +167 -159
  9. package/compiler/Substitution.ff +2 -2
  10. package/compiler/Syntax.ff +1 -0
  11. package/compiler/Unification.ff +1 -1
  12. package/core/Array.ff +6 -4
  13. package/core/Int.ff +12 -12
  14. package/core/List.ff +6 -4
  15. package/core/Map.ff +8 -0
  16. package/core/Set.ff +7 -0
  17. package/experimental/benchmarks/ListGrab.ff +23 -0
  18. package/experimental/benchmarks/ListGrab.java +55 -0
  19. package/experimental/benchmarks/Pyrotek45.ff +30 -0
  20. package/experimental/benchmarks/Pyrotek45.java +64 -0
  21. package/experimental/tests/TestJson.ff +26 -0
  22. package/lsp/Handler.ff +65 -61
  23. package/lsp/SignatureHelpHandler.ff +5 -4
  24. package/lsp/TestReferences.ff +15 -0
  25. package/lsp/TestReferencesCase.ff +8 -0
  26. package/output/js/ff/compiler/Builder.mjs +50 -44
  27. package/output/js/ff/compiler/Dependencies.mjs +0 -2
  28. package/output/js/ff/compiler/Deriver.mjs +16 -140
  29. package/output/js/ff/compiler/Dictionaries.mjs +24 -238
  30. package/output/js/ff/compiler/Environment.mjs +12 -154
  31. package/output/js/ff/compiler/Inference.mjs +207 -1069
  32. package/output/js/ff/compiler/JsEmitter.mjs +434 -2342
  33. package/output/js/ff/compiler/JsImporter.mjs +0 -12
  34. package/output/js/ff/compiler/LspHook.mjs +20 -446
  35. package/output/js/ff/compiler/Main.mjs +110 -553
  36. package/output/js/ff/compiler/Parser.mjs +36 -356
  37. package/output/js/ff/compiler/Patterns.mjs +24 -204
  38. package/output/js/ff/compiler/Resolver.mjs +428 -554
  39. package/output/js/ff/compiler/Substitution.mjs +6 -164
  40. package/output/js/ff/compiler/Syntax.mjs +449 -3293
  41. package/output/js/ff/compiler/Token.mjs +9 -1095
  42. package/output/js/ff/compiler/Tokenizer.mjs +4 -2
  43. package/output/js/ff/compiler/Unification.mjs +30 -364
  44. package/output/js/ff/compiler/Wildcards.mjs +0 -86
  45. package/output/js/ff/compiler/Workspace.mjs +8 -96
  46. package/output/js/ff/core/Array.mjs +15 -8
  47. package/output/js/ff/core/AssetSystem.mjs +4 -14
  48. package/output/js/ff/core/Bool.mjs +0 -12
  49. package/output/js/ff/core/Core.mjs +0 -30
  50. package/output/js/ff/core/Int.mjs +24 -24
  51. package/output/js/ff/core/IntMap.mjs +0 -8
  52. package/output/js/ff/core/Json.mjs +0 -40
  53. package/output/js/ff/core/List.mjs +23 -32
  54. package/output/js/ff/core/Lock.mjs +0 -10
  55. package/output/js/ff/core/Map.mjs +26 -24
  56. package/output/js/ff/core/Option.mjs +10 -286
  57. package/output/js/ff/core/Ordering.mjs +16 -158
  58. package/output/js/ff/core/Pair.mjs +2 -34
  59. package/output/js/ff/core/Path.mjs +2 -28
  60. package/output/js/ff/core/Random.mjs +4 -4
  61. package/output/js/ff/core/RbMap.mjs +56 -644
  62. package/output/js/ff/core/Set.mjs +16 -0
  63. package/output/js/ff/core/Show.mjs +0 -16
  64. package/output/js/ff/core/Stream.mjs +14 -144
  65. package/output/js/ff/core/StringMap.mjs +0 -8
  66. package/output/js/ff/core/Try.mjs +4 -108
  67. package/output/js/ff/core/Unit.mjs +2 -16
  68. package/package.json +1 -1
  69. package/postgresql/Pg.ff +23 -23
  70. package/vscode/package.json +1 -1
  71. package/bin/firefly.mjs +0 -2
  72. package/guide/Main.ff +0 -22
@@ -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 { _ != '/' }.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 { 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
+ 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 { import =>
81
- modules.find { _.file.dropLast(3) == import.file }.{
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) { unqualified } => [Pair(alias + "." + name, full), Pair(name, full), Pair(full, full)]
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 { 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()
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 { _.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()
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}} }.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()
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
- | 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
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
- 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
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
- 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
- )
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, Pair[Location, 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, Pair(at, name))].toMap()
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, _, variableAt, variable) =>
552
- variable.toList().map {x => Pair(x, Pair(variableAt, x))}.toMap()
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, Pair(at, variable))].toMap().addAll(findVariables(pattern))
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.second})
561
- variableLocations = self.variableLocations.addAll(variableMap1.mapValues {_, p => p.first})
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.second})
572
- variableLocations = self.variableLocations.addAll(variableMap2.mapValues {_, p => p.first})
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
@@ -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)) { self.substituteType(self.get(i)) } else { TConstructor(at, core("Nothing"), []) }
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 { t => self.substituteType(t) })
159
+ t.TConstructor(generics = t.generics.map {g => self.substituteType(g)})
160
160
  }
161
161
 
162
162
  get(index: Int): Type {
@@ -9,6 +9,7 @@ extend self: Location {
9
9
  }
10
10
 
11
11
  data CompileError(at: Location, message: String)
12
+ data CompileErrors(errors: List[CompileError])
12
13
 
13
14
  data ModuleWithPackageInfo(
14
15
  packageInfo: Option[PackageInfo]
@@ -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 {t => self.substitute(t)})
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
- if(index_ < 0 || index_ >= self_.array.length) {
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
- mutable result = []
31
- mutable n = inclusiveEnd
32
- while {self <= n} {
33
- result = [n, ...result]
34
- n -= 1
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
- mutable result = []
41
- mutable n = exclusiveEnd
42
- while {self < n} {
43
- result = [n - 1, ...result]
44
- n -= 1
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
- if(index_ < 0 || index_ >= self_.length) {
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
+ }