firefly-compiler 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/.firefly-workspace +1 -0
  2. package/.vscode/settings.json +5 -0
  3. package/LICENSE.txt +21 -0
  4. package/README.md +96 -0
  5. package/bin/firefly.mjs +2 -0
  6. package/compiler/.firefly/package.ff +1 -0
  7. package/compiler/Builder.ff +218 -0
  8. package/compiler/Compiler.ff +241 -0
  9. package/compiler/Dependencies.ff +179 -0
  10. package/compiler/Deriver.ff +647 -0
  11. package/compiler/Dictionaries.ff +205 -0
  12. package/compiler/Environment.ff +166 -0
  13. package/compiler/Inference.ff +1117 -0
  14. package/compiler/JsEmitter.ff +861 -0
  15. package/compiler/JsImporter.ff +56 -0
  16. package/compiler/LspHook.ff +188 -0
  17. package/compiler/Main.ff +237 -0
  18. package/compiler/Parser.ff +1383 -0
  19. package/compiler/Patterns.ff +111 -0
  20. package/compiler/Resolver.ff +620 -0
  21. package/compiler/Substitution.ff +178 -0
  22. package/compiler/Syntax.ff +299 -0
  23. package/compiler/Token.ff +180 -0
  24. package/compiler/Tokenizer.ff +278 -0
  25. package/compiler/Unification.ff +220 -0
  26. package/compiler/Wildcards.ff +50 -0
  27. package/compiler/Workspace.ff +88 -0
  28. package/core/.firefly/package.ff +2 -0
  29. package/core/Any.ff +30 -0
  30. package/core/Array.ff +249 -0
  31. package/core/AssetSystem.ff +61 -0
  32. package/core/Atomic.ff +64 -0
  33. package/core/Bool.ff +13 -0
  34. package/core/BrowserSystem.ff +14 -0
  35. package/core/Buffer.ff +211 -0
  36. package/core/BuildSystem.ff +144 -0
  37. package/core/Channel.ff +131 -0
  38. package/core/Char.ff +18 -0
  39. package/core/Core.ff +58 -0
  40. package/core/Duration.ff +15 -0
  41. package/core/Equal.ff +52 -0
  42. package/core/Error.ff +20 -0
  43. package/core/FileHandle.ff +41 -0
  44. package/core/Float.ff +41 -0
  45. package/core/HttpClient.ff +84 -0
  46. package/core/Instant.ff +9 -0
  47. package/core/Int.ff +61 -0
  48. package/core/IntMap.ff +85 -0
  49. package/core/JsSystem.ff +66 -0
  50. package/core/JsValue.ff +240 -0
  51. package/core/List.ff +440 -0
  52. package/core/Lock.ff +144 -0
  53. package/core/Log.ff +24 -0
  54. package/core/Map.ff +126 -0
  55. package/core/NodeSystem.ff +88 -0
  56. package/core/Nothing.ff +1 -0
  57. package/core/Option.ff +133 -0
  58. package/core/Ordering.ff +157 -0
  59. package/core/Pair.ff +55 -0
  60. package/core/Path.ff +393 -0
  61. package/core/RbMap.ff +216 -0
  62. package/core/Serializable.ff +173 -0
  63. package/core/Set.ff +38 -0
  64. package/core/Show.ff +43 -0
  65. package/core/Stack.ff +263 -0
  66. package/core/Stream.ff +406 -0
  67. package/core/String.ff +175 -0
  68. package/core/StringMap.ff +85 -0
  69. package/core/Task.ff +138 -0
  70. package/core/Try.ff +81 -0
  71. package/core/Unit.ff +3 -0
  72. package/experimental/random/AltGeneric.ff +44 -0
  73. package/experimental/random/Async.ff +68 -0
  74. package/experimental/random/Buffer2.ff +77 -0
  75. package/experimental/random/Cat.ff +12 -0
  76. package/experimental/random/Dictionary.ff +52 -0
  77. package/experimental/random/Example.ff +46 -0
  78. package/experimental/random/Generic.ff +102 -0
  79. package/experimental/random/HappyEyeballs.ff +40 -0
  80. package/experimental/random/HashMap.ff +72 -0
  81. package/experimental/random/IfElseUnit.ff +9 -0
  82. package/experimental/random/InputOutput.ff +23 -0
  83. package/experimental/random/ListVsArray.ff +45 -0
  84. package/experimental/random/Main.ff +44 -0
  85. package/experimental/random/MapTest.ff +67 -0
  86. package/experimental/random/OldTaskSystem.ff +210 -0
  87. package/experimental/random/PatternTest.ff +39 -0
  88. package/experimental/random/Patterns.ff +226 -0
  89. package/experimental/random/ReadBytesTest.ff +10 -0
  90. package/experimental/random/RunLength.ff +65 -0
  91. package/experimental/random/Scrape.ff +51 -0
  92. package/experimental/random/Serialization.ff +217 -0
  93. package/experimental/random/SerializationTest.ff +46 -0
  94. package/experimental/random/Serializer.ff +36 -0
  95. package/experimental/random/StdInOutErr.ff +4 -0
  96. package/experimental/random/Symbols.ff +74 -0
  97. package/experimental/random/Tag.ff +49 -0
  98. package/experimental/random/Tensor.ff +52 -0
  99. package/experimental/random/Try.ff +56 -0
  100. package/experimental/random/Tsv.ff +9 -0
  101. package/experimental/random/TypesAreModules.ff +87 -0
  102. package/experimental/random/blueprints/Blueprint.ff +52 -0
  103. package/experimental/random/blueprints/Main.ff +11 -0
  104. package/experimental/random/blueprints/Pretty.ff +58 -0
  105. package/experimental/random/blueprints/User.ff +64 -0
  106. package/experimental/random/blueprintsystem/BlueprintSystem.ff +48 -0
  107. package/experimental/random/blueprintsystem/Deserialize.ff +53 -0
  108. package/experimental/random/blueprintsystem/ReadJs.ff +13 -0
  109. package/experimental/random/blueprintsystem/User.ff +2 -0
  110. package/experimental/random/kahrs/Kahrs.ff +112 -0
  111. package/experimental/random/kahrs/TestKahrs.ff +22 -0
  112. package/experimental/random/kahrs/TestMap.ff +18 -0
  113. package/experimental/random/streaming/Gzip.ff +3 -0
  114. package/experimental/random/streaming/Main.ff +34 -0
  115. package/experimental/random/streaming/S3Bucket.ff +11 -0
  116. package/experimental/random/streaming/Tar.ff +5 -0
  117. package/experimental/rhymeapp/Main.ff +81 -0
  118. package/experimental/rhymeapp/index.html +14 -0
  119. package/firefly.sh +5 -0
  120. package/fireflysite/Main.ff +13 -0
  121. package/httpserver/.firefly/package.ff +1 -0
  122. package/httpserver/HttpServer.ff +184 -0
  123. package/lsp/.firefly/package.ff +1 -0
  124. package/lsp/CompletionHandler.ff +814 -0
  125. package/lsp/Handler.ff +551 -0
  126. package/lsp/HoverHandler.ff +82 -0
  127. package/lsp/LanguageServer.ff +229 -0
  128. package/lsp/SignatureHelpHandler.ff +55 -0
  129. package/lsp/SymbolHandler.ff +167 -0
  130. package/output/js/ff/compiler/Builder.mjs +483 -0
  131. package/output/js/ff/compiler/Compiler.mjs +410 -0
  132. package/output/js/ff/compiler/Dependencies.mjs +388 -0
  133. package/output/js/ff/compiler/Deriver.mjs +1166 -0
  134. package/output/js/ff/compiler/Dictionaries.mjs +1305 -0
  135. package/output/js/ff/compiler/Environment.mjs +1005 -0
  136. package/output/js/ff/compiler/Inference.mjs +4264 -0
  137. package/output/js/ff/compiler/JsEmitter.mjs +5353 -0
  138. package/output/js/ff/compiler/JsImporter.mjs +262 -0
  139. package/output/js/ff/compiler/LspHook.mjs +789 -0
  140. package/output/js/ff/compiler/Main.mjs +1695 -0
  141. package/output/js/ff/compiler/Parser.mjs +4004 -0
  142. package/output/js/ff/compiler/Patterns.mjs +923 -0
  143. package/output/js/ff/compiler/Resolver.mjs +2303 -0
  144. package/output/js/ff/compiler/Substitution.mjs +1146 -0
  145. package/output/js/ff/compiler/Syntax.mjs +12430 -0
  146. package/output/js/ff/compiler/Token.mjs +3092 -0
  147. package/output/js/ff/compiler/Tokenizer.mjs +589 -0
  148. package/output/js/ff/compiler/Unification.mjs +1748 -0
  149. package/output/js/ff/compiler/Wildcards.mjs +604 -0
  150. package/output/js/ff/compiler/Workspace.mjs +683 -0
  151. package/output/js/ff/core/Any.mjs +139 -0
  152. package/output/js/ff/core/Array.mjs +594 -0
  153. package/output/js/ff/core/AssetSystem.mjs +270 -0
  154. package/output/js/ff/core/Atomic.mjs +186 -0
  155. package/output/js/ff/core/Bool.mjs +141 -0
  156. package/output/js/ff/core/BrowserSystem.mjs +122 -0
  157. package/output/js/ff/core/Buffer.mjs +467 -0
  158. package/output/js/ff/core/BuildSystem.mjs +320 -0
  159. package/output/js/ff/core/Channel.mjs +268 -0
  160. package/output/js/ff/core/Char.mjs +145 -0
  161. package/output/js/ff/core/Core.mjs +300 -0
  162. package/output/js/ff/core/Duration.mjs +112 -0
  163. package/output/js/ff/core/Equal.mjs +175 -0
  164. package/output/js/ff/core/Error.mjs +138 -0
  165. package/output/js/ff/core/FileHandle.mjs +164 -0
  166. package/output/js/ff/core/Float.mjs +214 -0
  167. package/output/js/ff/core/HttpClient.mjs +210 -0
  168. package/output/js/ff/core/Instant.mjs +105 -0
  169. package/output/js/ff/core/Int.mjs +254 -0
  170. package/output/js/ff/core/IntMap.mjs +282 -0
  171. package/output/js/ff/core/JsSystem.mjs +234 -0
  172. package/output/js/ff/core/JsValue.mjs +678 -0
  173. package/output/js/ff/core/List.mjs +2335 -0
  174. package/output/js/ff/core/Lock.mjs +322 -0
  175. package/output/js/ff/core/Log.mjs +159 -0
  176. package/output/js/ff/core/Map.mjs +358 -0
  177. package/output/js/ff/core/NodeSystem.mjs +288 -0
  178. package/output/js/ff/core/Nothing.mjs +100 -0
  179. package/output/js/ff/core/Option.mjs +1002 -0
  180. package/output/js/ff/core/Ordering.mjs +734 -0
  181. package/output/js/ff/core/Pair.mjs +318 -0
  182. package/output/js/ff/core/Path.mjs +768 -0
  183. package/output/js/ff/core/RbMap.mjs +1936 -0
  184. package/output/js/ff/core/Serializable.mjs +434 -0
  185. package/output/js/ff/core/Set.mjs +250 -0
  186. package/output/js/ff/core/Show.mjs +201 -0
  187. package/output/js/ff/core/Stack.mjs +595 -0
  188. package/output/js/ff/core/Stream.mjs +1300 -0
  189. package/output/js/ff/core/String.mjs +433 -0
  190. package/output/js/ff/core/StringMap.mjs +282 -0
  191. package/output/js/ff/core/Task.mjs +345 -0
  192. package/output/js/ff/core/Try.mjs +503 -0
  193. package/output/js/ff/core/Unit.mjs +103 -0
  194. package/package.json +29 -0
  195. package/postgresql/.firefly/include/package-lock.json +250 -0
  196. package/postgresql/.firefly/include/package.json +5 -0
  197. package/postgresql/.firefly/include/prepare.sh +2 -0
  198. package/postgresql/.firefly/package.ff +3 -0
  199. package/postgresql/Pg.ff +530 -0
  200. package/unsafejs/.firefly/package.ff +1 -0
  201. package/unsafejs/UnsafeJs.ff +19 -0
  202. package/vscode/.vscode/launch.json +18 -0
  203. package/vscode/.vscode/tasks.json +33 -0
  204. package/vscode/LICENSE.txt +21 -0
  205. package/vscode/Prepublish.ff +15 -0
  206. package/vscode/README.md +17 -0
  207. package/vscode/client/package-lock.json +544 -0
  208. package/vscode/client/package.json +22 -0
  209. package/vscode/client/src/extension.ts +64 -0
  210. package/vscode/client/tsconfig.json +12 -0
  211. package/vscode/icons/firefly-icon.png +0 -0
  212. package/vscode/icons/firefly-icon.svg +10 -0
  213. package/vscode/icons/firefly-logo-notext.png +0 -0
  214. package/vscode/icons/firefly-logo.png +0 -0
  215. package/vscode/language-configuration.json +39 -0
  216. package/vscode/package-lock.json +3623 -0
  217. package/vscode/package.json +144 -0
  218. package/vscode/snippets-none.json +1 -0
  219. package/vscode/snippets.json +241 -0
  220. package/vscode/syntaxes/firefly.tmLanguage.json +294 -0
  221. package/vscode/tsconfig.json +20 -0
