firefly-compiler 0.4.21 → 0.4.23
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/Dictionaries.ff +10 -10
- package/compiler/Inference.ff +167 -148
- package/compiler/JsEmitter.ff +2 -2
- package/compiler/LspHook.ff +2 -1
- package/compiler/Main.ff +12 -4
- package/compiler/Patterns.ff +1 -1
- package/compiler/Resolver.ff +154 -146
- package/compiler/Substitution.ff +2 -2
- package/compiler/Unification.ff +1 -1
- package/core/Map.ff +8 -0
- package/core/Set.ff +7 -0
- package/lsp/Handler.ff +11 -3
- package/output/js/ff/compiler/Dictionaries.mjs +18 -18
- package/output/js/ff/compiler/Inference.mjs +182 -88
- package/output/js/ff/compiler/JsEmitter.mjs +8 -6
- package/output/js/ff/compiler/LspHook.mjs +4 -2
- package/output/js/ff/compiler/Main.mjs +16 -5
- package/output/js/ff/compiler/Patterns.mjs +4 -4
- package/output/js/ff/compiler/Resolver.mjs +372 -202
- package/output/js/ff/compiler/Substitution.mjs +4 -4
- package/output/js/ff/compiler/Unification.mjs +4 -4
- package/output/js/ff/core/Map.mjs +26 -0
- package/output/js/ff/core/Set.mjs +16 -0
- package/package.json +1 -1
- package/vscode/package.json +1 -1
- package/bin/firefly.mjs +0 -2
- package/guide/Main.ff +0 -22
package/compiler/Dictionaries.ff
CHANGED
|
@@ -168,18 +168,18 @@ extend self: Dictionaries {
|
|
|
168
168
|
): Dictionary {
|
|
169
169
|
let instantiationMap = typeParameters.zip(typeArguments).toMap()
|
|
170
170
|
let unification = Unification.make([], False)
|
|
171
|
-
let newGenerics = constraint.generics.map {
|
|
172
|
-
|
|
173
|
-
| TConstructor
|
|
171
|
+
let newGenerics = constraint.generics.map {unification.instantiate(instantiationMap, _)}
|
|
172
|
+
newGenerics.grabFirst().{
|
|
173
|
+
| TConstructor firstType =>
|
|
174
|
+
let instance = self.instances.get(InstanceKey(constraint.name, firstType.name)).else {
|
|
175
|
+
throw(CompileError(at, "Missing instance " + firstType.name + ": " + constraint.name))
|
|
176
|
+
}
|
|
177
|
+
let dictionaries = instance.constraints.map {c =>
|
|
178
|
+
self.makeDictionary(at, instance.generics, firstType.generics, c)
|
|
179
|
+
}
|
|
180
|
+
Dictionary(instance.packagePair, instance.moduleName, constraint.name, firstType.name, dictionaries)
|
|
174
181
|
| TVariable t => fail(t.at, " is still a unification variable")
|
|
175
182
|
}
|
|
176
|
-
let instance = self.instances.get(InstanceKey(constraint.name, firstType.name)).else {
|
|
177
|
-
throw(CompileError(at, "Missing instance " + firstType.name + ": " + constraint.name))
|
|
178
|
-
}
|
|
179
|
-
let dictionaries = instance.constraints.map { c =>
|
|
180
|
-
self.makeDictionary(at, instance.generics, firstType.generics, c)
|
|
181
|
-
}
|
|
182
|
-
Dictionary(instance.packagePair, instance.moduleName, constraint.name, firstType.name, dictionaries)
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
}
|
package/compiler/Inference.ff
CHANGED
|
@@ -298,8 +298,11 @@ extend self: Inference {
|
|
|
298
298
|
}
|
|
299
299
|
self.unification.unify(at, expected, instantiated.scheme.signature.returnType)
|
|
300
300
|
let parameters = instantiated.scheme.signature.parameters.sortBy {_.name}
|
|
301
|
-
let
|
|
302
|
-
TConstructor
|
|
301
|
+
let paramtersWithFieldAt = parameters.map {p => p.valueType.{
|
|
302
|
+
| TConstructor t => t.TConstructor(at = p.at)
|
|
303
|
+
| TVariable t => t.TVariable(at = p.at)
|
|
304
|
+
}}
|
|
305
|
+
let recordType = TConstructor(at, "Record$" + parameters.map {_.name}.join("$"), paramtersWithFieldAt)
|
|
303
306
|
variableOption.toList().map {Pair(_, Pair(variableAt, recordType))}.toMap()
|
|
304
307
|
| PVariant(at, "List$Empty", []) =>
|
|
305
308
|
let itemType = self.unification.freshUnificationVariable(at)
|
|
@@ -371,14 +374,18 @@ extend self: Inference {
|
|
|
371
374
|
let record = self.inferTerm(environment, recordType, e.record)
|
|
372
375
|
self.unification.substitute(recordType).{
|
|
373
376
|
| TConstructor(_, name, typeArguments)@t {name.startsWith("Record$")} =>
|
|
374
|
-
if(self.lspHook.isAt(e.at)) {
|
|
375
|
-
let symbolHook = SymbolHook(e.field, e.at, e.at)
|
|
376
|
-
let noEffect = self.unification.freshUnificationVariable(e.at)
|
|
377
|
-
self.lspHook.emit(
|
|
378
|
-
InferRecordFieldHook(self.unification, environment, expected, t, e.field)
|
|
379
|
-
)
|
|
380
|
-
}
|
|
381
377
|
let fieldNames = name.split('$').dropFirst(1)
|
|
378
|
+
if(self.lspHook.isEnabled()) {
|
|
379
|
+
fieldNames.zip(typeArguments).each {| Pair(fieldName, fieldType) =>
|
|
380
|
+
if(e.field == fieldName):
|
|
381
|
+
let definedAt = self.unification.substitute(fieldType).at
|
|
382
|
+
if(self.lspHook.isAt(e.at) || self.lspHook.isDefinedAt(definedAt)) {
|
|
383
|
+
self.lspHook.emit(
|
|
384
|
+
InferRecordFieldHook(e.at, self.unification, environment, expected, t, e.field)
|
|
385
|
+
)
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
382
389
|
fieldNames.pairs().find {_.second == e.field}.map {_.first}.map {index =>
|
|
383
390
|
let t1 = typeArguments.grab(index)
|
|
384
391
|
self.unification.unify(e.at, expected, t1)
|
|
@@ -568,7 +575,7 @@ extend self: Inference {
|
|
|
568
575
|
| ECall e =>
|
|
569
576
|
if((self.lspHook.isEnabled()) && e.target.{| StaticCall _ => True | _ => False}) {term} else:
|
|
570
577
|
let call = e.target.{
|
|
571
|
-
| DynamicCall call => call
|
|
578
|
+
| DynamicCall call => (function = call.function, tailCall = call.tailCall)
|
|
572
579
|
| StaticCall _ => fail(e.at, "Internal error: Static calls not expected in the Inference phase")
|
|
573
580
|
}
|
|
574
581
|
call.function.{
|
|
@@ -747,23 +754,26 @@ extend self: Inference {
|
|
|
747
754
|
recordType: Type
|
|
748
755
|
name: String
|
|
749
756
|
): Term {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
757
|
+
term.{
|
|
758
|
+
| ECall e =>
|
|
759
|
+
let tailCall = e.target.{
|
|
760
|
+
| DynamicCall call => call.tailCall
|
|
761
|
+
| StaticCall _ => fail(e.at, "Internal error: Static calls not expected in inferMethodCall")
|
|
762
|
+
}
|
|
763
|
+
let selfParameter = signature.parameters.grabFirst()
|
|
764
|
+
let selfArgument = Argument(record.at, Some(selfParameter.name), record) // Be careful not to infer again
|
|
765
|
+
self.unification.unify(term.at, expected, signature.returnType)
|
|
766
|
+
self.unification.unify(term.at, selfParameter.valueType, recordType)
|
|
767
|
+
let arguments = self.inferArguments(term.at, name, environment, signature.parameters.dropFirst(), e.arguments)
|
|
768
|
+
self.unification.affect(term.at, signature.effect, environment.effect)
|
|
769
|
+
e.ECall(
|
|
770
|
+
target = StaticCall(name, instanceCall = False, tailCall = tailCall)
|
|
771
|
+
typeArguments = instantiation.map {_.second}
|
|
772
|
+
arguments = [selfArgument, ...arguments]
|
|
773
|
+
effect = signature.effect
|
|
774
|
+
)
|
|
775
|
+
| _ => fail(term.at, "Call expected")
|
|
754
776
|
}
|
|
755
|
-
let selfParameter = signature.parameters.grabFirst()
|
|
756
|
-
let selfArgument = Argument(record.at, Some(selfParameter.name), record) // Be careful not to infer again
|
|
757
|
-
self.unification.unify(term.at, expected, signature.returnType)
|
|
758
|
-
self.unification.unify(term.at, selfParameter.valueType, recordType)
|
|
759
|
-
let arguments = self.inferArguments(term.at, name, environment, signature.parameters.dropFirst(), e.arguments)
|
|
760
|
-
self.unification.affect(term.at, signature.effect, environment.effect)
|
|
761
|
-
e.ECall(
|
|
762
|
-
target = StaticCall(name, instanceCall = False, tailCall = call.tailCall)
|
|
763
|
-
typeArguments = instantiation.map {_.second}
|
|
764
|
-
arguments = [selfArgument, ...arguments]
|
|
765
|
-
effect = signature.effect
|
|
766
|
-
)
|
|
767
777
|
}
|
|
768
778
|
|
|
769
779
|
inferFunctionCall(
|
|
@@ -775,139 +785,148 @@ extend self: Inference {
|
|
|
775
785
|
term: Term
|
|
776
786
|
name: String
|
|
777
787
|
): Term {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
788
|
+
term.{
|
|
789
|
+
| ECall e =>
|
|
790
|
+
let tailCall = e.target.{
|
|
791
|
+
| DynamicCall call => call.tailCall
|
|
792
|
+
| StaticCall _ => fail(e.at, "Internal error: Static calls not expected in inferFunctionCall")
|
|
793
|
+
}
|
|
794
|
+
self.unification.unify(e.at, expected, signature.returnType)
|
|
795
|
+
let arguments = self.inferArguments(e.at, name, environment, signature.parameters, e.arguments)
|
|
796
|
+
self.unification.affect(term.at, signature.effect, environment.effect)
|
|
797
|
+
e.ECall(
|
|
798
|
+
target = StaticCall(name, instanceCall = instanceCall, tailCall = tailCall)
|
|
799
|
+
typeArguments = instantiation.map {_.second}
|
|
800
|
+
arguments = arguments
|
|
801
|
+
effect = signature.effect
|
|
802
|
+
)
|
|
803
|
+
| _ => fail(term.at, "Call expected")
|
|
782
804
|
}
|
|
783
|
-
self.unification.unify(e.at, expected, signature.returnType)
|
|
784
|
-
let arguments = self.inferArguments(e.at, name, environment, signature.parameters, e.arguments)
|
|
785
|
-
self.unification.affect(term.at, signature.effect, environment.effect)
|
|
786
|
-
e.ECall(
|
|
787
|
-
target = StaticCall(name, instanceCall = instanceCall, tailCall = call.tailCall)
|
|
788
|
-
typeArguments = instantiation.map {_.second}
|
|
789
|
-
arguments = arguments
|
|
790
|
-
effect = signature.effect
|
|
791
|
-
)
|
|
792
805
|
}
|
|
793
806
|
|
|
794
807
|
inferLambdaCall(environment: Environment, expected: Type, term: Term): Term {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
808
|
+
term.{
|
|
809
|
+
| ECall e =>
|
|
810
|
+
let call = e.target.{
|
|
811
|
+
| DynamicCall call {!call.tailCall} => (function = call.function, tailCall = call.tailCall)
|
|
812
|
+
| DynamicCall _ => throw(CompileError(e.at, "Tailcalls not supported on lambda functions"))
|
|
813
|
+
| StaticCall _ => fail(e.at, "Internal error: Static calls not expected in inferLambdaCall")
|
|
814
|
+
}
|
|
815
|
+
let effect = self.unification.freshUnificationVariable(term.at)
|
|
816
|
+
let argumentTypes = e.arguments.map {self.unification.freshUnificationVariable(_.at)}
|
|
817
|
+
let functionType = TConstructor(e.at, "Function$" + e.arguments.size(), [
|
|
818
|
+
effect
|
|
819
|
+
...argumentTypes
|
|
820
|
+
expected
|
|
821
|
+
])
|
|
822
|
+
let function = self.inferTerm(environment, functionType, call.function)
|
|
823
|
+
let arguments = e.arguments.zip(argumentTypes).map {| Pair(argument, t) =>
|
|
824
|
+
argument.name.each {name =>
|
|
825
|
+
throw(CompileError(argument.at, "Named argument not allowed here: " + name))
|
|
826
|
+
}
|
|
827
|
+
argument.Argument(value = self.inferTerm(environment, t, argument.value))
|
|
828
|
+
}
|
|
829
|
+
e.typeArguments.first().each {typeArgument =>
|
|
830
|
+
throw(CompileError(typeArgument.at, "Type arguments not allowed here"))
|
|
831
|
+
}
|
|
832
|
+
self.unification.affect(term.at, effect, environment.effect)
|
|
833
|
+
e.ECall(
|
|
834
|
+
target = call.DynamicCall(function = function)
|
|
835
|
+
typeArguments = []
|
|
836
|
+
arguments = arguments
|
|
837
|
+
effect = effect
|
|
838
|
+
)
|
|
839
|
+
| _ => fail(term.at, "Call expected")
|
|
817
840
|
}
|
|
818
|
-
self.unification.affect(term.at, effect, environment.effect)
|
|
819
|
-
e.ECall(
|
|
820
|
-
target = call.DynamicCall(function = function)
|
|
821
|
-
typeArguments = []
|
|
822
|
-
arguments = arguments
|
|
823
|
-
effect = effect
|
|
824
|
-
)
|
|
825
841
|
}
|
|
826
842
|
|
|
827
843
|
inferOperator(environment: Environment, expected: Type, operator: String, term: Term): Term {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
844
|
+
term.{
|
|
845
|
+
| ECall e =>
|
|
846
|
+
let target = StaticCall(operator, instanceCall = False, tailCall = False)
|
|
847
|
+
e.arguments.{
|
|
848
|
+
| [a1] {
|
|
849
|
+
operator == "!"
|
|
850
|
+
} =>
|
|
851
|
+
let t = TConstructor(e.at, core("Bool"), [])
|
|
852
|
+
let e1 = self.inferTerm(environment, t, a1.value)
|
|
853
|
+
self.unification.unify(e.at, expected, t)
|
|
854
|
+
e.ECall(target = target, arguments = [a1.Argument(value = e1)])
|
|
855
|
+
| [a1] {
|
|
856
|
+
operator == "-"
|
|
857
|
+
} =>
|
|
858
|
+
let t1 = self.unification.freshUnificationVariable(e.at)
|
|
859
|
+
let e1 = self.inferTerm(environment, t1, a1.value)
|
|
860
|
+
self.unification.substitute(t1).{
|
|
861
|
+
| TConstructor(_, name, []) {name == core("Float")} =>
|
|
862
|
+
self.unification.unify(e.at, expected, t1)
|
|
863
|
+
| TConstructor(_, name, []) {name == core("Int")} =>
|
|
864
|
+
self.unification.unify(e.at, expected, t1)
|
|
865
|
+
| _ {self.lspHook.isEnabled()} =>
|
|
866
|
+
| _ =>
|
|
867
|
+
throw(CompileError(e.at, "Operators on unknown types not currently supported"))
|
|
868
|
+
}
|
|
869
|
+
e.ECall(target = target, arguments = [a1.Argument(value = e1)])
|
|
870
|
+
| [a1, a2] {
|
|
871
|
+
operator == "||" || operator == "&&"
|
|
872
|
+
} =>
|
|
873
|
+
let t = TConstructor(e.at, core("Bool"), [])
|
|
874
|
+
let e1 = self.inferTerm(environment, t, a1.value)
|
|
875
|
+
let e2 = self.inferTerm(environment, t, a2.value)
|
|
876
|
+
self.unification.unify(e.at, expected, t)
|
|
877
|
+
e.ECall(target = target, arguments = [a1.Argument(value = e1), a2.Argument(value = e2)])
|
|
878
|
+
| [a1, a2] {
|
|
879
|
+
operator == "===" || operator == "!==" // For internal use
|
|
880
|
+
} =>
|
|
881
|
+
let t1 = self.unification.freshUnificationVariable(e.at)
|
|
882
|
+
let e1 = self.inferTerm(environment, t1, a1.value)
|
|
883
|
+
let e2 = self.inferTerm(environment, t1, a2.value)
|
|
884
|
+
self.unification.unify(e.at, expected, TConstructor(e.at, core("Bool"), []))
|
|
885
|
+
e.ECall(target = target, arguments = [a1.Argument(value = e1), a2.Argument(value = e2)])
|
|
886
|
+
| [a1, a2] {
|
|
887
|
+
operator == "+" || operator == "-" ||
|
|
888
|
+
operator == "*" || operator == "/" || operator == "%" ||
|
|
889
|
+
operator == "^"
|
|
890
|
+
} =>
|
|
891
|
+
let t1 = self.unification.freshUnificationVariable(e.at)
|
|
892
|
+
let t2 = self.unification.freshUnificationVariable(e.at)
|
|
893
|
+
let e1 = self.inferTerm(environment, t1, a1.value)
|
|
894
|
+
let e2 = self.inferTerm(environment, t2, a2.value)
|
|
895
|
+
let magic: Type => Option[String] = {t =>
|
|
896
|
+
self.unification.substitute(t).{
|
|
897
|
+
| TConstructor(_, name, []) {name == core("Float")} => Some("Float")
|
|
898
|
+
| TConstructor(_, name, []) {name == core("Int")} => Some("Int")
|
|
899
|
+
| TConstructor(_, name, []) {operator == "+" && name == core("String")} => Some("String")
|
|
900
|
+
| _ => None
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
let chooseType: (Option[String], Option[String]) => Unit = {
|
|
904
|
+
| Some("String"), Some(_) => self.unification.unify(e.at, expected, t1)
|
|
905
|
+
| Some(_), Some("String") => self.unification.unify(e.at, expected, t2)
|
|
906
|
+
| Some("Float"), Some(_) => self.unification.unify(e.at, expected, t1)
|
|
907
|
+
| Some(_), Some("Float") => self.unification.unify(e.at, expected, t2)
|
|
908
|
+
| Some("Int"), Some(_) => self.unification.unify(e.at, expected, t1)
|
|
909
|
+
| Some(_), Some("Int") => self.unification.unify(e.at, expected, t2)
|
|
910
|
+
| Some(_), None =>
|
|
911
|
+
self.unification.unify(e.at, t1, t2)
|
|
912
|
+
self.unification.unify(e.at, expected, t1)
|
|
913
|
+
| None, Some(_) =>
|
|
914
|
+
self.unification.unify(e.at, t2, t1)
|
|
915
|
+
self.unification.unify(e.at, expected, t2)
|
|
916
|
+
| _, _ {self.lspHook.isEnabled()} =>
|
|
917
|
+
| Some(_), Some(_) =>
|
|
918
|
+
throw(CompileError(e.at, "Operators on these types not currently supported"))
|
|
919
|
+
| None, None =>
|
|
920
|
+
throw(CompileError(e.at, "Operators on unknown types not currently supported"))
|
|
921
|
+
}
|
|
922
|
+
chooseType(magic(t1), magic(t2))
|
|
923
|
+
e.ECall(target = target, arguments = [a1.Argument(value = e1), a2.Argument(value = e2)])
|
|
848
924
|
| _ {self.lspHook.isEnabled()} =>
|
|
925
|
+
term
|
|
849
926
|
| _ =>
|
|
850
|
-
|
|
851
|
-
}
|
|
852
|
-
e.ECall(target = target, arguments = [a1.Argument(value = e1)])
|
|
853
|
-
| [a1, a2] {
|
|
854
|
-
operator == "||" || operator == "&&"
|
|
855
|
-
} =>
|
|
856
|
-
let t = TConstructor(e.at, core("Bool"), [])
|
|
857
|
-
let e1 = self.inferTerm(environment, t, a1.value)
|
|
858
|
-
let e2 = self.inferTerm(environment, t, a2.value)
|
|
859
|
-
self.unification.unify(e.at, expected, t)
|
|
860
|
-
e.ECall(target = target, arguments = [a1.Argument(value = e1), a2.Argument(value = e2)])
|
|
861
|
-
| [a1, a2] {
|
|
862
|
-
operator == "===" || operator == "!==" // For internal use
|
|
863
|
-
} =>
|
|
864
|
-
let t1 = self.unification.freshUnificationVariable(e.at)
|
|
865
|
-
let e1 = self.inferTerm(environment, t1, a1.value)
|
|
866
|
-
let e2 = self.inferTerm(environment, t1, a2.value)
|
|
867
|
-
self.unification.unify(e.at, expected, TConstructor(e.at, core("Bool"), []))
|
|
868
|
-
e.ECall(target = target, arguments = [a1.Argument(value = e1), a2.Argument(value = e2)])
|
|
869
|
-
| [a1, a2] {
|
|
870
|
-
operator == "+" || operator == "-" ||
|
|
871
|
-
operator == "*" || operator == "/" || operator == "%" ||
|
|
872
|
-
operator == "^"
|
|
873
|
-
} =>
|
|
874
|
-
let t1 = self.unification.freshUnificationVariable(e.at)
|
|
875
|
-
let t2 = self.unification.freshUnificationVariable(e.at)
|
|
876
|
-
let e1 = self.inferTerm(environment, t1, a1.value)
|
|
877
|
-
let e2 = self.inferTerm(environment, t2, a2.value)
|
|
878
|
-
let magic: Type => Option[String] = {t =>
|
|
879
|
-
self.unification.substitute(t).{
|
|
880
|
-
| TConstructor(_, name, []) {name == core("Float")} => Some("Float")
|
|
881
|
-
| TConstructor(_, name, []) {name == core("Int")} => Some("Int")
|
|
882
|
-
| TConstructor(_, name, []) {operator == "+" && name == core("String")} => Some("String")
|
|
883
|
-
| _ => None
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
let chooseType: (Option[String], Option[String]) => Unit = {
|
|
887
|
-
| Some("String"), Some(_) => self.unification.unify(e.at, expected, t1)
|
|
888
|
-
| Some(_), Some("String") => self.unification.unify(e.at, expected, t2)
|
|
889
|
-
| Some("Float"), Some(_) => self.unification.unify(e.at, expected, t1)
|
|
890
|
-
| Some(_), Some("Float") => self.unification.unify(e.at, expected, t2)
|
|
891
|
-
| Some("Int"), Some(_) => self.unification.unify(e.at, expected, t1)
|
|
892
|
-
| Some(_), Some("Int") => self.unification.unify(e.at, expected, t2)
|
|
893
|
-
| Some(_), None =>
|
|
894
|
-
self.unification.unify(e.at, t1, t2)
|
|
895
|
-
self.unification.unify(e.at, expected, t1)
|
|
896
|
-
| None, Some(_) =>
|
|
897
|
-
self.unification.unify(e.at, t2, t1)
|
|
898
|
-
self.unification.unify(e.at, expected, t2)
|
|
899
|
-
| _, _ {self.lspHook.isEnabled()} =>
|
|
900
|
-
| Some(_), Some(_) =>
|
|
901
|
-
throw(CompileError(e.at, "Operators on these types not currently supported"))
|
|
902
|
-
| None, None =>
|
|
903
|
-
throw(CompileError(e.at, "Operators on unknown types not currently supported"))
|
|
927
|
+
fail(e.at, "Unknown operator: " + operator)
|
|
904
928
|
}
|
|
905
|
-
|
|
906
|
-
e.ECall(target = target, arguments = [a1.Argument(value = e1), a2.Argument(value = e2)])
|
|
907
|
-
| _ {self.lspHook.isEnabled()} =>
|
|
908
|
-
term
|
|
909
|
-
| _ =>
|
|
910
|
-
fail(e.at, "Unknown operator: " + operator)
|
|
929
|
+
| _ => fail(term.at, "Call expected")
|
|
911
930
|
}
|
|
912
931
|
}
|
|
913
932
|
|
package/compiler/JsEmitter.ff
CHANGED
|
@@ -899,9 +899,9 @@ extractTypeName(type: Type): String {
|
|
|
899
899
|
|
|
900
900
|
firstTypeName(types: List[Type]): String {
|
|
901
901
|
types.grabFirst().{
|
|
902
|
-
| TConstructor t => t
|
|
902
|
+
| TConstructor t => t.name
|
|
903
903
|
| TVariable t => fail(t.at, " is still a unification variable")
|
|
904
|
-
}
|
|
904
|
+
}
|
|
905
905
|
}
|
|
906
906
|
|
|
907
907
|
makeDictionaryName(traitName: String, typeName: String): String {
|
package/compiler/LspHook.ff
CHANGED
|
@@ -173,6 +173,7 @@ class ResultHook {
|
|
|
173
173
|
instantiated: Box[Option[Instantiated]]
|
|
174
174
|
)
|
|
175
175
|
InferRecordFieldHook(
|
|
176
|
+
usageAt: Location
|
|
176
177
|
unification: Unification
|
|
177
178
|
environment: Environment
|
|
178
179
|
expected: Type
|
|
@@ -188,7 +189,7 @@ showHook(hook: ResultHook): String {
|
|
|
188
189
|
| InferLookupHook(unification, environment, expected, selfVariable, symbol, instantiated) => "InferLookupHook(...)"
|
|
189
190
|
| InferParameterHook(unification, environment, parameter, missing) => "InferParameterHook(...)"
|
|
190
191
|
| InferPatternHook(unification, environment, expected, pattern) => "InferPatternHook(...)"
|
|
191
|
-
| InferRecordFieldHook(unification, environment, expected, recordType, fieldName) => "InferRecordFieldHook(...)"
|
|
192
|
+
| InferRecordFieldHook(usageAt, unification, environment, expected, recordType, fieldName) => "InferRecordFieldHook(...)"
|
|
192
193
|
| InferSequentialStartHook(unification, term, missing) => "InferSequentialStartHook(...)"
|
|
193
194
|
| InferTermHook(unification, environment, expected, term, recordType, missing) => "InferTermHook(...)"
|
|
194
195
|
| ParseArgumentHook(callAt, argumentIndex, parameterName) => "ParseArgumentHook(...)"
|
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"))
|
|
@@ -83,7 +86,7 @@ main(system: NodeSystem): Unit {
|
|
|
83
86
|
|
|
84
87
|
| CheckCommand(filePath) =>
|
|
85
88
|
let errors = Builder.check(system, fireflyPath, system.path(filePath), None, Map.empty(), LspHook.disabled(), True)
|
|
86
|
-
if(!errors.isEmpty()) {throw(CompileErrors(errors))}
|
|
89
|
+
if(!errors.isEmpty()) {throw(CompileErrors(errors.distinct()))}
|
|
87
90
|
|
|
88
91
|
| BootstrapCommand =>
|
|
89
92
|
let workingDirectory = system.path(".")
|
|
@@ -212,14 +215,19 @@ importAndRun(
|
|
|
212
215
|
packagePair: PackagePair
|
|
213
216
|
mainFile: String
|
|
214
217
|
arguments: List[String]
|
|
215
|
-
):
|
|
218
|
+
): Bool
|
|
216
219
|
target node async """
|
|
217
220
|
const process = await import('process');
|
|
218
221
|
const cwd = process.cwd();
|
|
219
222
|
const workingDirectory = cwd.indexOf(':') == 1 ? 'file:///' + cwd : cwd;
|
|
220
223
|
const packagePath = packagePair_.group_ + "/" + packagePair_.name_
|
|
221
224
|
const main = await import(workingDirectory + "/.firefly/output/" + target_ + "/" + packagePath + "/" + mainFile_ + ".mjs");
|
|
222
|
-
|
|
225
|
+
if(typeof main.$run$ !== 'undefined') {
|
|
226
|
+
await main.$run$(fireflyPath_, arguments_);
|
|
227
|
+
return true;
|
|
228
|
+
} else {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
223
231
|
"""
|
|
224
232
|
|
|
225
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))
|