firefly-compiler 0.4.21 → 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.
@@ -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 { unification.instantiate(instantiationMap, _) }
172
- let firstType = newGenerics.grabFirst().{
173
- | TConstructor t => t
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
  }
@@ -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 recordType =
302
- TConstructor(at, "Record$" + parameters.map {_.name}.join("$"), parameters.map {_.valueType})
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
- let e = term.{| ECall e => e | _ => fail(term.at, "Call expected")}
751
- let call = e.target.{
752
- | DynamicCall call => call
753
- | StaticCall _ => fail(e.at, "Internal error: Static calls not expected in inferMethodCall")
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
- let e = term.{| ECall e => e | _ => fail(term.at, "Call expected")}
779
- let call = e.target.{
780
- | DynamicCall call => call
781
- | StaticCall _ => fail(e.at, "Internal error: Static calls not expected in inferFunctionCall")
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
- let e = term.{| ECall e => e | _ => fail(term.at, "Call expected")}
796
- let call = e.target.{
797
- | DynamicCall call {!call.tailCall} => call
798
- | DynamicCall _ => throw(CompileError(e.at, "Tailcalls not supported on lambda functions"))
799
- | StaticCall _ => fail(e.at, "Internal error: Static calls not expected in inferLambdaCall")
800
- }
801
- let effect = self.unification.freshUnificationVariable(term.at)
802
- let argumentTypes = e.arguments.map {self.unification.freshUnificationVariable(_.at)}
803
- let functionType = TConstructor(e.at, "Function$" + e.arguments.size(), [
804
- effect
805
- ...argumentTypes
806
- expected
807
- ])
808
- let function = self.inferTerm(environment, functionType, call.function)
809
- let arguments = e.arguments.zip(argumentTypes).map {| Pair(argument, t) =>
810
- argument.name.each {name =>
811
- throw(CompileError(argument.at, "Named argument not allowed here: " + name))
812
- }
813
- argument.Argument(value = self.inferTerm(environment, t, argument.value))
814
- }
815
- e.typeArguments.first().each {typeArgument =>
816
- throw(CompileError(typeArgument.at, "Type arguments not allowed here"))
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
- let e = term.{| ECall e => e | _ => fail(term.at, "Call expected") }
829
- let target = StaticCall(operator, instanceCall = False, tailCall = False)
830
- e.arguments.{
831
- | [a1] {
832
- operator == "!"
833
- } =>
834
- let t = TConstructor(e.at, core("Bool"), [])
835
- let e1 = self.inferTerm(environment, t, a1.value)
836
- self.unification.unify(e.at, expected, t)
837
- e.ECall(target = target, arguments = [a1.Argument(value = e1)])
838
- | [a1] {
839
- operator == "-"
840
- } =>
841
- let t1 = self.unification.freshUnificationVariable(e.at)
842
- let e1 = self.inferTerm(environment, t1, a1.value)
843
- self.unification.substitute(t1).{
844
- | TConstructor(_, name, []) {name == core("Float")} =>
845
- self.unification.unify(e.at, expected, t1)
846
- | TConstructor(_, name, []) {name == core("Int")} =>
847
- self.unification.unify(e.at, expected, t1)
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
- throw(CompileError(e.at, "Operators on unknown types not currently supported"))
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
- chooseType(magic(t1), magic(t2))
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
 
@@ -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
- }.name
904
+ }
905
905
  }
906
906
 
907
907
  makeDictionaryName(traitName: String, typeName: String): String {
@@ -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
- ): Unit
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
- await main.$run$(fireflyPath_, arguments_)
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) {
@@ -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(p)) => Some(Pair("" + i, p))
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))