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/JsEmitter.ff
CHANGED
|
@@ -223,9 +223,9 @@ extend self: JsEmitter {
|
|
|
223
223
|
}.join("\n")
|
|
224
224
|
let body = self.emitTailCall {
|
|
225
225
|
let casesString = cases.map {
|
|
226
|
-
|
|
226
|
+
self.emitCase(escapedArguments, _, [], [], True, True, async)
|
|
227
227
|
}.join("\n")
|
|
228
|
-
|
|
228
|
+
shadowingWorkaround + "\n" + casesString
|
|
229
229
|
}
|
|
230
230
|
signature + " {\n" + body + "\n}"
|
|
231
231
|
}
|
|
@@ -343,7 +343,7 @@ extend self: JsEmitter {
|
|
|
343
343
|
Patterns.convertAndCheck(self.otherModules, cases)
|
|
344
344
|
let arguments = cases.grab(0).patterns.pairs().map {"_" + (_.first + 1)}
|
|
345
345
|
let escapedArguments = arguments.map(escapeKeyword) // emitCase arguments must be preescaped
|
|
346
|
-
let caseStrings = cases.map {
|
|
346
|
+
let caseStrings = cases.map {self.emitCase(escapedArguments, _, [], [], True, True, newAsync)}
|
|
347
347
|
let prefix = if(newAsync) {"async "} else {""}
|
|
348
348
|
"(" + prefix + "(" + [...escapedArguments, ...controller].join(", ") + ") => " +
|
|
349
349
|
"{\n" + caseStrings.join("\n") + "\n})"
|
|
@@ -356,6 +356,12 @@ extend self: JsEmitter {
|
|
|
356
356
|
"(" + operator + self.emitArgument(at, value, async) + ")"
|
|
357
357
|
| ECall(at, StaticCall(operator, _, _), _, [], [left, right], _) {!operator.grabFirst().isAsciiLetter()} =>
|
|
358
358
|
"(" + self.emitArgument(at, left, async) + " " + operator + " " + self.emitArgument(at, right, async) + ")"
|
|
359
|
+
| ECall(at, StaticCall("ff:core/List.List_grab", _, _), _, _, [Argument(_, _, EVariable(_, x1)), Argument(_, _, EVariable(_, x2))], _) =>
|
|
360
|
+
"(" + escapeResolved(x1) + "[" + escapeResolved(x2) + "] ?? " +
|
|
361
|
+
"ff_core_List.internalGrab_(" + escapeResolved(x1) + ", " + escapeResolved(x2) + "))"
|
|
362
|
+
| ECall(at, StaticCall("ff:core/Array.Array_grab", _, _), _, _, [Argument(_, _, EVariable(_, x1)), Argument(_, _, EVariable(_, x2))], _) =>
|
|
363
|
+
"(" + escapeResolved(x1) + ".array[" + escapeResolved(x2) + "] ?? " +
|
|
364
|
+
"ff_core_Array.internalGrab_(" + escapeResolved(x1) + ", " + escapeResolved(x2) + "))"
|
|
359
365
|
| ECall(at, StaticCall("ff:unsafejs/UnsafeJs.import", _, _), _, _, [Argument(_, _, EString(_, url))], _) =>
|
|
360
366
|
self.jsImporter.add(url.replace("\"", ""))
|
|
361
367
|
| ECall(at, StaticCall("ff:unsafejs/UnsafeJs.await", _, _), _, _, [Argument(_, _, body)], _) =>
|
|
@@ -490,9 +496,9 @@ extend self: JsEmitter {
|
|
|
490
496
|
self.emitStatements(body, last, async)
|
|
491
497
|
| EVariant(at, "ff:core/Unit.Unit", _, _) =>
|
|
492
498
|
""
|
|
493
|
-
| ESequential(
|
|
499
|
+
| ESequential(_, EVariant(_, "ff:core/Unit.Unit", _, _), after) =>
|
|
494
500
|
self.emitStatements(after, last, async)
|
|
495
|
-
| ESequential(
|
|
501
|
+
| ESequential(_, before, EVariant(_, "ff:core/Unit.Unit", _, _)) =>
|
|
496
502
|
self.emitStatements(before, False, async)
|
|
497
503
|
| ESequential(at, before, after) =>
|
|
498
504
|
self.emitStatements(before, False, async) + ";\n" + self.emitStatements(after, last, async)
|
|
@@ -561,7 +567,7 @@ extend self: JsEmitter {
|
|
|
561
567
|
Patterns.convertAndCheck(self.otherModules, cases)
|
|
562
568
|
if(!last) {"do "}.else {""} +
|
|
563
569
|
"{\nconst _1 = " + self.emitTerm(value, async) + ";\n" +
|
|
564
|
-
cases.map {
|
|
570
|
+
cases.map {self.emitCase(["_1"], _, [], [], True, last, async)}.join("\n") +
|
|
565
571
|
"\n}" + if(!last) {" while(false)"}.else {""}
|
|
566
572
|
| _ =>
|
|
567
573
|
detectIfElse(term).{
|
|
@@ -594,16 +600,16 @@ extend self: JsEmitter {
|
|
|
594
600
|
let arguments = ["_exception.value_", "_error"]
|
|
595
601
|
cases.{
|
|
596
602
|
| [case] =>
|
|
597
|
-
self.emitCase(arguments, case, False, last, catchAsync)
|
|
603
|
+
self.emitCase(arguments, case, [], [], False, last, catchAsync)
|
|
598
604
|
| cs =>
|
|
599
605
|
let caseStrings =
|
|
600
|
-
cases.map {
|
|
606
|
+
cases.map {self.emitCase(arguments, _, [], [], True, last, catchAsync)}
|
|
601
607
|
if(last) {caseStrings.join("\n")} else {"do {\n" + caseStrings.join("\n") + "\n} while(false)"}
|
|
602
608
|
}
|
|
603
609
|
}
|
|
604
610
|
term.{
|
|
605
|
-
| ECall(
|
|
606
|
-
Argument(_, _, ECall(
|
|
611
|
+
| ECall(_, StaticCall("ff:core/Try.Try_finally", _, _), _, _, [
|
|
612
|
+
Argument(_, _, ECall(_, StaticCall("ff:core/Core.try", _, _), _, _, [
|
|
607
613
|
Argument(_, _, ELambda(_, Lambda(_, tryEffect, [MatchCase(_, [], [], tryBody)])))
|
|
608
614
|
], _))
|
|
609
615
|
Argument(_, _, ELambda(_, Lambda(_, finallyEffect, [MatchCase(_, [], [], finallyBody)])))
|
|
@@ -614,8 +620,8 @@ extend self: JsEmitter {
|
|
|
614
620
|
"try {\n" + self.emitStatements(tryBody, last, tryAsync) +
|
|
615
621
|
"\n} finally {\n" + self.emitStatements(finallyBody, last, finallyAsync) + "\n}"
|
|
616
622
|
)
|
|
617
|
-
| ECall(
|
|
618
|
-
Argument(_, _, ECall(
|
|
623
|
+
| ECall(_, StaticCall("ff:core/Try.Try_catch", _, _), _, _, [
|
|
624
|
+
Argument(_, _, ECall(_, StaticCall("ff:core/Core.try", _, _), _, _, [
|
|
619
625
|
Argument(_, _, ELambda(_, Lambda(_, tryEffect, [MatchCase(_, [], [], tryBody)])))
|
|
620
626
|
], _))
|
|
621
627
|
Argument(_, _, ELambda(_, Lambda(_, catchEffect, cases)))
|
|
@@ -631,9 +637,9 @@ extend self: JsEmitter {
|
|
|
631
637
|
emitCatch(catchEffect, cases) +
|
|
632
638
|
"\n}"
|
|
633
639
|
)
|
|
634
|
-
| ECall(
|
|
635
|
-
Argument(_, _, ECall(
|
|
636
|
-
Argument(_, _, ECall(
|
|
640
|
+
| ECall(_, StaticCall("ff:core/Try.Try_finally", _, _), _, _, [
|
|
641
|
+
Argument(_, _, ECall(_, StaticCall("ff:core/Try.Try_catch", _, _), _, _, [
|
|
642
|
+
Argument(_, _, ECall(_, StaticCall("ff:core/Core.try", _, _), _, _, [
|
|
637
643
|
Argument(_, _, ELambda(_, Lambda(_, tryEffect, [MatchCase(_, [], [], tryBody)])))
|
|
638
644
|
], _))
|
|
639
645
|
Argument(_, _, ELambda(_, Lambda(_, catchEffect, cases)))
|
|
@@ -657,7 +663,23 @@ extend self: JsEmitter {
|
|
|
657
663
|
}
|
|
658
664
|
}
|
|
659
665
|
|
|
660
|
-
emitCase(
|
|
666
|
+
emitCase(
|
|
667
|
+
arguments: List[String]
|
|
668
|
+
matchCase: MatchCase
|
|
669
|
+
conditions: List[String]
|
|
670
|
+
variables: List[String]
|
|
671
|
+
jump: Bool
|
|
672
|
+
last: Bool
|
|
673
|
+
async: Bool
|
|
674
|
+
): String {
|
|
675
|
+
function emitWrapper(code: String): String {
|
|
676
|
+
if(conditions.isEmpty()) {"{\n"} else {
|
|
677
|
+
"if(" + conditions.join(" && ") + ") {\n"
|
|
678
|
+
} +
|
|
679
|
+
variables.join() +
|
|
680
|
+
code +
|
|
681
|
+
"\n}"
|
|
682
|
+
}
|
|
661
683
|
Pair(matchCase.patterns, matchCase.guards).{
|
|
662
684
|
| Pair([p, ...ps], _) =>
|
|
663
685
|
self.emitPattern(
|
|
@@ -665,18 +687,45 @@ extend self: JsEmitter {
|
|
|
665
687
|
p
|
|
666
688
|
arguments.dropFirst()
|
|
667
689
|
matchCase.MatchCase(patterns = ps)
|
|
690
|
+
conditions
|
|
691
|
+
variables
|
|
668
692
|
jump
|
|
669
693
|
last
|
|
670
694
|
async
|
|
671
695
|
)
|
|
696
|
+
| Pair([], [MatchGuard(_, e, PVariant(_, "ff:core/Bool.True", _))]) {variables.isEmpty()} =>
|
|
697
|
+
let newCase = matchCase.MatchCase(patterns = [], guards = [])
|
|
698
|
+
self.emitCase([], newCase, [...conditions, self.emitTerm(e, async)], [], jump, last, async)
|
|
699
|
+
| Pair([], [MatchGuard(_, e, PVariant(_, "ff:core/Bool.True", _))]) =>
|
|
700
|
+
let newCase = matchCase.MatchCase(patterns = [], guards = [])
|
|
701
|
+
let code = self.emitCase([], newCase, [self.emitTerm(e, async)], [], jump, last, async)
|
|
702
|
+
emitWrapper(code)
|
|
672
703
|
| Pair([], [guard, ...guards]) =>
|
|
673
704
|
let guardName = "_guard" + (guards.size() + 1)
|
|
674
705
|
let newCase = matchCase.MatchCase(patterns = [guard.pattern], guards = guards)
|
|
675
|
-
|
|
676
|
-
|
|
706
|
+
let code =
|
|
707
|
+
"const " + guardName + " = " + self.emitTerm(guard.term, async) + ";\n" +
|
|
708
|
+
self.emitCase([guardName], newCase, [], [], jump, last, async)
|
|
709
|
+
emitWrapper(code)
|
|
677
710
|
| Pair([], []) =>
|
|
678
|
-
self.emitStatements(matchCase.body, last, async)
|
|
679
|
-
|
|
711
|
+
let statementsCode = self.emitStatements(matchCase.body, last, async)
|
|
712
|
+
let lastLine = statementsCode.reverse().takeWhile {_ != '\n'}.reverse()
|
|
713
|
+
let returns =
|
|
714
|
+
lastLine.startsWith("return ") ||
|
|
715
|
+
lastLine.startsWith("break ") ||
|
|
716
|
+
lastLine.startsWith("continue ") ||
|
|
717
|
+
lastLine.startsWith("return;") ||
|
|
718
|
+
lastLine.startsWith("break;") ||
|
|
719
|
+
lastLine.startsWith("continue;") ||
|
|
720
|
+
lastLine.startsWith("throw ")
|
|
721
|
+
let code = statementsCode + if(jump && last && !returns) {
|
|
722
|
+
"\nreturn"
|
|
723
|
+
} elseIf {jump && !returns} {
|
|
724
|
+
"\nbreak"
|
|
725
|
+
} else {
|
|
726
|
+
""
|
|
727
|
+
}
|
|
728
|
+
emitWrapper(code)
|
|
680
729
|
}
|
|
681
730
|
}
|
|
682
731
|
|
|
@@ -685,81 +734,78 @@ extend self: JsEmitter {
|
|
|
685
734
|
pattern: MatchPattern
|
|
686
735
|
arguments: List[String]
|
|
687
736
|
matchCase: MatchCase
|
|
737
|
+
conditions: List[String]
|
|
738
|
+
variables: List[String]
|
|
688
739
|
jump: Bool
|
|
689
740
|
last: Bool
|
|
690
741
|
async: Bool
|
|
691
742
|
): String {
|
|
692
743
|
pattern.{
|
|
693
744
|
| PString(_, value) =>
|
|
694
|
-
|
|
695
|
-
self.emitCase(arguments, matchCase, jump, last, async)
|
|
696
|
-
"\n}"
|
|
745
|
+
let newConditions = [...conditions, argument + " === " + value]
|
|
746
|
+
self.emitCase(arguments, matchCase, newConditions, variables, jump, last, async)
|
|
697
747
|
| PInt(_, value) =>
|
|
698
|
-
|
|
699
|
-
self.emitCase(arguments, matchCase, jump, last, async)
|
|
700
|
-
"\n}"
|
|
748
|
+
let newConditions = [...conditions, argument + " === " + value]
|
|
749
|
+
self.emitCase(arguments, matchCase, newConditions, variables, jump, last, async)
|
|
701
750
|
| PChar(_, value) =>
|
|
702
|
-
|
|
703
|
-
self.emitCase(arguments, matchCase, jump, last, async)
|
|
704
|
-
"\n}"
|
|
751
|
+
let newConditions = [...conditions, argument + " === " + charLiteralToNumber(value)]
|
|
752
|
+
self.emitCase(arguments, matchCase, newConditions, variables, jump, last, async)
|
|
705
753
|
| PVariable(_, None) =>
|
|
706
|
-
self.emitCase(arguments, matchCase, jump, last, async)
|
|
754
|
+
self.emitCase(arguments, matchCase, conditions, variables, jump, last, async)
|
|
707
755
|
| PVariable(_, Some(name)) =>
|
|
708
756
|
let escaped = escapeKeyword(name)
|
|
709
|
-
if(escaped != argument) {
|
|
710
|
-
|
|
757
|
+
let newVariables = if(escaped != argument) {
|
|
758
|
+
[...variables, "const " + escaped + " = " + argument + ";\n"]
|
|
759
|
+
} else {variables}
|
|
760
|
+
self.emitCase(arguments, matchCase, conditions, newVariables, jump, last, async)
|
|
711
761
|
| PVariant(_, "ff:core/Bool.False", []) =>
|
|
712
|
-
"
|
|
713
|
-
self.emitCase(arguments, matchCase, jump, last, async) +
|
|
714
|
-
"\n}"
|
|
762
|
+
self.emitCase(arguments, matchCase, [...conditions, "!" + argument], variables, jump, last, async)
|
|
715
763
|
| PVariant(_, "ff:core/Bool.True", []) =>
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
self.emitCase(arguments, matchCase, jump, last, async) +
|
|
728
|
-
"\n}"
|
|
729
|
-
| PVariant(_, "List$Link", [head, tail]) =>
|
|
730
|
-
mutable shortArgument = argument
|
|
731
|
-
mutable shortCount = 0
|
|
732
|
-
while {shortArgument.endsWith(".slice(1)")} {
|
|
733
|
-
shortArgument = shortArgument.dropLast(".slice(1)".size())
|
|
734
|
-
shortCount += 1
|
|
764
|
+
self.emitCase(arguments, matchCase, [...conditions, argument], variables, jump, last, async)
|
|
765
|
+
| PVariant(_, emptyOrLink, _) {emptyOrLink == "List$Empty" || emptyOrLink == "List$Link"} =>
|
|
766
|
+
mutable restPattern = None
|
|
767
|
+
function listPatterns(matchPattern: MatchPattern): List[MatchPattern] {
|
|
768
|
+
| PVariant(_, "List$Empty", []) =>
|
|
769
|
+
[]
|
|
770
|
+
| PVariant(_, "List$Link", [head, tail]) =>
|
|
771
|
+
[head, ...listPatterns(tail)]
|
|
772
|
+
| p =>
|
|
773
|
+
restPattern = Some(p)
|
|
774
|
+
[]
|
|
735
775
|
}
|
|
736
|
-
let
|
|
737
|
-
let
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
776
|
+
let patterns = listPatterns(pattern)
|
|
777
|
+
let itemArguments = patterns.pairs().map {| Pair(i, _) => argument + "[" + i + "]"}
|
|
778
|
+
let restArgument = restPattern.map {_ => argument + ".slice(" + patterns.size() + ")"}
|
|
779
|
+
let newArguments = [...itemArguments, ...restArgument.toList(), ...arguments]
|
|
780
|
+
let newMatchCase = matchCase.MatchCase(
|
|
781
|
+
patterns = [...patterns, ...restPattern.toList(), ...matchCase.patterns]
|
|
782
|
+
)
|
|
783
|
+
let operator = restPattern.map {_ => ">="}.else {"==="}
|
|
784
|
+
let newConditions = [...conditions, argument + ".length " + operator + " " + patterns.size()]
|
|
785
|
+
self.emitCase(newArguments, newMatchCase, newConditions, variables, jump, last, async)
|
|
741
786
|
| PVariant(_, name, patterns) =>
|
|
742
787
|
let processed = self.processVariantCase(name, argument)
|
|
743
788
|
let newMatchCase = matchCase.MatchCase(patterns = [...patterns, ...matchCase.patterns])
|
|
744
|
-
if(processed.loneVariant) {
|
|
745
|
-
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
|
|
789
|
+
let newConditions = if(processed.loneVariant) {conditions} else {
|
|
790
|
+
[...conditions, argument + "." + processed.variantName]
|
|
791
|
+
}
|
|
792
|
+
let newArguments = [...processed.arguments, ...arguments]
|
|
793
|
+
self.emitCase(newArguments, newMatchCase, newConditions, variables, jump, last, async)
|
|
749
794
|
| PVariantAs(at, name, variableAt, variable) =>
|
|
750
795
|
let processed = self.processVariantCase(name, argument)
|
|
751
|
-
if(processed.loneVariant) {
|
|
752
|
-
|
|
753
|
-
}
|
|
754
|
-
variable.map(escapeKeyword).filter {_ != argument}.map {
|
|
755
|
-
"const " + _ + " = " + argument + ";\n"
|
|
756
|
-
}.else {
|
|
757
|
-
self.emitCase(arguments, matchCase, jump, last, async)
|
|
758
|
-
if(processed.loneVariant) {""} else {"\n}"}
|
|
796
|
+
let newConditions = if(processed.loneVariant) {conditions} else {
|
|
797
|
+
[...conditions, argument + "." + processed.variantName]
|
|
798
|
+
}
|
|
799
|
+
let newVariables = variable.map(escapeKeyword).filter {_ != argument}.map {
|
|
800
|
+
[...variables, "const " + _ + " = " + argument + ";\n"]
|
|
801
|
+
}.else {[]}
|
|
802
|
+
self.emitCase(arguments, matchCase, newConditions, newVariables, jump, last, async)
|
|
759
803
|
| PAlias(_, pattern, variable) =>
|
|
760
804
|
let escaped = escapeKeyword(variable)
|
|
761
|
-
if(escaped != argument) {
|
|
762
|
-
|
|
805
|
+
let newVariables = if(escaped != argument) {
|
|
806
|
+
[...variables, "const " + escaped + " = " + argument + ";\n"]
|
|
807
|
+
} else {variables}
|
|
808
|
+
self.emitPattern(argument, pattern, arguments, matchCase, conditions, newVariables, jump, last, async)
|
|
763
809
|
}
|
|
764
810
|
}
|
|
765
811
|
|
|
@@ -771,8 +817,6 @@ extend self: JsEmitter {
|
|
|
771
817
|
}
|
|
772
818
|
|
|
773
819
|
processVariantCase(name: String, argument: String): ProcessedVariantCase {
|
|
774
|
-
if(name == "List$Empty") {ProcessedVariantCase(name, False, False, [])} else:
|
|
775
|
-
if(name == "List$Link") {ProcessedVariantCase(name, False, False, [argument + "[0]", argument + ".slice(1)"])} else:
|
|
776
820
|
let variantNameUnqualified = name.reverse().takeWhile {_ != '.'}.reverse()
|
|
777
821
|
let variantName = escapeKeyword(variantNameUnqualified)
|
|
778
822
|
let moduleName = name.dropLast(variantNameUnqualified.size() + 1)
|
|
@@ -855,9 +899,9 @@ extractTypeName(type: Type): String {
|
|
|
855
899
|
|
|
856
900
|
firstTypeName(types: List[Type]): String {
|
|
857
901
|
types.grabFirst().{
|
|
858
|
-
| TConstructor t => t
|
|
902
|
+
| TConstructor t => t.name
|
|
859
903
|
| TVariable t => fail(t.at, " is still a unification variable")
|
|
860
|
-
}
|
|
904
|
+
}
|
|
861
905
|
}
|
|
862
906
|
|
|
863
907
|
makeDictionaryName(traitName: String, typeName: String): String {
|
package/compiler/LspHook.ff
CHANGED
|
@@ -96,6 +96,7 @@ class ResultHook {
|
|
|
96
96
|
ResolveSymbolHook(
|
|
97
97
|
symbol: SymbolHook
|
|
98
98
|
annotation: Option[Type]
|
|
99
|
+
topLevel: Bool
|
|
99
100
|
)
|
|
100
101
|
ResolveTypeHook(
|
|
101
102
|
types: Map[String, String]
|
|
@@ -110,6 +111,7 @@ class ResultHook {
|
|
|
110
111
|
ResolveSignatureHook(
|
|
111
112
|
signature: Signature
|
|
112
113
|
isInstanceMethod: Bool
|
|
114
|
+
topLevel: Bool
|
|
113
115
|
)
|
|
114
116
|
ResolveVariantFieldHook(
|
|
115
117
|
symbol: SymbolHook
|
|
@@ -171,6 +173,7 @@ class ResultHook {
|
|
|
171
173
|
instantiated: Box[Option[Instantiated]]
|
|
172
174
|
)
|
|
173
175
|
InferRecordFieldHook(
|
|
176
|
+
usageAt: Location
|
|
174
177
|
unification: Unification
|
|
175
178
|
environment: Environment
|
|
176
179
|
expected: Type
|
|
@@ -186,15 +189,15 @@ showHook(hook: ResultHook): String {
|
|
|
186
189
|
| InferLookupHook(unification, environment, expected, selfVariable, symbol, instantiated) => "InferLookupHook(...)"
|
|
187
190
|
| InferParameterHook(unification, environment, parameter, missing) => "InferParameterHook(...)"
|
|
188
191
|
| InferPatternHook(unification, environment, expected, pattern) => "InferPatternHook(...)"
|
|
189
|
-
| InferRecordFieldHook(unification, environment, expected, recordType, fieldName) => "InferRecordFieldHook(...)"
|
|
192
|
+
| InferRecordFieldHook(usageAt, unification, environment, expected, recordType, fieldName) => "InferRecordFieldHook(...)"
|
|
190
193
|
| InferSequentialStartHook(unification, term, missing) => "InferSequentialStartHook(...)"
|
|
191
194
|
| InferTermHook(unification, environment, expected, term, recordType, missing) => "InferTermHook(...)"
|
|
192
195
|
| ParseArgumentHook(callAt, argumentIndex, parameterName) => "ParseArgumentHook(...)"
|
|
193
196
|
| ParseSymbolBegin => "ParseSymbolBegin(...)"
|
|
194
197
|
| ParseSymbolEnd(name, kind, selectionStart, selectionEnd, start, end) => "ParseSymbolEnd(...)"
|
|
195
198
|
| ResolveConstraintHook(symbol, constrant) => "ResolveConstraintHook(...)"
|
|
196
|
-
| ResolveSignatureHook(signature, _) => "ResolveSignatureHook(...)"
|
|
197
|
-
| ResolveSymbolHook(symbol, annotation) => "ResolveSymbolHook(...)"
|
|
199
|
+
| ResolveSignatureHook(signature, _, _) => "ResolveSignatureHook(...)"
|
|
200
|
+
| ResolveSymbolHook(symbol, annotation, _) => "ResolveSymbolHook(...)"
|
|
198
201
|
| ResolveTypeHook(types, typeGenerics, symbol, explicitType) => "ResolveTypeHook(...)"
|
|
199
202
|
| ResolveVariantFieldHook(symbol, type, commonField) => "ResolveVariantFieldHook(...)"
|
|
200
203
|
}
|
package/compiler/Main.ff
CHANGED
|
@@ -63,7 +63,10 @@ main(system: NodeSystem): Unit {
|
|
|
63
63
|
prepareFireflyDirectory(system.path("."))
|
|
64
64
|
let localMainFile = system.path(mainFile).base()
|
|
65
65
|
buildScript(localMainFile, resolvedDependencies.mainPackagePair, EmitNode, resolvedDependencies)
|
|
66
|
-
importAndRun(fireflyPath, "node", resolvedDependencies.mainPackagePair, localMainFile, arguments)
|
|
66
|
+
if(!importAndRun(fireflyPath, "node", resolvedDependencies.mainPackagePair, localMainFile, arguments)) {
|
|
67
|
+
let at = Location(system.path(mainFile + ".ff").absolute(), 1, 1)
|
|
68
|
+
throw(CompileError(at, "This module does not contain a 'nodeMain' function"))
|
|
69
|
+
}
|
|
67
70
|
|
|
68
71
|
| BrowserCommand(mainFile) =>
|
|
69
72
|
let resolvedDependencies = Dependencies.process(system.httpClient(), system.path(mainFile + ".ff"))
|
|
@@ -82,8 +85,9 @@ main(system: NodeSystem): Unit {
|
|
|
82
85
|
importAndRun(fireflyPath, "build", resolvedDependencies.mainPackagePair, localMainFile, [])
|
|
83
86
|
|
|
84
87
|
| CheckCommand(filePath) =>
|
|
85
|
-
Builder.check(system, fireflyPath, system.path(filePath), Map.empty(), LspHook.disabled(), True)
|
|
86
|
-
|
|
88
|
+
let errors = Builder.check(system, fireflyPath, system.path(filePath), None, Map.empty(), LspHook.disabled(), True)
|
|
89
|
+
if(!errors.isEmpty()) {throw(CompileErrors(errors.distinct()))}
|
|
90
|
+
|
|
87
91
|
| BootstrapCommand =>
|
|
88
92
|
let workingDirectory = system.path(".")
|
|
89
93
|
Builder.build(
|
|
@@ -110,11 +114,16 @@ main(system: NodeSystem): Unit {
|
|
|
110
114
|
try {
|
|
111
115
|
let command = parseCommandLine(system.arguments())
|
|
112
116
|
runCommand(command)
|
|
113
|
-
} catch {| CommandLineError(message),
|
|
117
|
+
} catch {| CommandLineError(message), _ =>
|
|
114
118
|
Log.debug(message)
|
|
115
|
-
} catch {| CompileError(at, message),
|
|
119
|
+
} catch {| CompileError(at, message), _ =>
|
|
116
120
|
Log.debug(message)
|
|
117
121
|
Log.debug(" at " + at.file.replace("./", "") + ":" + at.line + ":" + at.column)
|
|
122
|
+
} catch {| CompileErrors(errors), _ =>
|
|
123
|
+
errors.map {| CompileError(at, message) =>
|
|
124
|
+
Log.debug(message)
|
|
125
|
+
Log.debug(" at " + at.file.replace("./", "") + ":" + at.line + ":" + at.column)
|
|
126
|
+
}
|
|
118
127
|
} grab()
|
|
119
128
|
}
|
|
120
129
|
|
|
@@ -164,13 +173,13 @@ parseCommandLine(arguments: List[String]): MainCommand {
|
|
|
164
173
|
}
|
|
165
174
|
| ["check", ...checkArguments] =>
|
|
166
175
|
checkArguments.{
|
|
167
|
-
| [fileName]
|
|
176
|
+
| [fileName] =>
|
|
168
177
|
CheckCommand(fileName)
|
|
169
178
|
| [_, _, ...] => throw(CommandLineError(
|
|
170
179
|
"You must only specify a single argument to check." + usageString
|
|
171
180
|
))
|
|
172
|
-
|
|
|
173
|
-
"You must specify a Firefly file (.ff) as the argument to
|
|
181
|
+
| [] => throw(CommandLineError(
|
|
182
|
+
"You must specify a Firefly file (.ff) or directory as the argument to check." + usageString
|
|
174
183
|
))
|
|
175
184
|
}
|
|
176
185
|
| ["bootstrap", _] =>
|
|
@@ -206,14 +215,19 @@ importAndRun(
|
|
|
206
215
|
packagePair: PackagePair
|
|
207
216
|
mainFile: String
|
|
208
217
|
arguments: List[String]
|
|
209
|
-
):
|
|
218
|
+
): Bool
|
|
210
219
|
target node async """
|
|
211
220
|
const process = await import('process');
|
|
212
221
|
const cwd = process.cwd();
|
|
213
222
|
const workingDirectory = cwd.indexOf(':') == 1 ? 'file:///' + cwd : cwd;
|
|
214
223
|
const packagePath = packagePair_.group_ + "/" + packagePair_.name_
|
|
215
224
|
const main = await import(workingDirectory + "/.firefly/output/" + target_ + "/" + packagePath + "/" + mainFile_ + ".mjs");
|
|
216
|
-
|
|
225
|
+
if(typeof main.$run$ !== 'undefined') {
|
|
226
|
+
await main.$run$(fireflyPath_, arguments_);
|
|
227
|
+
return true;
|
|
228
|
+
} else {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
217
231
|
"""
|
|
218
232
|
|
|
219
233
|
prepareFireflyDirectory(path: Path) {
|
package/compiler/Patterns.ff
CHANGED
|
@@ -72,7 +72,7 @@ convert(modules: Map[String, Module], cases: List[MatchCase]): List[PatternCaseI
|
|
|
72
72
|
None
|
|
73
73
|
| PVariant p =>
|
|
74
74
|
let fields = p.patterns.map(convertPattern).pairs().collect {
|
|
75
|
-
| Pair(i, Some(
|
|
75
|
+
| Pair(i, Some(info)) => Some(Pair("" + i, info))
|
|
76
76
|
| _ => None
|
|
77
77
|
}
|
|
78
78
|
Some(PatternInfo(unqualifiedName(p.name), otherVariants(p.name), fields))
|