firefly-compiler 0.5.47 → 0.5.48
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/.vscode/settings.json +1 -1
- package/compiler/Builder.ff +9 -1
- package/compiler/Dependencies.ff +11 -7
- package/compiler/JsEmitter.ff +75 -58
- package/core/Map.ff +8 -0
- package/core/RbMap.ff +16 -0
- package/core/Set.ff +3 -1
- package/experimental/IfBug.ff +8 -0
- package/lsp/LanguageServer.ff +3 -0
- package/output/js/ff/compiler/Builder.mjs +44 -2
- package/output/js/ff/compiler/Dependencies.mjs +26 -12
- package/output/js/ff/compiler/JsEmitter.mjs +698 -598
- package/output/js/ff/core/Map.mjs +16 -0
- package/output/js/ff/core/Path.mjs +2 -8
- package/output/js/ff/core/RbMap.mjs +112 -0
- package/output/js/ff/core/Set.mjs +24 -0
- package/package.json +1 -1
- package/vscode/package.json +1 -1
package/.vscode/settings.json
CHANGED
package/compiler/Builder.ff
CHANGED
|
@@ -136,7 +136,15 @@ check(
|
|
|
136
136
|
|
|
137
137
|
packages.filter {!_.files.isEmpty()}.each {package =>
|
|
138
138
|
let firstFile = package.files.grabFirst()
|
|
139
|
-
|
|
139
|
+
try {
|
|
140
|
+
Some(Dependencies.process(system.httpClient(), dependencyLock, firstFile))
|
|
141
|
+
} tryCatch {| CompileError(_, _) @ c, error =>
|
|
142
|
+
errors.push(c)
|
|
143
|
+
None
|
|
144
|
+
} catch {| CompileErrors(compileErrors), error =>
|
|
145
|
+
errors.pushList(compileErrors)
|
|
146
|
+
None
|
|
147
|
+
}.each: resolvedDependencies =>
|
|
140
148
|
let fixedPackagePaths = if(resolvedDependencies.packagePaths.contains(PackagePair("ff", "core"))) {
|
|
141
149
|
resolvedDependencies.packagePaths
|
|
142
150
|
} else {
|
package/compiler/Dependencies.ff
CHANGED
|
@@ -24,7 +24,7 @@ extend self: Dependencies {
|
|
|
24
24
|
loadPackageInfo(
|
|
25
25
|
packagePair: PackagePair
|
|
26
26
|
path: Path
|
|
27
|
-
): PackageInfo {
|
|
27
|
+
): Option[PackageInfo] {
|
|
28
28
|
let packageDirectory = if(path.extension() == ".ff") {path.parent().grab()} else {path}
|
|
29
29
|
let sharedPackageFile = packageDirectory.slash(".firefly").slash("package.ff")
|
|
30
30
|
let packageFile = if(sharedPackageFile.exists()) {
|
|
@@ -33,8 +33,8 @@ extend self: Dependencies {
|
|
|
33
33
|
self.singleFilePackages = self.singleFilePackages.add(packagePair)
|
|
34
34
|
path
|
|
35
35
|
}
|
|
36
|
-
|
|
37
|
-
self.parsePackageFile(packagePair, packageFile.
|
|
36
|
+
try {packageFile.readText()}.toOption().map: code =>
|
|
37
|
+
self.parsePackageFile(packagePair, packageFile.absolute(), code)
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
parsePackageFile(
|
|
@@ -93,7 +93,7 @@ extend self: Dependencies {
|
|
|
93
93
|
Log.trace("Fetching " + location)
|
|
94
94
|
let buffer = httpClient.get(location, []) {response =>
|
|
95
95
|
if(!response.ok()) {
|
|
96
|
-
|
|
96
|
+
throw(CompileError(dependency.at, "Could not download dependency: " + location))
|
|
97
97
|
}
|
|
98
98
|
response.readBuffer()
|
|
99
99
|
}
|
|
@@ -109,7 +109,7 @@ extend self: Dependencies {
|
|
|
109
109
|
}
|
|
110
110
|
dependencyPath
|
|
111
111
|
} else {
|
|
112
|
-
|
|
112
|
+
throw(CompileError(dependency.at, "Loading packages by this protocol is not supported: " + location))
|
|
113
113
|
}
|
|
114
114
|
} else {
|
|
115
115
|
path.path(location)
|
|
@@ -126,7 +126,9 @@ extend self: Dependencies {
|
|
|
126
126
|
let packageInfos = dependencies.map {dependency =>
|
|
127
127
|
let dependencyPath = self.fetchDependency(path, httpClient, dependencyLock, dependency)
|
|
128
128
|
self.packagePaths = self.packagePaths.add(dependency.packagePair, dependencyPath)
|
|
129
|
-
let packageInfo = self.loadPackageInfo(dependency.packagePair, dependencyPath)
|
|
129
|
+
let packageInfo = self.loadPackageInfo(dependency.packagePair, dependencyPath).else {
|
|
130
|
+
throw(CompileError(dependency.at, "Dependency not found: " + dependencyPath.absolute()))
|
|
131
|
+
}
|
|
130
132
|
checkPackagePairs(dependency.packagePair, packageInfo.package.packagePair)
|
|
131
133
|
packageInfo
|
|
132
134
|
}
|
|
@@ -141,7 +143,9 @@ extend self: Dependencies {
|
|
|
141
143
|
process(fetch: HttpClient, dependencyLock: DependencyLock, path: Path): ResolvedDependencies {
|
|
142
144
|
let workspace = Workspace.loadWorkspace(path)
|
|
143
145
|
let self = Dependencies(workspace, [].toMap(), [].toMap(), [].toSet())
|
|
144
|
-
let packageInfo = self.loadPackageInfo(PackagePair("script", "script"), path)
|
|
146
|
+
let packageInfo = self.loadPackageInfo(PackagePair("script", "script"), path).else {
|
|
147
|
+
panic("Not a main file: " + path.absolute())
|
|
148
|
+
}
|
|
145
149
|
let newDependencies = self.processPackageInfo(packageInfo)
|
|
146
150
|
self.processDependencies(path, fetch, dependencyLock, newDependencies)
|
|
147
151
|
let packagePaths = self.packagePaths.add(packageInfo.package.packagePair, findScriptPackageLocation(path))
|
package/compiler/JsEmitter.ff
CHANGED
|
@@ -279,7 +279,7 @@ extend self: JsEmitter {
|
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
-
emitTerm(term: Term, async: Bool): String {term.{
|
|
282
|
+
emitTerm(term: Term, async: Bool, ignored: Bool = False): String {term.{
|
|
283
283
|
| EString(at, value) {value.startsWith("\"\"\"")} =>
|
|
284
284
|
"`" + value.dropFirst(3).dropLast(3).replace("`", "\\`") + "`" // TODO: Fix escaping
|
|
285
285
|
| EString(at, value) => value
|
|
@@ -347,6 +347,8 @@ extend self: JsEmitter {
|
|
|
347
347
|
let c = if(await) {", $task"} else {""}
|
|
348
348
|
let call = "(" + self.emitTerm(function, async) + ")(" + self.emitTerm(value, async) + c + ")"
|
|
349
349
|
if(await) {"(await " + call + ")"} else {call}
|
|
350
|
+
| _ {self.emitAssignment(term, async) | Some(code)} =>
|
|
351
|
+
if(ignored) {code} else {"(" + code + ", void 0)"}
|
|
350
352
|
| ECall(at, StaticCall(name, _, _), _, _, arguments, dictionaries) {
|
|
351
353
|
self.emitSpecialCall(term, async, name, arguments.map {_.value}, dictionaries) | Some(code)
|
|
352
354
|
} =>
|
|
@@ -379,14 +381,14 @@ extend self: JsEmitter {
|
|
|
379
381
|
let call = functionCode + "(" + [...emittedArguments, ...ds, ...controller].join(", ") + ")"
|
|
380
382
|
if(await) {"(await " + call + ")"} else {call}
|
|
381
383
|
| [Pair(EVariant(_, "ff:core/Bool.True", _, _), elseBody), ...list] =>
|
|
382
|
-
"(" + list.foldLeft(self.
|
|
383
|
-
self.
|
|
384
|
-
"\n? " + self.
|
|
384
|
+
"(" + list.foldLeft(self.emitTerm(elseBody, async)) {| otherwise, Pair(condition, body) =>
|
|
385
|
+
self.emitTerm(condition, async) +
|
|
386
|
+
"\n? " + self.emitTerm(body, async) + "\n: " + otherwise
|
|
385
387
|
} + ")"
|
|
386
388
|
| list =>
|
|
387
389
|
"(" + list.foldLeft("ff_core_Option.None()") {| otherwise, Pair(condition, body) =>
|
|
388
|
-
self.
|
|
389
|
-
"\n? ff_core_Option.Some(" + self.
|
|
390
|
+
self.emitTerm(condition, async) +
|
|
391
|
+
"\n? ff_core_Option.Some(" + self.emitTerm(body, async) + ")\n: " + otherwise
|
|
390
392
|
} + ")"
|
|
391
393
|
}
|
|
392
394
|
| ECall(at, DynamicCall(function, _), effect, typeArguments, arguments, dictionaries) =>
|
|
@@ -405,6 +407,24 @@ extend self: JsEmitter {
|
|
|
405
407
|
| EWildcard(at, index) =>
|
|
406
408
|
if(index == 0) {fail(at, "Unbound wildcard")}
|
|
407
409
|
"_w" + index
|
|
410
|
+
| ESequential(_, ESequential(_, ESequential(_, before1, before2), before3), after) {
|
|
411
|
+
safeCommable(before1) && safeCommable(before2) && safeCommable(before3) && safeCommable(after)
|
|
412
|
+
} =>
|
|
413
|
+
"(" + self.emitTerm(before1, async, ignored = True) + ", " +
|
|
414
|
+
self.emitTerm(before2, async, ignored = True) + ", " +
|
|
415
|
+
self.emitTerm(before3, async, ignored = True) + ", " +
|
|
416
|
+
self.emitTerm(after, async, ignored) + ")"
|
|
417
|
+
| ESequential(_, ESequential(_, before1, before2), after) {
|
|
418
|
+
safeCommable(before1) && safeCommable(before2) && safeCommable(after)
|
|
419
|
+
} =>
|
|
420
|
+
"(" + self.emitTerm(before1, async, ignored = True) + ", " +
|
|
421
|
+
self.emitTerm(before2, async, ignored = True) + ", " +
|
|
422
|
+
self.emitTerm(after, async, ignored) + ")"
|
|
423
|
+
| ESequential(_, before, after) {
|
|
424
|
+
safeCommable(before) && safeCommable(after)
|
|
425
|
+
} =>
|
|
426
|
+
"(" + self.emitTerm(before, async, ignored = True) + ", " +
|
|
427
|
+
self.emitTerm(after, async, ignored) + ")"
|
|
408
428
|
| _ {async} =>
|
|
409
429
|
"(await (async function() {\n" + self.emitStatements(term, True, False, async) + "\n})())"
|
|
410
430
|
| _ =>
|
|
@@ -450,11 +470,6 @@ extend self: JsEmitter {
|
|
|
450
470
|
| ESequential(at, before, after) =>
|
|
451
471
|
self.emitStatements(before, False, False, async) + ";\n" +
|
|
452
472
|
self.emitStatements(after, last, break, async)
|
|
453
|
-
| EAssign(at, operator, name, value) =>
|
|
454
|
-
escapeKeyword(name) + " " + operator + "= " + self.emitTerm(value, async)
|
|
455
|
-
| EAssignField(at, operator, record, field, value) =>
|
|
456
|
-
self.emitTerm(record, async) + "." + escapeKeyword(field) + " " + operator + "= " +
|
|
457
|
-
self.emitTerm(value, async)
|
|
458
473
|
| ECall(at, StaticCall(name, True, instanceCall), effect, _, arguments, _) =>
|
|
459
474
|
if(instanceCall) {throw(CompileError(at, "Not yet implemented: Tail calls on trait methods."))}
|
|
460
475
|
self.tailCallUsed = True
|
|
@@ -478,15 +493,17 @@ extend self: JsEmitter {
|
|
|
478
493
|
self.emitCase(["_1"], c, [], [], True, last, break, lastCase, async)
|
|
479
494
|
}.join("\n") +
|
|
480
495
|
"\n}" + if(!last && !break) {" while(false)"}.else {""}
|
|
496
|
+
| _ {self.emitAssignment(term, async) | Some(code)} =>
|
|
497
|
+
code
|
|
481
498
|
| _ =>
|
|
482
499
|
detectIfElse(term).{
|
|
483
500
|
| [] =>
|
|
484
501
|
if(break) {
|
|
485
|
-
"if(!" + self.
|
|
502
|
+
"if(!" + self.emitTerm(term, async) + ") break"
|
|
486
503
|
} elseIf {last} {
|
|
487
504
|
"return " + self.emitTerm(term, async)
|
|
488
505
|
} else {
|
|
489
|
-
self.emitTerm(term, async)
|
|
506
|
+
self.emitTerm(term, async, ignored = True)
|
|
490
507
|
}
|
|
491
508
|
| [Pair(EVariant(_, "ff:core/Bool.True", _, _), elseBody), ...list] =>
|
|
492
509
|
let initial = "{\n" + self.emitStatements(elseBody, last, break, async) + "\n}"
|
|
@@ -508,6 +525,49 @@ extend self: JsEmitter {
|
|
|
508
525
|
}
|
|
509
526
|
}
|
|
510
527
|
|
|
528
|
+
emitAssignment(
|
|
529
|
+
term: Term
|
|
530
|
+
async: Bool
|
|
531
|
+
): Option[String] {
|
|
532
|
+
| ECall(at, StaticCall(name, _, _), _, _, arguments, dictionaries), _ =>
|
|
533
|
+
name.{
|
|
534
|
+
| "ff:core/JsValue.JsValue_set" {arguments.map {_.value} | [e1, e2, e3]} =>
|
|
535
|
+
Some(self.emitTerm(e1, async) + self.emitField(e2, async) + " = " + self.emitTerm(e3, async))
|
|
536
|
+
| "ff:core/JsValue.JsValue_increment" {arguments.map {_.value} | [e1, e2, e3]} =>
|
|
537
|
+
Some(self.emitTerm(e1, async) + self.emitField(e2, async) + " += " + self.emitTerm(e3, async))
|
|
538
|
+
| "ff:core/JsValue.JsValue_decrement" {arguments.map {_.value} | [e1, e2, e3]} =>
|
|
539
|
+
Some(self.emitTerm(e1, async) + self.emitField(e2, async) + " -= " + self.emitTerm(e3, async))
|
|
540
|
+
| "ff:core/JsSystem.JsSystem_set" {arguments.map {_.value} | [e1, EString(_, q), e3]} {
|
|
541
|
+
noSideEffects(e1)} {safeBare(q) | Some(s)
|
|
542
|
+
} =>
|
|
543
|
+
Some(s + " = " + self.emitTerm(e3, async))
|
|
544
|
+
| "ff:core/JsSystem.JsSystem_increment" {arguments.map {_.value} | [e1, EString(_, q), e3]} {
|
|
545
|
+
noSideEffects(e1)} {safeBare(q) | Some(s)
|
|
546
|
+
} =>
|
|
547
|
+
Some(s + " += " + self.emitTerm(e3, async))
|
|
548
|
+
| "ff:core/JsSystem.JsSystem_decrement" {arguments.map {_.value} | [e1, EString(_, q), e3]} {
|
|
549
|
+
noSideEffects(e1)} {safeBare(q) | Some(s)
|
|
550
|
+
} =>
|
|
551
|
+
Some(s + " -= " + self.emitTerm(e3, async))
|
|
552
|
+
| "ff:core/Js.set" {arguments.map {_.value} | [EString(_, q), e2]} {safeBare(q) | Some(s)} =>
|
|
553
|
+
Some(s + " = " + self.emitTerm(e2, async))
|
|
554
|
+
| "ff:core/Js.increment" {arguments.map {_.value} | [EString(_, q), e2]} {safeBare(q) | Some(s)} =>
|
|
555
|
+
Some(s + " += " + self.emitTerm(e2, async))
|
|
556
|
+
| "ff:core/Js.decrement" {arguments.map {_.value} | [EString(_, q), e2]} {safeBare(q) | Some(s)} =>
|
|
557
|
+
Some(s + " -= " + self.emitTerm(e2, async))
|
|
558
|
+
| _ => None
|
|
559
|
+
}
|
|
560
|
+
| EAssign(at, operator, name, value), _ =>
|
|
561
|
+
Some(escapeKeyword(name) + " " + operator + "= " + self.emitTerm(value, async))
|
|
562
|
+
| EAssignField(at, operator, record, field, value), _ =>
|
|
563
|
+
Some(
|
|
564
|
+
self.emitTerm(record, async) + "." + escapeKeyword(field) + " " + operator + "= " +
|
|
565
|
+
self.emitTerm(value, async)
|
|
566
|
+
)
|
|
567
|
+
| _, _ =>
|
|
568
|
+
None
|
|
569
|
+
}
|
|
570
|
+
|
|
511
571
|
emitSpecialCall(
|
|
512
572
|
term: Term
|
|
513
573
|
async: Bool
|
|
@@ -794,7 +854,7 @@ extend self: JsEmitter {
|
|
|
794
854
|
name.{
|
|
795
855
|
| "ff:core/Core.while" {arguments | [condition, body]} =>
|
|
796
856
|
Some(
|
|
797
|
-
"while(" + self.
|
|
857
|
+
"while(" + self.emitTerm(invokeImmediately(condition), async) + ") {\n" +
|
|
798
858
|
self.emitStatements(invokeImmediately(body), False, False, async) + "\n}"
|
|
799
859
|
)
|
|
800
860
|
| "ff:core/Core.doWhile" {arguments | [doWhileBody]} {
|
|
@@ -906,7 +966,7 @@ extend self: JsEmitter {
|
|
|
906
966
|
Some(self.emitTerm(array, async) + ".array.push(" + self.emitTerm(value, async) + ")")
|
|
907
967
|
| "ff:core/Core.if" {arguments | [condition, body]} =>
|
|
908
968
|
Some(
|
|
909
|
-
"if(" + self.
|
|
969
|
+
"if(" + self.emitTerm(condition, async) + ") {\n" +
|
|
910
970
|
if(last) {
|
|
911
971
|
"return ff_core_Option.Some(" + self.emitTerm(invokeImmediately(body), async) +
|
|
912
972
|
")\n} else return ff_core_Option.None()"
|
|
@@ -928,24 +988,6 @@ extend self: JsEmitter {
|
|
|
928
988
|
Some(if(async) {"ff_core_Task.Task_throwIfAborted($task)"} else {""})
|
|
929
989
|
| "ff:core/Js.throw" {term | ECall c} {c.arguments | [argument]} =>
|
|
930
990
|
Some("throw " + self.emitTerm(argument.value, async))
|
|
931
|
-
| "ff:core/JsValue.JsValue_set" {arguments | [e1, e2, e3]} =>
|
|
932
|
-
Some(self.emitTerm(e1, async) + self.emitField(e2, async) + " = " + self.emitTerm(e3, async))
|
|
933
|
-
| "ff:core/JsValue.JsValue_increment" {arguments | [e1, e2, e3]} =>
|
|
934
|
-
Some(self.emitTerm(e1, async) + self.emitField(e2, async) + " += " + self.emitTerm(e3, async))
|
|
935
|
-
| "ff:core/JsValue.JsValue_decrement" {arguments | [e1, e2, e3]} =>
|
|
936
|
-
Some(self.emitTerm(e1, async) + self.emitField(e2, async) + " -= " + self.emitTerm(e3, async))
|
|
937
|
-
| "ff:core/JsSystem.JsSystem_set" {arguments | [e1, EString(_, q), e3]} {noSideEffects(e1)} {safeBare(q) | Some(s)} =>
|
|
938
|
-
Some(s + " = " + self.emitTerm(e3, async))
|
|
939
|
-
| "ff:core/JsSystem.JsSystem_increment" {arguments | [e1, EString(_, q), e3]} {noSideEffects(e1)} {safeBare(q) | Some(s)} =>
|
|
940
|
-
Some(s + " += " + self.emitTerm(e3, async))
|
|
941
|
-
| "ff:core/JsSystem.JsSystem_decrement" {arguments | [e1, EString(_, q), e3]} {noSideEffects(e1)} {safeBare(q) | Some(s)} =>
|
|
942
|
-
Some(s + " -= " + self.emitTerm(e3, async))
|
|
943
|
-
| "ff:core/Js.set" {arguments | [EString(_, q), e2]} {safeBare(q) | Some(s)} =>
|
|
944
|
-
Some(s + " = " + self.emitTerm(e2, async))
|
|
945
|
-
| "ff:core/Js.increment" {arguments | [EString(_, q), e2]} {safeBare(q) | Some(s)} =>
|
|
946
|
-
Some(s + " += " + self.emitTerm(e2, async))
|
|
947
|
-
| "ff:core/Js.decrement" {arguments | [EString(_, q), e2]} {safeBare(q) | Some(s)} =>
|
|
948
|
-
Some(s + " -= " + self.emitTerm(e2, async))
|
|
949
991
|
| _ =>
|
|
950
992
|
None
|
|
951
993
|
}
|
|
@@ -1280,31 +1322,6 @@ extend self: JsEmitter {
|
|
|
1280
1322
|
}
|
|
1281
1323
|
}
|
|
1282
1324
|
|
|
1283
|
-
emitComma(term: Term, async: Bool): String {
|
|
1284
|
-
term.{
|
|
1285
|
-
| ESequential(_, ESequential(_, ESequential(_, before1, before2), before3), after) {
|
|
1286
|
-
safeCommable(before1) && safeCommable(before2) && safeCommable(before3) && safeCommable(after)
|
|
1287
|
-
} =>
|
|
1288
|
-
"(" + self.emitStatements(before1, False, False, async) + ", " +
|
|
1289
|
-
self.emitStatements(before2, False, False, async) + ", " +
|
|
1290
|
-
self.emitStatements(before3, False, False, async) + ", " +
|
|
1291
|
-
self.emitTerm(after, async) + ")"
|
|
1292
|
-
| ESequential(_, ESequential(_, before1, before2), after) {
|
|
1293
|
-
safeCommable(before1) && safeCommable(before2) && safeCommable(after)
|
|
1294
|
-
} =>
|
|
1295
|
-
"(" + self.emitStatements(before1, False, False, async) + ", " +
|
|
1296
|
-
self.emitStatements(before2, False, False, async) + ", " +
|
|
1297
|
-
self.emitTerm(after, async) + ")"
|
|
1298
|
-
| ESequential(_, before, after) {
|
|
1299
|
-
safeCommable(before) && safeCommable(after)
|
|
1300
|
-
} =>
|
|
1301
|
-
"(" + self.emitStatements(before, False, False, async) + ", " +
|
|
1302
|
-
self.emitTerm(after, async) + ")"
|
|
1303
|
-
| _ =>
|
|
1304
|
-
self.emitTerm(term, async)
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
1325
|
}
|
|
1309
1326
|
|
|
1310
1327
|
data ProcessedVariantCase(
|
package/core/Map.ff
CHANGED
|
@@ -29,6 +29,14 @@ extend self[K: Order, V]: Map[K, V] {
|
|
|
29
29
|
get(key: K): Option[V] {
|
|
30
30
|
self.redBlack.get(key)
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
lastBefore(key: K): Option[Pair[K, V]] {
|
|
34
|
+
self.redBlack.lastBefore(key)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
firstAfter(key: K): Option[Pair[K, V]] {
|
|
38
|
+
self.redBlack.firstAfter(key)
|
|
39
|
+
}
|
|
32
40
|
|
|
33
41
|
remove(key: K): Map[K, V] {
|
|
34
42
|
Map(RbMap.delete(key, self.redBlack))
|
package/core/RbMap.ff
CHANGED
|
@@ -123,6 +123,22 @@ extend self[K: Order, V]: RB[K, V] {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
+
|
|
127
|
+
lastBefore(key: K): Option[Pair[K, V]] {
|
|
128
|
+
self.{
|
|
129
|
+
| E => None
|
|
130
|
+
| T(_, l, k, v, r) {k >= key} => l.lastBefore(key)
|
|
131
|
+
| T(_, l, k, v, r) => r.lastBefore(key).orElse {Some(Pair(k, v))}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
firstAfter(key: K): Option[Pair[K, V]] {
|
|
136
|
+
self.{
|
|
137
|
+
| E => None
|
|
138
|
+
| T(_, l, k, v, r) {k <= key} => r.firstAfter(key)
|
|
139
|
+
| T(_, l, k, v, r) => l.firstAfter(key).orElse {Some(Pair(k, v))}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
126
142
|
|
|
127
143
|
size(): Int {
|
|
128
144
|
self.{
|
package/core/Set.ff
CHANGED
|
@@ -17,6 +17,8 @@ extend self[T: Order]: Set[T] {
|
|
|
17
17
|
remove(value: T): Set[T] {Set(self.map.remove(value))}
|
|
18
18
|
removeAll(that: Set[T]): Set[T] {Set(self.map.removeAll(that.map))}
|
|
19
19
|
contains(value: T): Bool {self.map.contains(value)}
|
|
20
|
+
lastBefore(key: T): Option[T] {self.map.lastBefore(key).map {_.first}}
|
|
21
|
+
firstAfter(key: T): Option[T] {self.map.firstAfter(key).map {_.first}}
|
|
20
22
|
size(): Int {self.map.size()}
|
|
21
23
|
toList(): List[T] {self.map.toList().map {_.first}}
|
|
22
24
|
toStream(cycle: Bool = False): Stream[T] {self.map.toStream(cycle).map {_.first }}
|
|
@@ -41,4 +43,4 @@ instance Set[A: Show: Order]: Show {
|
|
|
41
43
|
show(value: Set[A]): String {
|
|
42
44
|
Show.show(value.toList()) + ".toSet()"
|
|
43
45
|
}
|
|
44
|
-
}
|
|
46
|
+
}
|
package/lsp/LanguageServer.ff
CHANGED
|
@@ -117,6 +117,9 @@ taskGroup[K: Order, R](
|
|
|
117
117
|
parseRequest(system: NodeSystem, input: Stream[Buffer]): Pair[Request, Stream[Buffer]] {
|
|
118
118
|
let headersPair = parseRequestHeaders(input)
|
|
119
119
|
let headers = headersPair.first
|
|
120
|
+
if(!headers.contains("content-length")) {
|
|
121
|
+
system.writeErrorLine(Show.show(headers.toList()))
|
|
122
|
+
}
|
|
120
123
|
let contentLength = headers
|
|
121
124
|
.get("content-length").else {throw(BadRequestException("'content-length' header is missing"))}
|
|
122
125
|
.trim().getInt().else {throw(BadRequestException("Value for 'content-length' is not an integer"))}
|
|
@@ -217,7 +217,26 @@ return (!ff_core_List.List_isEmpty(_w1.files_))
|
|
|
217
217
|
})), for_i = 0, for_l = for_a.length; for_i < for_l; for_i++) {
|
|
218
218
|
const package_ = for_a[for_i];
|
|
219
219
|
const firstFile_ = ff_core_List.List_grabFirst(package_.files_);
|
|
220
|
-
|
|
220
|
+
{
|
|
221
|
+
const if_o = ff_core_Try.Try_catch(ff_core_Try.Try_tryCatch(ff_core_Core.try_((() => {
|
|
222
|
+
return ff_core_Option.Some(ff_compiler_Dependencies.process_(ff_core_NodeSystem.NodeSystem_httpClient(system_), dependencyLock_, firstFile_))
|
|
223
|
+
})), ((_1, _2) => {
|
|
224
|
+
{
|
|
225
|
+
const c_ = _1;
|
|
226
|
+
const error_ = _2;
|
|
227
|
+
errors_.array.push(c_);
|
|
228
|
+
return ff_core_Option.None()
|
|
229
|
+
}
|
|
230
|
+
}), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError), ((_1, _2) => {
|
|
231
|
+
{
|
|
232
|
+
const compileErrors_ = _1.errors_;
|
|
233
|
+
const error_ = _2;
|
|
234
|
+
ff_core_Array.Array_pushList(errors_, compileErrors_);
|
|
235
|
+
return ff_core_Option.None()
|
|
236
|
+
}
|
|
237
|
+
}), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileErrors)
|
|
238
|
+
if(if_o.Some) {
|
|
239
|
+
const resolvedDependencies_ = if_o.value_;
|
|
221
240
|
const fixedPackagePaths_ = (ff_core_Map.Map_contains(resolvedDependencies_.packagePaths_, ff_compiler_Syntax.PackagePair("ff", "core"), ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair)
|
|
222
241
|
? resolvedDependencies_.packagePaths_
|
|
223
242
|
: ff_core_Map.Map_add(resolvedDependencies_.packagePaths_, ff_compiler_Syntax.PackagePair("ff", "core"), ff_core_Path.Path_slash(fireflyPath_, "core"), ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair));
|
|
@@ -257,6 +276,8 @@ return
|
|
|
257
276
|
}), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileErrors)
|
|
258
277
|
};
|
|
259
278
|
ff_compiler_ModuleCache.ModuleCache_mergeVersions(cache_, compiler_.cache_)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
260
281
|
};
|
|
261
282
|
return ff_core_Array.Array_drain(errors_)
|
|
262
283
|
}
|
|
@@ -439,7 +460,26 @@ return (!ff_core_List.List_isEmpty(_w1.files_))
|
|
|
439
460
|
})), for_i = 0, for_l = for_a.length; for_i < for_l; for_i++) {
|
|
440
461
|
const package_ = for_a[for_i];
|
|
441
462
|
const firstFile_ = ff_core_List.List_grabFirst(package_.files_);
|
|
442
|
-
|
|
463
|
+
{
|
|
464
|
+
const if_o = ff_core_Try.Try_catch(ff_core_Try.Try_tryCatch((await ff_core_Core.try_$((async ($task) => {
|
|
465
|
+
return ff_core_Option.Some((await ff_compiler_Dependencies.process_$((await ff_core_NodeSystem.NodeSystem_httpClient$(system_, $task)), dependencyLock_, firstFile_, $task)))
|
|
466
|
+
}), $task)), ((_1, _2) => {
|
|
467
|
+
{
|
|
468
|
+
const c_ = _1;
|
|
469
|
+
const error_ = _2;
|
|
470
|
+
errors_.array.push(c_);
|
|
471
|
+
return ff_core_Option.None()
|
|
472
|
+
}
|
|
473
|
+
}), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError), ((_1, _2) => {
|
|
474
|
+
{
|
|
475
|
+
const compileErrors_ = _1.errors_;
|
|
476
|
+
const error_ = _2;
|
|
477
|
+
ff_core_Array.Array_pushList(errors_, compileErrors_);
|
|
478
|
+
return ff_core_Option.None()
|
|
479
|
+
}
|
|
480
|
+
}), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileErrors)
|
|
481
|
+
if(if_o.Some) {
|
|
482
|
+
const resolvedDependencies_ = if_o.value_;
|
|
443
483
|
const fixedPackagePaths_ = (ff_core_Map.Map_contains(resolvedDependencies_.packagePaths_, ff_compiler_Syntax.PackagePair("ff", "core"), ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair)
|
|
444
484
|
? resolvedDependencies_.packagePaths_
|
|
445
485
|
: ff_core_Map.Map_add(resolvedDependencies_.packagePaths_, ff_compiler_Syntax.PackagePair("ff", "core"), (await ff_core_Path.Path_slash$(fireflyPath_, "core", $task)), ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair));
|
|
@@ -479,6 +519,8 @@ return
|
|
|
479
519
|
}), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileErrors)
|
|
480
520
|
};
|
|
481
521
|
ff_compiler_ModuleCache.ModuleCache_mergeVersions(cache_, compiler_.cache_)
|
|
522
|
+
}
|
|
523
|
+
}
|
|
482
524
|
};
|
|
483
525
|
return ff_core_Array.Array_drain(errors_)
|
|
484
526
|
}
|
|
@@ -123,7 +123,9 @@ return {mainPackagePair_, packages_, packagePaths_, singleFilePackages_};
|
|
|
123
123
|
export function process_(fetch_, dependencyLock_, path_) {
|
|
124
124
|
const workspace_ = ff_compiler_Workspace.loadWorkspace_(path_);
|
|
125
125
|
const self_ = ff_compiler_Dependencies.Dependencies(workspace_, ff_core_List.List_toMap([], ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair), ff_core_List.List_toMap([], ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair), ff_core_List.List_toSet([], ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair));
|
|
126
|
-
const packageInfo_ = ff_compiler_Dependencies.Dependencies_loadPackageInfo(self_, ff_compiler_Syntax.PackagePair("script", "script"), path_)
|
|
126
|
+
const packageInfo_ = ff_core_Option.Option_else(ff_compiler_Dependencies.Dependencies_loadPackageInfo(self_, ff_compiler_Syntax.PackagePair("script", "script"), path_), (() => {
|
|
127
|
+
return ff_core_Core.panic_(("Not a main file: " + ff_core_Path.Path_absolute(path_)))
|
|
128
|
+
}));
|
|
127
129
|
const newDependencies_ = ff_compiler_Dependencies.Dependencies_processPackageInfo(self_, packageInfo_);
|
|
128
130
|
ff_compiler_Dependencies.Dependencies_processDependencies(self_, path_, fetch_, dependencyLock_, newDependencies_);
|
|
129
131
|
const packagePaths_ = ff_core_Map.Map_add(self_.packagePaths_, packageInfo_.package_.packagePair_, ff_compiler_Dependencies.findScriptPackageLocation_(path_), ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair);
|
|
@@ -161,7 +163,9 @@ tar_.extract({file: tarGzPath_.absolutePath_, cwd: path_.absolutePath_, strict:
|
|
|
161
163
|
export async function process_$(fetch_, dependencyLock_, path_, $task) {
|
|
162
164
|
const workspace_ = (await ff_compiler_Workspace.loadWorkspace_$(path_, $task));
|
|
163
165
|
const self_ = ff_compiler_Dependencies.Dependencies(workspace_, ff_core_List.List_toMap([], ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair), ff_core_List.List_toMap([], ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair), ff_core_List.List_toSet([], ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair));
|
|
164
|
-
const packageInfo_ = (await ff_compiler_Dependencies.Dependencies_loadPackageInfo$(self_, ff_compiler_Syntax.PackagePair("script", "script"), path_, $task))
|
|
166
|
+
const packageInfo_ = (await ff_core_Option.Option_else$((await ff_compiler_Dependencies.Dependencies_loadPackageInfo$(self_, ff_compiler_Syntax.PackagePair("script", "script"), path_, $task)), (async ($task) => {
|
|
167
|
+
return ff_core_Core.panic_(("Not a main file: " + (await ff_core_Path.Path_absolute$(path_, $task))))
|
|
168
|
+
}), $task));
|
|
165
169
|
const newDependencies_ = (await ff_compiler_Dependencies.Dependencies_processPackageInfo$(self_, packageInfo_, $task));
|
|
166
170
|
(await ff_compiler_Dependencies.Dependencies_processDependencies$(self_, path_, fetch_, dependencyLock_, newDependencies_, $task));
|
|
167
171
|
const packagePaths_ = ff_core_Map.Map_add(self_.packagePaths_, packageInfo_.package_.packagePair_, (await ff_compiler_Dependencies.findScriptPackageLocation_$(path_, $task)), ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair);
|
|
@@ -204,8 +208,11 @@ const sharedPackageFile_ = ff_core_Path.Path_slash(ff_core_Path.Path_slash(packa
|
|
|
204
208
|
const packageFile_ = (ff_core_Path.Path_exists(sharedPackageFile_, false, false, false)
|
|
205
209
|
? sharedPackageFile_
|
|
206
210
|
: (self_.singleFilePackages_ = ff_core_Set.Set_add(self_.singleFilePackages_, packagePair_, ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair), path_));
|
|
207
|
-
|
|
208
|
-
return
|
|
211
|
+
return ff_core_Option.Option_map(ff_core_Try.Try_toOption(ff_core_Core.try_((() => {
|
|
212
|
+
return ff_core_Path.Path_readText(packageFile_)
|
|
213
|
+
}))), ((code_) => {
|
|
214
|
+
return ff_compiler_Dependencies.Dependencies_parsePackageFile(self_, packagePair_, ff_core_Path.Path_absolute(packageFile_), code_)
|
|
215
|
+
}))
|
|
209
216
|
}
|
|
210
217
|
|
|
211
218
|
export function Dependencies_parsePackageFile(self_, packagePair_, fileName_, code_) {
|
|
@@ -258,7 +265,7 @@ return ff_core_Option.Some((function() {
|
|
|
258
265
|
ff_core_Log.trace_(("Fetching " + location_));
|
|
259
266
|
const buffer_ = ff_core_HttpClient.HttpClient_get(httpClient_, location_, [], ((response_) => {
|
|
260
267
|
if((!ff_core_HttpClient.FetchResponse_ok(response_))) {
|
|
261
|
-
|
|
268
|
+
throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(dependency_.at_, ("Could not download dependency: " + location_)), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
|
|
262
269
|
};
|
|
263
270
|
return ff_core_HttpClient.FetchResponse_readBuffer(response_)
|
|
264
271
|
}));
|
|
@@ -275,7 +282,7 @@ return ff_core_Path.Path_renameTo(tarGzPath_, donePath_)
|
|
|
275
282
|
};
|
|
276
283
|
return dependencyPath_
|
|
277
284
|
} else {
|
|
278
|
-
|
|
285
|
+
throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(dependency_.at_, ("Loading packages by this protocol is not supported: " + location_)), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
|
|
279
286
|
}
|
|
280
287
|
} else {
|
|
281
288
|
return ff_core_Path.Path_path(path_, location_)
|
|
@@ -286,7 +293,9 @@ export function Dependencies_processDependencies(self_, path_, httpClient_, depe
|
|
|
286
293
|
const packageInfos_ = ff_core_List.List_map(dependencies_, ((dependency_) => {
|
|
287
294
|
const dependencyPath_ = ff_compiler_Dependencies.Dependencies_fetchDependency(self_, path_, httpClient_, dependencyLock_, dependency_);
|
|
288
295
|
self_.packagePaths_ = ff_core_Map.Map_add(self_.packagePaths_, dependency_.packagePair_, dependencyPath_, ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair);
|
|
289
|
-
const packageInfo_ = ff_compiler_Dependencies.Dependencies_loadPackageInfo(self_, dependency_.packagePair_, dependencyPath_)
|
|
296
|
+
const packageInfo_ = ff_core_Option.Option_else(ff_compiler_Dependencies.Dependencies_loadPackageInfo(self_, dependency_.packagePair_, dependencyPath_), (() => {
|
|
297
|
+
throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(dependency_.at_, ("Dependency not found: " + ff_core_Path.Path_absolute(dependencyPath_))), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
|
|
298
|
+
}));
|
|
290
299
|
ff_compiler_Dependencies.checkPackagePairs_(dependency_.packagePair_, packageInfo_.package_.packagePair_);
|
|
291
300
|
return packageInfo_
|
|
292
301
|
}));
|
|
@@ -306,8 +315,11 @@ const sharedPackageFile_ = (await ff_core_Path.Path_slash$((await ff_core_Path.P
|
|
|
306
315
|
const packageFile_ = ((await ff_core_Path.Path_exists$(sharedPackageFile_, false, false, false, $task))
|
|
307
316
|
? sharedPackageFile_
|
|
308
317
|
: (self_.singleFilePackages_ = ff_core_Set.Set_add(self_.singleFilePackages_, packagePair_, ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair), path_));
|
|
309
|
-
|
|
310
|
-
return (await
|
|
318
|
+
return (await ff_core_Option.Option_map$(ff_core_Try.Try_toOption((await ff_core_Core.try_$((async ($task) => {
|
|
319
|
+
return (await ff_core_Path.Path_readText$(packageFile_, $task))
|
|
320
|
+
}), $task))), (async (code_, $task) => {
|
|
321
|
+
return (await ff_compiler_Dependencies.Dependencies_parsePackageFile$(self_, packagePair_, (await ff_core_Path.Path_absolute$(packageFile_, $task)), code_, $task))
|
|
322
|
+
}), $task))
|
|
311
323
|
}
|
|
312
324
|
|
|
313
325
|
export async function Dependencies_parsePackageFile$(self_, packagePair_, fileName_, code_, $task) {
|
|
@@ -360,7 +372,7 @@ return ff_core_Option.Some((await (async function() {
|
|
|
360
372
|
ff_core_Log.trace_(("Fetching " + location_));
|
|
361
373
|
const buffer_ = (await ff_core_HttpClient.HttpClient_get$(httpClient_, location_, [], (async (response_, $task) => {
|
|
362
374
|
if((!(await ff_core_HttpClient.FetchResponse_ok$(response_, $task)))) {
|
|
363
|
-
|
|
375
|
+
throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(dependency_.at_, ("Could not download dependency: " + location_)), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
|
|
364
376
|
};
|
|
365
377
|
return (await ff_core_HttpClient.FetchResponse_readBuffer$(response_, $task))
|
|
366
378
|
}), $task));
|
|
@@ -377,7 +389,7 @@ return (await ff_core_Path.Path_renameTo$(tarGzPath_, donePath_, $task))
|
|
|
377
389
|
};
|
|
378
390
|
return dependencyPath_
|
|
379
391
|
} else {
|
|
380
|
-
|
|
392
|
+
throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(dependency_.at_, ("Loading packages by this protocol is not supported: " + location_)), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
|
|
381
393
|
}
|
|
382
394
|
} else {
|
|
383
395
|
return (await ff_core_Path.Path_path$(path_, location_, $task))
|
|
@@ -388,7 +400,9 @@ export async function Dependencies_processDependencies$(self_, path_, httpClient
|
|
|
388
400
|
const packageInfos_ = (await ff_core_List.List_map$(dependencies_, (async (dependency_, $task) => {
|
|
389
401
|
const dependencyPath_ = (await ff_compiler_Dependencies.Dependencies_fetchDependency$(self_, path_, httpClient_, dependencyLock_, dependency_, $task));
|
|
390
402
|
self_.packagePaths_ = ff_core_Map.Map_add(self_.packagePaths_, dependency_.packagePair_, dependencyPath_, ff_compiler_Syntax.ff_core_Ordering_Order$ff_compiler_Syntax_PackagePair);
|
|
391
|
-
const packageInfo_ = (await ff_compiler_Dependencies.Dependencies_loadPackageInfo$(self_, dependency_.packagePair_, dependencyPath_, $task))
|
|
403
|
+
const packageInfo_ = (await ff_core_Option.Option_else$((await ff_compiler_Dependencies.Dependencies_loadPackageInfo$(self_, dependency_.packagePair_, dependencyPath_, $task)), (async ($task) => {
|
|
404
|
+
throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(dependency_.at_, ("Dependency not found: " + (await ff_core_Path.Path_absolute$(dependencyPath_, $task)))), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
|
|
405
|
+
}), $task));
|
|
392
406
|
ff_compiler_Dependencies.checkPackagePairs_(dependency_.packagePair_, packageInfo_.package_.packagePair_);
|
|
393
407
|
return packageInfo_
|
|
394
408
|
}), $task));
|