firefly-compiler 0.5.39 → 0.5.40

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 (129) hide show
  1. package/.hintrc +4 -4
  2. package/.vscode/settings.json +4 -4
  3. package/bin/Release.ff +157 -157
  4. package/bin/firefly.mjs +1 -1
  5. package/compiler/Builder.ff +275 -275
  6. package/compiler/Compiler.ff +234 -234
  7. package/compiler/Dependencies.ff +186 -186
  8. package/compiler/DependencyLock.ff +17 -17
  9. package/compiler/JsEmitter.ff +1437 -1437
  10. package/compiler/LspHook.ff +202 -202
  11. package/compiler/ModuleCache.ff +178 -178
  12. package/compiler/Workspace.ff +88 -88
  13. package/core/.firefly/include/package.json +5 -5
  14. package/core/.firefly/package.ff +2 -2
  15. package/core/Any.ff +25 -25
  16. package/core/Array.ff +298 -298
  17. package/core/Atomic.ff +63 -63
  18. package/core/Box.ff +7 -7
  19. package/core/BrowserSystem.ff +40 -40
  20. package/core/BuildSystem.ff +156 -156
  21. package/core/Crypto.ff +94 -94
  22. package/core/Equal.ff +41 -41
  23. package/core/Error.ff +25 -25
  24. package/core/HttpClient.ff +142 -142
  25. package/core/Instant.ff +24 -24
  26. package/core/Js.ff +305 -305
  27. package/core/JsSystem.ff +135 -135
  28. package/core/Json.ff +423 -423
  29. package/core/List.ff +482 -482
  30. package/core/Lock.ff +108 -108
  31. package/core/NodeSystem.ff +198 -198
  32. package/core/Ordering.ff +160 -160
  33. package/core/Path.ff +377 -378
  34. package/core/Queue.ff +90 -90
  35. package/core/Random.ff +140 -140
  36. package/core/RbMap.ff +216 -216
  37. package/core/Show.ff +44 -44
  38. package/core/SourceLocation.ff +68 -68
  39. package/core/Task.ff +165 -165
  40. package/experimental/benchmarks/ListGrab.ff +23 -23
  41. package/experimental/benchmarks/ListGrab.java +55 -55
  42. package/experimental/benchmarks/Pyrotek45.ff +30 -30
  43. package/experimental/benchmarks/Pyrotek45.java +64 -64
  44. package/experimental/bidirectional/Bidi.ff +88 -88
  45. package/experimental/lines/Main.ff +40 -40
  46. package/experimental/random/Index.ff +53 -53
  47. package/experimental/random/Process.ff +120 -120
  48. package/experimental/random/RunLength.ff +65 -65
  49. package/experimental/random/Scrape.ff +51 -51
  50. package/experimental/random/Symbols.ff +73 -73
  51. package/experimental/random/Tensor.ff +52 -52
  52. package/experimental/random/Units.ff +36 -36
  53. package/experimental/s3/S3TestAuthorizationHeader.ff +39 -39
  54. package/experimental/s3/S3TestPut.ff +16 -16
  55. package/experimental/tests/TestJson.ff +26 -26
  56. package/firefly.sh +0 -0
  57. package/fireflysite/.firefly/package.ff +4 -4
  58. package/fireflysite/CommunityOverview.ff +20 -20
  59. package/fireflysite/CountingButtonDemo.ff +58 -58
  60. package/fireflysite/DocumentParser.ff +325 -325
  61. package/fireflysite/ExamplesOverview.ff +40 -40
  62. package/fireflysite/FrontPage.ff +344 -344
  63. package/fireflysite/GettingStarted.ff +45 -45
  64. package/fireflysite/Guide.ff +456 -456
  65. package/fireflysite/Main.ff +163 -163
  66. package/fireflysite/MatchingPasswordsDemo.ff +82 -82
  67. package/fireflysite/PackagesOverview.ff +49 -49
  68. package/fireflysite/PostgresqlDemo.ff +34 -34
  69. package/fireflysite/ReferenceAll.ff +18 -18
  70. package/fireflysite/ReferenceIntroduction.ff +11 -11
  71. package/fireflysite/Styles.ff +567 -567
  72. package/fireflysite/Test.ff +121 -121
  73. package/fireflysite/assets/markdown/reference/BaseTypes.md +209 -209
  74. package/fireflysite/assets/markdown/reference/EmittedJavascript.md +65 -65
  75. package/fireflysite/assets/markdown/reference/Exceptions.md +101 -101
  76. package/fireflysite/assets/markdown/reference/FunctionsAndMethods.md +364 -364
  77. package/fireflysite/assets/markdown/reference/JavascriptInterop.md +235 -235
  78. package/fireflysite/assets/markdown/reference/ModulesAndPackages.md +162 -162
  79. package/fireflysite/assets/markdown/reference/OldStructuredConcurrency.md +48 -48
  80. package/fireflysite/assets/markdown/reference/PatternMatching.md +224 -224
  81. package/fireflysite/assets/markdown/reference/StatementsAndExpressions.md +86 -86
  82. package/fireflysite/assets/markdown/reference/StructuredConcurrency.md +99 -99
  83. package/fireflysite/assets/markdown/reference/TraitsAndInstances.md +100 -100
  84. package/fireflysite/assets/markdown/reference/UserDefinedTypes.md +184 -184
  85. package/fireflysite/assets/markdown/scratch/ControlFlow.md +136 -136
  86. package/fireflysite/assets/markdown/scratch/Toc.md +40 -40
  87. package/lsp/.firefly/package.ff +1 -1
  88. package/lsp/CompletionHandler.ff +827 -827
  89. package/lsp/Handler.ff +714 -714
  90. package/lsp/HoverHandler.ff +79 -79
  91. package/lsp/LanguageServer.ff +272 -272
  92. package/lsp/SignatureHelpHandler.ff +55 -55
  93. package/lsp/SymbolHandler.ff +181 -181
  94. package/lsp/TestReferences.ff +17 -17
  95. package/lsp/TestReferencesCase.ff +7 -7
  96. package/lsp/stderr.txt +1 -1
  97. package/lsp/stdout.txt +34 -34
  98. package/lux/.firefly/package.ff +1 -1
  99. package/lux/Css.ff +648 -648
  100. package/lux/CssTest.ff +48 -48
  101. package/lux/Lux.ff +608 -608
  102. package/lux/LuxEvent.ff +79 -79
  103. package/lux/Main.ff +123 -123
  104. package/lux/Main2.ff +143 -143
  105. package/lux/TestDry.ff +28 -28
  106. package/output/js/ff/compiler/Builder.mjs +36 -36
  107. package/output/js/ff/core/Path.mjs +0 -2
  108. package/package.json +1 -1
  109. package/rpc/.firefly/package.ff +1 -1
  110. package/rpc/Rpc.ff +70 -70
  111. package/s3/.firefly/package.ff +1 -1
  112. package/s3/S3.ff +92 -92
  113. package/vscode/LICENSE.txt +21 -21
  114. package/vscode/Prepublish.ff +15 -15
  115. package/vscode/README.md +16 -16
  116. package/vscode/client/package-lock.json +544 -544
  117. package/vscode/client/package.json +22 -22
  118. package/vscode/client/src/extension.ts +104 -104
  119. package/vscode/icons/firefly-icon.svg +10 -10
  120. package/vscode/language-configuration.json +61 -61
  121. package/vscode/package-lock.json +3623 -3623
  122. package/vscode/package.json +1 -1
  123. package/vscode/snippets.json +241 -241
  124. package/vscode/syntaxes/firefly-markdown-injection.json +45 -45
  125. package/webserver/.firefly/include/package.json +5 -5
  126. package/webserver/.firefly/package.ff +2 -2
  127. package/webserver/WebServer.ff +647 -647
  128. package/websocket/.firefly/package.ff +1 -1
  129. package/websocket/WebSocket.ff +100 -100