@@ -0,0 +1,56 @@
1
+ import Syntax
2
+
3
+ class JsImporter(
4
+ mutable imports: Map[String, String]
5
+ )
6
+
7
+ make(): JsImporter {
8
+ JsImporter(Map.empty())
9
+ }
10
+
11
+ fail[T](at: Location, message: String): T {
12
+ panic(message + " " + at.show())
13
+ }
14
+
15
+ extend self: JsImporter {
16
+
17
+ add(url: String): String {
18
+ let importName = self.imports.get(url).{
19
+ | None =>
20
+ let n = "import$" + self.imports.size()
21
+ self.imports = self.imports.add(url, n)
22
+ n
23
+ | Some(n) => n
24
+ }
25
+ importName
26
+ }
27
+
28
+ process(at: Location, code: String): String {
29
+ let space = code.takeWhile {c => c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == ';'}
30
+ let rest = code.dropFirst(space.size())
31
+ if(!rest.startsWith("import * as ")) {code} else:
32
+ let rest2 = rest.dropFirst("import * as ".size())
33
+ let name = rest2.takeWhile {_.isAsciiLetterOrDigit()}
34
+ if(name.size() == 0) {throw(CompileError(at, "Expected alias after \"import * as \""))}
35
+ let rest3 = rest2.dropFirst(name.size())
36
+ if(!rest3.startsWith(" from '")) {throw(CompileError(at, "Expected \" from '\" after \"import * as ...\""))}
37
+ let rest4 = rest3.dropFirst(" from '".size())
38
+ let url = rest4.takeWhile {_ != '\''}
39
+ if(url.size() == 0) {throw(CompileError(at, "Expected module name after \" from '\""))}
40
+ if(url.any{_ == '\n'}) {throw(CompileError(at, "Unclosed module name string"))}
41
+ let rest5 = rest4.dropFirst(url.size() + 1)
42
+ let importName = self.add(url)
43
+ space + "const " + name + " = " + importName + self.process(at, rest5)
44
+ }
45
+
46
+ generateImports(ignoreModules: Set[String]): List[String] {
47
+ self.imports.pairs().map {| Pair(moduleName, mangledName) =>
48
+ if(ignoreModules.contains(moduleName)) {
49
+ "const " + mangledName + " = void 0; // Ignored import"
50
+ } else {
51
+ "import * as " + mangledName + " from '" + moduleName + "';"
52
+ }
53
+ }
54
+ }
55
+
56
+ }
@@ -0,0 +1,188 @@
1
+ import Syntax
2
+ import Unification
3
+ import Environment
4
+
5
+ class LspHook(
6
+ at: Location
7
+ definedAt: Location
8
+ insertIdentifier: Bool
9
+ trackSymbols: Bool
10
+ stackOfResults: Stack[ResultHook]
11
+ )
12
+
13
+ disabled(): LspHook {
14
+ make(None, None, False, False)
15
+ }
16
+
17
+ make(at: Option[Location], definedAt: Option[Location], insertIdentifier: Bool, trackSymbols: Bool): LspHook {
18
+ LspHook( // Default dummy values instead of Option[Location] to speed up location hit check
19
+ at = at.else {Location("^lsp", -7, -7)}
20
+ definedAt = definedAt.else {Location("^lsp", -7, -7)}
21
+ insertIdentifier = insertIdentifier
22
+ trackSymbols = trackSymbols
23
+ stackOfResults = [].toStack()
24
+ )
25
+ }
26
+
27
+ extend self: LspHook {
28
+ isEnabled(): Bool {
29
+ self.at.line != -7 ||
30
+ self.definedAt.line != -7 ||
31
+ self.trackSymbols
32
+ }
33
+ isAt(at: Location): Bool {
34
+ self.at.line == at.line &&
35
+ self.at.column == at.column &&
36
+ self.at.file == at.file
37
+ }
38
+ isDefinedAt(at: Location): Bool {
39
+ self.definedAt.line == at.line &&
40
+ self.definedAt.column == at.column &&
41
+ self.definedAt.file == at.file
42
+ }
43
+ emit(result: ResultHook) {
44
+ self.stackOfResults.push(result)
45
+ }
46
+ results(): List[ResultHook] {
47
+ self.stackOfResults.toList()
48
+ }
49
+ }
50
+
51
+ strictlyBetween(afterAt: Location, beforeAt: Location, at: Location, extraColumns: Int): Bool {
52
+ at.file == afterAt.file && (
53
+ (at.line == afterAt.line && at.column > afterAt.column) ||
54
+ at.line > afterAt.line
55
+ ) && (
56
+ (at.line == beforeAt.line && at.column < beforeAt.column + extraColumns) ||
57
+ at.line < beforeAt.line
58
+ )
59
+ }
60
+
61
+ data SymbolHook(
62
+ qualifiedName: String
63
+ usageAt: Location
64
+ definedAt: Location
65
+ )
66
+
67
+ class Box[T](mutable value: T)
68
+
69
+ class ResultHook {
70
+ ParseSymbolBegin
71
+ ParseSymbolEnd(
72
+ name: String
73
+ kind: Int
74
+ selectionStart: Location
75
+ selectionEnd: Location
76
+ start: Location
77
+ end: Location
78
+ )
79
+ ParseArgumentHook(
80
+ callAt: Location
81
+ argumentIndex: Int
82
+ parameterName: Option[String]
83
+ )
84
+ ResolveSymbolHook(
85
+ symbol: SymbolHook
86
+ annotation: Option[Type]
87
+ )
88
+ ResolveTypeHook(
89
+ types: Map[String, String]
90
+ typeGenerics: Map[String, List[String]]
91
+ symbol: SymbolHook
92
+ explicitType: Type
93
+ )
94
+ ResolveConstraintHook(
95
+ symbol: SymbolHook
96
+ constrant: Constraint
97
+ )
98
+ ResolveSignatureHook(
99
+ signature: Signature
100
+ isInstanceMethod: Bool
101
+ )
102
+ ResolveVariantFieldHook(
103
+ symbol: SymbolHook
104
+ type: Type
105
+ commonField: Bool
106
+ )
107
+ InferTermHook(
108
+ unification: Unification
109
+ environment: Environment
110
+ expected: Type
111
+ term: Term
112
+ recordType: Box[Option[Type]]
113
+ missing: StringMap[Pair[Instantiated, Option[List[Argument]]]]
114
+ )
115
+ InferLambdaStartHook(
116
+ unification: Unification
117
+ environment: Environment
118
+ lambdaType: Type
119
+ )
120
+ InferSequentialStartHook(
121
+ unification: Unification
122
+ term: Term
123
+ missing: StringMap[Pair[Instantiated, Option[List[Argument]]]]
124
+ )
125
+ InferFunctionDefinitionHook(
126
+ unification: Unification
127
+ environment: Environment
128
+ definition: DFunction
129
+ missing: StringMap[Pair[Instantiated, Option[List[Argument]]]]
130
+ )
131
+ InferPatternHook(
132
+ unification: Unification
133
+ environment: Environment
134
+ expected: Type
135
+ pattern: MatchPattern
136
+ )
137
+ InferParameterHook(
138
+ unification: Unification
139
+ environment: Environment
140
+ parameter: Parameter
141
+ missing: StringMap[Pair[Instantiated, Option[List[Argument]]]]
142
+ )
143
+ InferArgumentHook(
144
+ unification: Unification
145
+ environment: Environment
146
+ isCopy: Bool
147
+ callAt: Location
148
+ callName: String
149
+ parameters: List[Parameter]
150
+ arguments: List[Argument]
151
+ argumentIndex: Int
152
+ )
153
+ InferLookupHook(
154
+ unification: Unification
155
+ environment: Environment
156
+ expected: Type
157
+ selfVariable: Option[String]
158
+ symbol: Box[SymbolHook]
159
+ instantiated: Box[Option[Instantiated]]
160
+ )
161
+ InferRecordFieldHook(
162
+ unification: Unification
163
+ environment: Environment
164
+ expected: Type
165
+ recordType: Type
166
+ fieldName: String
167
+ )
168
+ }
169
+
170
+ showHook(hook: ResultHook): String {
171
+ | InferArgumentHook(unification, environment, isCopy, callAt, callName, parameters, arguments, argumentIndex) => "InferArgumentHook(...)"
172
+ | InferFunctionDefinitionHook(unification, environment, definition, missing) => "InferFunctionDefinitionHook(...)"
173
+ | InferLambdaStartHook(unification, environment, lambdaType) => "InferLambdaStartHook(...)"
174
+ | InferLookupHook(unification, environment, expected, selfVariable, symbol, instantiated) => "InferLookupHook(...)"
175
+ | InferParameterHook(unification, environment, parameter, missing) => "InferParameterHook(...)"
176
+ | InferPatternHook(unification, environment, expected, pattern) => "InferPatternHook(...)"
177
+ | InferRecordFieldHook(unification, environment, expected, recordType, fieldName) => "InferRecordFieldHook(...)"
178
+ | InferSequentialStartHook(unification, term, missing) => "InferSequentialStartHook(...)"
179
+ | InferTermHook(unification, environment, expected, term, recordType, missing) => "InferTermHook(...)"
180
+ | ParseArgumentHook(callAt, argumentIndex, parameterName) => "ParseArgumentHook(...)"
181
+ | ParseSymbolBegin => "ParseSymbolBegin(...)"
182
+ | ParseSymbolEnd(name, kind, selectionStart, selectionEnd, start, end) => "ParseSymbolEnd(...)"
183
+ | ResolveConstraintHook(symbol, constrant) => "ResolveConstraintHook(...)"
184
+ | ResolveSignatureHook(signature, _) => "ResolveSignatureHook(...)"
185
+ | ResolveSymbolHook(symbol, annotation) => "ResolveSymbolHook(...)"
186
+ | ResolveTypeHook(types, typeGenerics, symbol, explicitType) => "ResolveTypeHook(...)"
187
+ | ResolveVariantFieldHook(symbol, type, commonField) => "ResolveVariantFieldHook(...)"
188
+ }
@@ -0,0 +1,237 @@
1
+ import Tokenizer
2
+ import Parser
3
+ import Syntax
4
+ import Resolver
5
+ import Compiler
6
+ import Unification
7
+ import Builder
8
+ import Dependencies
9
+ import JsEmitter
10
+ import Inference
11
+ import LspHook
12
+
13
+ data MainCommand {
14
+ BootstrapCommand
15
+ RunCommand(mainPath: String, argument: List[String])
16
+ BrowserCommand(mainPath: String)
17
+ BuildCommand(mainPath: String)
18
+ CheckCommand(filePath: String)
19
+ }
20
+
21
+ data CommandLineError(problem: String)
22
+
23
+ main(system: NodeSystem): Unit {
24
+
25
+ let fireflyPath = detectFireflyPath(system)
26
+
27
+ function buildScript(
28
+ mainFile: String
29
+ mainPackagePair: PackagePair
30
+ emitTarget: EmitTarget
31
+ resolvedDependencies: ResolvedDependencies
32
+ ) {
33
+ let fixedPackagePaths = if(resolvedDependencies.packagePaths.contains(PackagePair("ff", "core"))) {
34
+ resolvedDependencies.packagePaths
35
+ } else {
36
+ resolvedDependencies.packagePaths.add(PackagePair("ff", "core"), fireflyPath.slash("core"))
37
+ }
38
+ let compilerModulePath = if(emitTarget != EmitBrowser && emitTarget != EmitExecutable) {
39
+ fireflyPath.slash("output").slash("js").slash("ff").slash("compiler/Builder.mjs")
40
+ }
41
+ let targetName = emitTarget.{
42
+ | EmitBuild => "build"
43
+ | EmitNode => "node"
44
+ | EmitBrowser => "browser"
45
+ | EmitExecutable => "executable"
46
+ }
47
+ Builder.build(
48
+ system = system
49
+ emitTarget = emitTarget
50
+ mainPackage = mainPackagePair
51
+ mainModule = mainFile
52
+ resolvedDependencies = resolvedDependencies.ResolvedDependencies(packagePaths = fixedPackagePaths)
53
+ compilerModulePath = compilerModulePath
54
+ tempPath = system.path(".firefly").slash("temporary")
55
+ jsOutputPath = system.path(".firefly").path("output").path(targetName)
56
+ printMeasurements = False
57
+ )
58
+ }
59
+
60
+ function runCommand(command: MainCommand) {
61
+ | RunCommand(mainFile, arguments) =>
62
+ let resolvedDependencies = Dependencies.process(system.httpClient(), system.path(mainFile + ".ff"))
63
+ prepareFireflyDirectory(system.path("."))
64
+ let localMainFile = system.path(mainFile).base()
65
+ buildScript(localMainFile, resolvedDependencies.mainPackagePair, EmitNode, resolvedDependencies)
66
+ importAndRun(fireflyPath, "node", resolvedDependencies.mainPackagePair, localMainFile, arguments)
67
+
68
+ | BrowserCommand(mainFile) =>
69
+ let resolvedDependencies = Dependencies.process(system.httpClient(), system.path(mainFile + ".ff"))
70
+ prepareFireflyDirectory(system.path("."))
71
+ let localMainFile = system.path(mainFile).base()
72
+ buildScript(mainFile, resolvedDependencies.mainPackagePair, EmitBrowser, resolvedDependencies)
73
+ bundleForBrowser(system, resolvedDependencies.mainPackagePair, localMainFile)
74
+
75
+ | BuildCommand(mainFile) =>
76
+ let resolvedDependencies = Dependencies.process(system.httpClient(), system.path(mainFile + ".ff"))
77
+ prepareFireflyDirectory(system.path("."))
78
+ let localMainFile = system.path(mainFile).base()
79
+ buildScript(localMainFile, resolvedDependencies.mainPackagePair, EmitBuild, resolvedDependencies)
80
+ buildScript(localMainFile, resolvedDependencies.mainPackagePair, EmitExecutable, resolvedDependencies)
81
+ bundleForPkg(system, resolvedDependencies.mainPackagePair, localMainFile)
82
+ importAndRun(fireflyPath, "build", resolvedDependencies.mainPackagePair, localMainFile, [])
83
+
84
+ | CheckCommand(filePath) =>
85
+ Builder.check(system, fireflyPath, system.path(filePath), Map.empty(), LspHook.disabled(), True)
86
+
87
+ | BootstrapCommand =>
88
+ let workingDirectory = system.path(".")
89
+ Builder.build(
90
+ system = system
91
+ emitTarget = EmitNode
92
+ mainPackage = PackagePair("ff", "compiler")
93
+ mainModule = "Main"
94
+ resolvedDependencies = ResolvedDependencies(
95
+ mainPackagePair = PackagePair("ff", "compiler")
96
+ packages = [].toMap() // Only used for includes currently
97
+ packagePaths = [
98
+ Pair(PackagePair("ff", "compiler"), workingDirectory.slash("compiler"))
99
+ Pair(PackagePair("ff", "core"), workingDirectory.slash("core"))
100
+ ].toMap()
101
+ singleFilePackages = [].toSet()
102
+ )
103
+ compilerModulePath = None
104
+ tempPath = workingDirectory.slash("output").slash("temporary")
105
+ jsOutputPath = workingDirectory.slash("output").slash("js")
106
+ printMeasurements = True
107
+ )
108
+ }
109
+
110
+ try {
111
+ let command = parseCommandLine(system.arguments().toList())
112
+ runCommand(command)
113
+ } catch {| CommandLineError(message), error =>
114
+ Log.debug(message)
115
+ } catch {| CompileError(at, message), error =>
116
+ Log.debug(message)
117
+ Log.debug(" at " + at.file.replace("./", "") + ":" + at.line + ":" + at.column)
118
+ } grab()
119
+ }
120
+
121
+ usageString = """
122
+ usage: firefly <main-file> [<main-arguments>] | <command> [<command-arguments>]
123
+
124
+ These are the commands:
125
+ run <main-file> [<main-arguments>] Run the main file with the provided arguments
126
+ browser <main-file> Compile the main file for the browser
127
+ build <main-file> Build the main file
128
+ check <firefly-file> Check the firefly source file for errors
129
+ bootstrap Bootstrap the compiler
130
+ """
131
+
132
+ parseCommandLine(arguments: List[String]): MainCommand {
133
+ | [mainFile, ...mainArguments] {mainFile.removeLast(".ff") | Some(mainName)} =>
134
+ RunCommand(mainName, mainArguments)
135
+ | ["run", ...runArguments] =>
136
+ runArguments.{
137
+ | [mainFile, ...mainArguments] {mainFile.removeLast(".ff") | Some(mainName)} =>
138
+ RunCommand(mainName, mainArguments)
139
+ | _ => throw(CommandLineError(
140
+ "You must specify a Firefly file (.ff) as first argument to run." + usageString
141
+ ))
142
+ }
143
+ | ["browser", ...browserArguments] =>
144
+ browserArguments.{
145
+ | [mainFile] {mainFile.removeLast(".ff") | Some(mainName)} =>
146
+ BrowserCommand(mainName)
147
+ | [_, _, ..._] => throw(CommandLineError(
148
+ "You must only specify a single argument to browser." + usageString
149
+ ))
150
+ | _ => throw(CommandLineError(
151
+ "You must specify a Firefly file (.ff) as the argument to browser." + usageString
152
+ ))
153
+ }
154
+ | ["build", ...buildArguments] =>
155
+ buildArguments.{
156
+ | [mainFile] {mainFile.removeLast(".ff") | Some(mainName)} =>
157
+ BuildCommand(mainName)
158
+ | [_, _, ..._] => throw(CommandLineError(
159
+ "You must only specify a single argument to build." + usageString
160
+ ))
161
+ | _ => throw(CommandLineError(
162
+ "You must specify a Firefly file (.ff) as the argument to build." + usageString
163
+ ))
164
+ }
165
+ | ["check", ...checkArguments] =>
166
+ checkArguments.{
167
+ | [fileName] {fileName.removeLast(".ff") | Some(_)} =>
168
+ CheckCommand(fileName)
169
+ | [_, _, ..._] => throw(CommandLineError(
170
+ "You must only specify a single argument to check." + usageString
171
+ ))
172
+ | _ => throw(CommandLineError(
173
+ "You must specify a Firefly file (.ff) as the argument to build." + usageString
174
+ ))
175
+ }
176
+ | ["bootstrap", _] =>
177
+ throw(CommandLineError("bootstrap takes no arguments" + usageString))
178
+ | ["bootstrap"] => BootstrapCommand
179
+ | [] => throw(CommandLineError("You must specify a command or a main file to run." + usageString))
180
+ | [s, ..._] => throw(CommandLineError("Unknown command '" + s + "'" + usageString))
181
+ }
182
+
183
+ bundleForPkg(system: NodeSystem, packagePair: PackagePair, mainFile: String) {
184
+ let prefix = ".firefly/output/executable/"
185
+ let mainJsFile = prefix + packagePair.groupName("/") + "/" + mainFile + ".mjs"
186
+ let file = prefix + "Main.bundle.js"
187
+ BuildSystem.internalNodeCallEsBuild(system, mainJsFile, outputPath = file, minify = False)
188
+ }
189
+
190
+ bundleForBrowser(system: NodeSystem, packagePair: PackagePair, mainFile: String) {
191
+ let prefix = ".firefly/output/browser/"
192
+ let mainJsFile = prefix + packagePair.groupName("/") + "/" + mainFile + ".mjs"
193
+ let file = prefix + "Main.bundle.js"
194
+ let browserCode = BrowserCode(
195
+ packageGroup = packagePair.group
196
+ packageName = packagePair.name
197
+ mainFile = system.path(mainFile)
198
+ assetSystem = AssetSystem([Pair("/", {system.path(".").readStream()})].toMap())
199
+ ) // TODO
200
+ BuildSystem.internalCallEsBuild(browserCode, mainJsFile, outputPath = file, minify = True, sourceMap = True)
201
+ }
202
+
203
+ importAndRun(
204
+ fireflyPath: Path
205
+ target: String
206
+ packagePair: PackagePair
207
+ mainFile: String
208
+ arguments: List[String]
209
+ ): Unit
210
+ target node async """
211
+ const process = await import('process');
212
+ const cwd = process.cwd();
213
+ const workingDirectory = cwd.indexOf(':') == 1 ? 'file:///' + cwd : cwd;
214
+ const packagePath = packagePair_.group_ + "/" + packagePair_.name_
215
+ const main = await import(workingDirectory + "/.firefly/output/" + target_ + "/" + packagePath + "/" + mainFile_ + ".mjs");
216
+ await main.$run$(fireflyPath_, ff_core_List.List_toArray(arguments_))
217
+ """
218
+
219
+ prepareFireflyDirectory(path: Path) {
220
+ if(!path.slash(".firefly").slash("output").exists()) {
221
+ if(!path.slash(".firefly").exists()) {
222
+ path.slash(".firefly").createDirectory()
223
+ }
224
+ path.slash(".firefly").slash("output").createDirectory()
225
+ }
226
+ }
227
+
228
+ detectFireflyPath(system: NodeSystem): Path
229
+ target node async """
230
+ import * as url from 'url'
231
+ const suffix = '/output/js/ff/compiler/Main.mjs'
232
+ const moduleUrl = import.meta.url
233
+ if(!import.meta.url.endsWith(suffix)) {
234
+ throw 'Expected module path to end with: ' + suffix + ", but got: " + moduleUrl;
235
+ }
236
+ return url.fileURLToPath(new URL(moduleUrl.slice(0, -suffix.length)))
237
+ """