@@ -1,234 +1,234 @@
1
- import Syntax
2
- import Tokenizer
3
- import ModuleCache
4
- import Parser
5
- import Resolver
6
- import Deriver
7
- import Inference
8
- import JsEmitter
9
- import Dictionaries
10
- import Dependencies
11
- import LspHook
12
-
13
- capability Compiler(
14
- emitTarget: EmitTarget
15
- task: Task
16
- compilerModulePath: Option[Path]
17
- jsOutputPath: Path
18
- packagePaths: Map[PackagePair, Path]
19
- singleFilePackages: Set[PackagePair]
20
- virtualFiles: Map[String, String]
21
- cache: ModuleCache
22
- lspHook: LspHook
23
- mutable phaseDurationDelta: Duration
24
- phaseDurations: Array[Pair[String, Duration]]
25
- )
26
-
27
- new(
28
- emitTarget: EmitTarget
29
- task: Task
30
- compilerModulePath: Option[Path]
31
- jsOutputPath: Path
32
- resolvedDependencies: ResolvedDependencies
33
- virtualFiles: Map[String, String]
34
- cache: ModuleCache
35
- lspHook: LspHook
36
- ): Compiler {
37
- Compiler(
38
- emitTarget = emitTarget
39
- task = task
40
- compilerModulePath = compilerModulePath
41
- jsOutputPath = jsOutputPath
42
- packagePaths = resolvedDependencies.packagePaths
43
- singleFilePackages = resolvedDependencies.singleFilePackages
44
- virtualFiles = virtualFiles
45
- cache = cache
46
- lspHook = lspHook
47
- phaseDurationDelta = Duration(0.0)
48
- phaseDurations = [].toArray()
49
- )
50
- }
51
-
52
- fail[T](at: Location, message: String): T {
53
- panic(message + " " + at.show())
54
- }
55
-
56
- coreImports: List[DImport] =
57
- [
58
- "Any"
59
- "Array"
60
- "AssetSystem"
61
- "Atomic"
62
- "Bool"
63
- "BrowserSystem"
64
- "Buffer"
65
- "BuildSystem"
66
- "Channel"
67
- "Char"
68
- "Core"
69
- "Crypto"
70
- "Duration"
71
- "Equal"
72
- "Error"
73
- "FileHandle"
74
- "Float"
75
- "HttpClient"
76
- "Instant"
77
- "Int"
78
- "IntMap"
79
- "Json"
80
- "JsValue"
81
- "JsSystem"
82
- "List"
83
- "Lock"
84
- "Log"
85
- "Map"
86
- "NodeSystem"
87
- "Nothing"
88
- "Option"
89
- "Ordering"
90
- "Pair"
91
- "Path"
92
- "Queue"
93
- "Random"
94
- "Serializable"
95
- "Set"
96
- "Show"
97
- "SourceLocation"
98
- "Stream"
99
- "String"
100
- "StringMap"
101
- "Task"
102
- "Try"
103
- "Unit"
104
- "Js"
105
- ].map {moduleName =>
106
- DImport(
107
- at = Location("<prelude>", 1, 1)
108
- alias = moduleName
109
- package = PackagePair("ff", "core")
110
- directory = []
111
- file = moduleName
112
- )
113
- }
114
-
115
- extend self: Compiler {
116
-
117
- measure[T](phase: String, packagePair: PackagePair, moduleName: String, body: () => T): T {
118
- let start = Duration(self.task.elapsed().seconds - self.phaseDurationDelta.seconds)
119
- let result = body()
120
- let stop = Duration(self.task.elapsed().seconds - self.phaseDurationDelta.seconds)
121
- let duration = Duration(stop.seconds - start.seconds)
122
- self.phaseDurationDelta = Duration(self.phaseDurationDelta.seconds + duration.seconds)
123
- let text = phase + " " + packagePair.groupName() + "/" + moduleName
124
- self.phaseDurations.push(Pair(text, duration))
125
- result
126
- }
127
-
128
- printMeasurements(): Unit {
129
- let worst = self.phaseDurations.toList().sortBy {
130
- (_.second.seconds + 1000000.0) + ""
131
- }.takeLast(5).reverse()
132
- worst.each {| Pair(text, duration) =>
133
- Log.debug(text + ":\t" + duration.show())
134
- }
135
- }
136
-
137
- parse(packagePair: PackagePair, moduleName: String, importedAt: Option[Location]): Module {
138
- self.cache.cacheParsedModule(self.packagePaths, packagePair, moduleName): path =>
139
- let packageName = packagePair.groupName()
140
- self.measure("Parse", packagePair, moduleName):
141
- let code = self.virtualFiles.get(path.absolute()).else {
142
- importedAt.each {at => if(!path.exists()) {
143
- throw(CompileError(at, "Imported module not found: " + packageName + "/" + moduleName))
144
- }}
145
- path.readText()
146
- }
147
- let completionAt = if(self.lspHook.isEnabled() && self.lspHook.insertIdentifier) {self.lspHook.at}
148
- let tokens = Tokenizer.tokenize(path.absolute(), code, completionAt, self.lspHook.isEnabled())
149
- let parser = Parser.new(packagePair, path.base(), tokens, self.emitTarget != EmitBrowser, self.lspHook)
150
- let module = if(self.singleFilePackages.contains(packagePair)) {
151
- parser.parseModuleWithPackageInfo().module
152
- } else {
153
- parser.parseModuleWithoutPackageInfo()
154
- }
155
- let result = module.Module(
156
- imports = [...coreImports, ...module.imports]
157
- )
158
- result
159
- }
160
-
161
- imports(module: Module): List[Module] {
162
- module.imports.map {import =>
163
- let newPackagePair = import.package
164
- let newModuleName = import.directory.map {_ + "/"}.join("") + import.file
165
- if(!self.packagePaths.contains(newPackagePair)) {
166
- throw(CompileError(import.at, "Missing dependency declaration for: " + newPackagePair.groupName()))
167
- }
168
- try {
169
- self.parse(newPackagePair, newModuleName, Some(import.at))
170
- } catch {| CompileError(_, _) @ e, error =>
171
- let newError = CompileError(import.at, "Parse error in imported module: " + import.package.groupName() + "/" + newModuleName)
172
- throw(CompileErrors([e, newError]))
173
- }
174
- }
175
- }
176
-
177
- resolve(packagePair: PackagePair, moduleName: String): Module {
178
- self.cache.cacheResolvedModule(self.packagePaths, packagePair, moduleName): path =>
179
- self.measure("Resolve", packagePair, moduleName):
180
-
181
- let module = self.parse(packagePair, moduleName, None)
182
- let otherModules = self.imports(module)
183
- let resolver = Resolver.new(packagePair, moduleName, self.lspHook)
184
- resolver.resolveModule(module, otherModules)
185
- }
186
-
187
- derive(packagePair: PackagePair, moduleName: String): Module {
188
- self.cache.cacheDerivedModule(self.packagePaths, packagePair, moduleName): path =>
189
- self.measure("Derive", packagePair, moduleName):
190
-
191
- let module = self.resolve(packagePair, moduleName)
192
- Deriver.new().deriveModule(module)
193
- }
194
-
195
- infer(packagePair: PackagePair, moduleName: String): Module {
196
- self.cache.cacheInferredModule(self.packagePaths, packagePair, moduleName): path =>
197
- self.measure("Infer", packagePair, moduleName):
198
-
199
- let module = self.derive(packagePair, moduleName)
200
- let otherModules = self.imports(module).map {i =>
201
- self.derive(i.packagePair, i.file.dropLast(".ff".size()))
202
- }
203
- let inference = Inference.new([module, ...otherModules], self.lspHook)
204
- let inferredModule = inference.inferModule(module, otherModules)
205
- Dictionaries.new([module, ...otherModules]).processModule(inferredModule, otherModules)
206
- }
207
-
208
- emit(packagePair: PackagePair, moduleName: String, isMainModule: Bool): Unit {
209
- self.cache.cacheEmittedModule(self.packagePaths, packagePair, moduleName): path =>
210
- self.measure("Emit", packagePair, moduleName):
211
-
212
- let module = self.infer(packagePair, moduleName)
213
- let otherModules = self.imports(module).map {i =>
214
- let newModuleName = i.file.dropLast(".ff".size())
215
- self.emit(i.packagePair, newModuleName, isMainModule = False)
216
- self.infer(i.packagePair, newModuleName)
217
- }
218
-
219
- let allModules = [module, ...otherModules]
220
- let js = JsEmitter.new(
221
- otherModules = allModules
222
- emitTarget = self.emitTarget
223
- isMainModule = isMainModule
224
- compilerModuleFileUrl = self.compilerModulePath.map {_.url()}
225
- packagePair = packagePair
226
- moduleName = moduleName
227
- ).emitModule(packagePair, module)
228
- let jsPath = self.jsOutputPath.slash(packagePair.group).slash(packagePair.name)
229
- let jsFile = jsPath.slash(moduleName + ".mjs")
230
- jsPath.createDirectory(createParentDirectories = True)
231
- jsFile.writeText(js)
232
- }
233
-
234
- }
1
+ import Syntax
2
+ import Tokenizer
3
+ import ModuleCache
4
+ import Parser
5
+ import Resolver
6
+ import Deriver
7
+ import Inference
8
+ import JsEmitter
9
+ import Dictionaries
10
+ import Dependencies
11
+ import LspHook
12
+
13
+ capability Compiler(
14
+ emitTarget: EmitTarget
15
+ task: Task
16
+ compilerModulePath: Option[Path]
17
+ jsOutputPath: Path
18
+ packagePaths: Map[PackagePair, Path]
19
+ singleFilePackages: Set[PackagePair]
20
+ virtualFiles: Map[String, String]
21
+ cache: ModuleCache
22
+ lspHook: LspHook
23
+ mutable phaseDurationDelta: Duration
24
+ phaseDurations: Array[Pair[String, Duration]]
25
+ )
26
+
27
+ new(
28
+ emitTarget: EmitTarget
29
+ task: Task
30
+ compilerModulePath: Option[Path]
31
+ jsOutputPath: Path
32
+ resolvedDependencies: ResolvedDependencies
33
+ virtualFiles: Map[String, String]
34
+ cache: ModuleCache
35
+ lspHook: LspHook
36
+ ): Compiler {
37
+ Compiler(
38
+ emitTarget = emitTarget
39
+ task = task
40
+ compilerModulePath = compilerModulePath
41
+ jsOutputPath = jsOutputPath
42
+ packagePaths = resolvedDependencies.packagePaths
43
+ singleFilePackages = resolvedDependencies.singleFilePackages
44
+ virtualFiles = virtualFiles
45
+ cache = cache
46
+ lspHook = lspHook
47
+ phaseDurationDelta = Duration(0.0)
48
+ phaseDurations = [].toArray()
49
+ )
50
+ }
51
+
52
+ fail[T](at: Location, message: String): T {
53
+ panic(message + " " + at.show())
54
+ }
55
+
56
+ coreImports: List[DImport] =
57
+ [
58
+ "Any"
59
+ "Array"
60
+ "AssetSystem"
61
+ "Atomic"
62
+ "Bool"
63
+ "BrowserSystem"
64
+ "Buffer"
65
+ "BuildSystem"
66
+ "Channel"
67
+ "Char"
68
+ "Core"
69
+ "Crypto"
70
+ "Duration"
71
+ "Equal"
72
+ "Error"
73
+ "FileHandle"
74
+ "Float"
75
+ "HttpClient"
76
+ "Instant"
77
+ "Int"
78
+ "IntMap"
79
+ "Json"
80
+ "JsValue"
81
+ "JsSystem"
82
+ "List"
83
+ "Lock"
84
+ "Log"
85
+ "Map"
86
+ "NodeSystem"
87
+ "Nothing"
88
+ "Option"
89
+ "Ordering"
90
+ "Pair"
91
+ "Path"
92
+ "Queue"
93
+ "Random"
94
+ "Serializable"
95
+ "Set"
96
+ "Show"
97
+ "SourceLocation"
98
+ "Stream"
99
+ "String"
100
+ "StringMap"
101
+ "Task"
102
+ "Try"
103
+ "Unit"
104
+ "Js"
105
+ ].map {moduleName =>
106
+ DImport(
107
+ at = Location("<prelude>", 1, 1)
108
+ alias = moduleName
109
+ package = PackagePair("ff", "core")
110
+ directory = []
111
+ file = moduleName
112
+ )
113
+ }
114
+
115
+ extend self: Compiler {
116
+
117
+ measure[T](phase: String, packagePair: PackagePair, moduleName: String, body: () => T): T {
118
+ let start = Duration(self.task.elapsed().seconds - self.phaseDurationDelta.seconds)
119
+ let result = body()
120
+ let stop = Duration(self.task.elapsed().seconds - self.phaseDurationDelta.seconds)
121
+ let duration = Duration(stop.seconds - start.seconds)
122
+ self.phaseDurationDelta = Duration(self.phaseDurationDelta.seconds + duration.seconds)
123
+ let text = phase + " " + packagePair.groupName() + "/" + moduleName
124
+ self.phaseDurations.push(Pair(text, duration))
125
+ result
126
+ }
127
+
128
+ printMeasurements(): Unit {
129
+ let worst = self.phaseDurations.toList().sortBy {
130
+ (_.second.seconds + 1000000.0) + ""
131
+ }.takeLast(5).reverse()
132
+ worst.each {| Pair(text, duration) =>
133
+ Log.debug(text + ":\t" + duration.show())
134
+ }
135
+ }
136
+
137
+ parse(packagePair: PackagePair, moduleName: String, importedAt: Option[Location]): Module {
138
+ self.cache.cacheParsedModule(self.packagePaths, packagePair, moduleName): path =>
139
+ let packageName = packagePair.groupName()
140
+ self.measure("Parse", packagePair, moduleName):
141
+ let code = self.virtualFiles.get(path.absolute()).else {
142
+ importedAt.each {at => if(!path.exists()) {
143
+ throw(CompileError(at, "Imported module not found: " + packageName + "/" + moduleName))
144
+ }}
145
+ path.readText()
146
+ }
147
+ let completionAt = if(self.lspHook.isEnabled() && self.lspHook.insertIdentifier) {self.lspHook.at}
148
+ let tokens = Tokenizer.tokenize(path.absolute(), code, completionAt, self.lspHook.isEnabled())
149
+ let parser = Parser.new(packagePair, path.base(), tokens, self.emitTarget != EmitBrowser, self.lspHook)
150
+ let module = if(self.singleFilePackages.contains(packagePair)) {
151
+ parser.parseModuleWithPackageInfo().module
152
+ } else {
153
+ parser.parseModuleWithoutPackageInfo()
154
+ }
155
+ let result = module.Module(
156
+ imports = [...coreImports, ...module.imports]
157
+ )
158
+ result
159
+ }
160
+
161
+ imports(module: Module): List[Module] {
162
+ module.imports.map {import =>
163
+ let newPackagePair = import.package
164
+ let newModuleName = import.directory.map {_ + "/"}.join("") + import.file
165
+ if(!self.packagePaths.contains(newPackagePair)) {
166
+ throw(CompileError(import.at, "Missing dependency declaration for: " + newPackagePair.groupName()))
167
+ }
168
+ try {
169
+ self.parse(newPackagePair, newModuleName, Some(import.at))
170
+ } catch {| CompileError(_, _) @ e, error =>
171
+ let newError = CompileError(import.at, "Parse error in imported module: " + import.package.groupName() + "/" + newModuleName)
172
+ throw(CompileErrors([e, newError]))
173
+ }
174
+ }
175
+ }
176
+
177
+ resolve(packagePair: PackagePair, moduleName: String): Module {
178
+ self.cache.cacheResolvedModule(self.packagePaths, packagePair, moduleName): path =>
179
+ self.measure("Resolve", packagePair, moduleName):
180
+
181
+ let module = self.parse(packagePair, moduleName, None)
182
+ let otherModules = self.imports(module)
183
+ let resolver = Resolver.new(packagePair, moduleName, self.lspHook)
184
+ resolver.resolveModule(module, otherModules)
185
+ }
186
+
187
+ derive(packagePair: PackagePair, moduleName: String): Module {
188
+ self.cache.cacheDerivedModule(self.packagePaths, packagePair, moduleName): path =>
189
+ self.measure("Derive", packagePair, moduleName):
190
+
191
+ let module = self.resolve(packagePair, moduleName)
192
+ Deriver.new().deriveModule(module)
193
+ }
194
+
195
+ infer(packagePair: PackagePair, moduleName: String): Module {
196
+ self.cache.cacheInferredModule(self.packagePaths, packagePair, moduleName): path =>
197
+ self.measure("Infer", packagePair, moduleName):
198
+
199
+ let module = self.derive(packagePair, moduleName)
200
+ let otherModules = self.imports(module).map {i =>
201
+ self.derive(i.packagePair, i.file.dropLast(".ff".size()))
202
+ }
203
+ let inference = Inference.new([module, ...otherModules], self.lspHook)
204
+ let inferredModule = inference.inferModule(module, otherModules)
205
+ Dictionaries.new([module, ...otherModules]).processModule(inferredModule, otherModules)
206
+ }
207
+
208
+ emit(packagePair: PackagePair, moduleName: String, isMainModule: Bool): Unit {
209
+ self.cache.cacheEmittedModule(self.packagePaths, packagePair, moduleName): path =>
210
+ self.measure("Emit", packagePair, moduleName):
211
+
212
+ let module = self.infer(packagePair, moduleName)
213
+ let otherModules = self.imports(module).map {i =>
214
+ let newModuleName = i.file.dropLast(".ff".size())
215
+ self.emit(i.packagePair, newModuleName, isMainModule = False)
216
+ self.infer(i.packagePair, newModuleName)
217
+ }
218
+
219
+ let allModules = [module, ...otherModules]
220
+ let js = JsEmitter.new(
221
+ otherModules = allModules
222
+ emitTarget = self.emitTarget
223
+ isMainModule = isMainModule
224
+ compilerModuleFileUrl = self.compilerModulePath.map {_.url()}
225
+ packagePair = packagePair
226
+ moduleName = moduleName
227
+ ).emitModule(packagePair, module)
228
+ let jsPath = self.jsOutputPath.slash(packagePair.group).slash(packagePair.name)
229
+ let jsFile = jsPath.slash(moduleName + ".mjs")
230
+ jsPath.createDirectory(createParentDirectories = True)
231
+ jsFile.writeText(js)
232
+ }
233
+
234
+ }