firefly-compiler 0.5.35 → 0.5.36

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 (225) hide show
  1. package/.hintrc +4 -4
  2. package/.vscode/settings.json +4 -4
  3. package/bin/Release.ff +157 -154
  4. package/bin/firefly.mjs +1 -1
  5. package/compiler/Builder.ff +275 -277
  6. package/compiler/Compiler.ff +234 -233
  7. package/compiler/Dependencies.ff +186 -187
  8. package/compiler/DependencyLock.ff +17 -17
  9. package/compiler/Deriver.ff +23 -31
  10. package/compiler/Dictionaries.ff +1 -1
  11. package/compiler/Inference.ff +43 -20
  12. package/compiler/JsEmitter.ff +1437 -1282
  13. package/compiler/LspHook.ff +202 -202
  14. package/compiler/Main.ff +25 -24
  15. package/compiler/ModuleCache.ff +178 -178
  16. package/compiler/Parser.ff +36 -109
  17. package/compiler/Resolver.ff +5 -8
  18. package/compiler/Substitution.ff +1 -1
  19. package/compiler/Syntax.ff +1 -16
  20. package/compiler/Token.ff +9 -0
  21. package/compiler/Tokenizer.ff +4 -0
  22. package/compiler/Workspace.ff +88 -88
  23. package/core/.firefly/include/package.json +5 -5
  24. package/core/.firefly/package.ff +2 -2
  25. package/core/Any.ff +26 -30
  26. package/core/Array.ff +298 -265
  27. package/core/Atomic.ff +63 -64
  28. package/core/Box.ff +7 -7
  29. package/core/BrowserSystem.ff +40 -40
  30. package/core/Buffer.ff +185 -152
  31. package/core/BuildSystem.ff +156 -148
  32. package/core/Channel.ff +95 -92
  33. package/core/Char.ff +3 -2
  34. package/core/Core.ff +16 -23
  35. package/core/Crypto.ff +94 -96
  36. package/core/Equal.ff +41 -36
  37. package/core/Error.ff +15 -10
  38. package/core/FileHandle.ff +45 -37
  39. package/core/Float.ff +176 -200
  40. package/core/HttpClient.ff +142 -148
  41. package/core/Instant.ff +6 -8
  42. package/core/Int.ff +40 -24
  43. package/core/IntMap.ff +61 -39
  44. package/core/Js.ff +305 -0
  45. package/core/JsSystem.ff +135 -114
  46. package/core/JsValue.ff +303 -159
  47. package/core/Json.ff +423 -443
  48. package/core/List.ff +482 -486
  49. package/core/Lock.ff +108 -144
  50. package/core/Log.ff +25 -14
  51. package/core/NodeSystem.ff +198 -191
  52. package/core/Ordering.ff +160 -161
  53. package/core/Path.ff +377 -409
  54. package/core/Queue.ff +90 -0
  55. package/core/Random.ff +140 -134
  56. package/core/RbMap.ff +216 -216
  57. package/core/Serializable.ff +16 -13
  58. package/core/Show.ff +44 -43
  59. package/core/SourceLocation.ff +68 -68
  60. package/core/Stream.ff +1 -1
  61. package/core/String.ff +224 -202
  62. package/core/StringMap.ff +58 -36
  63. package/core/Task.ff +165 -149
  64. package/experimental/benchmarks/ListGrab.ff +23 -23
  65. package/experimental/benchmarks/ListGrab.java +55 -55
  66. package/experimental/benchmarks/Pyrotek45.ff +30 -30
  67. package/experimental/benchmarks/Pyrotek45.java +64 -64
  68. package/experimental/bidirectional/Bidi.ff +88 -88
  69. package/experimental/lines/Main.ff +40 -0
  70. package/experimental/random/Index.ff +53 -53
  71. package/experimental/random/Process.ff +120 -120
  72. package/experimental/random/RunLength.ff +65 -65
  73. package/experimental/random/Scrape.ff +51 -51
  74. package/experimental/random/Symbols.ff +73 -73
  75. package/experimental/random/Tensor.ff +52 -52
  76. package/experimental/random/Units.ff +36 -36
  77. package/experimental/s3/S3TestAuthorizationHeader.ff +39 -39
  78. package/experimental/s3/S3TestPut.ff +16 -16
  79. package/experimental/tests/TestJson.ff +26 -26
  80. package/firefly.sh +0 -0
  81. package/fireflysite/.firefly/package.ff +4 -4
  82. package/fireflysite/CommunityOverview.ff +20 -20
  83. package/fireflysite/CountingButtonDemo.ff +58 -58
  84. package/fireflysite/DocumentParser.ff +325 -331
  85. package/fireflysite/ExamplesOverview.ff +40 -40
  86. package/fireflysite/FrontPage.ff +344 -344
  87. package/fireflysite/GettingStarted.ff +45 -45
  88. package/fireflysite/Guide.ff +456 -456
  89. package/fireflysite/Main.ff +163 -152
  90. package/fireflysite/MatchingPasswordsDemo.ff +82 -82
  91. package/fireflysite/PackagesOverview.ff +49 -49
  92. package/fireflysite/PostgresqlDemo.ff +34 -34
  93. package/fireflysite/ReferenceAll.ff +18 -18
  94. package/fireflysite/ReferenceIntroduction.ff +11 -11
  95. package/fireflysite/Styles.ff +567 -567
  96. package/fireflysite/Test.ff +121 -62
  97. package/fireflysite/assets/markdown/reference/BaseTypes.md +209 -209
  98. package/fireflysite/assets/markdown/reference/EmittedJavascript.md +65 -65
  99. package/fireflysite/assets/markdown/reference/Exceptions.md +101 -101
  100. package/fireflysite/assets/markdown/reference/FunctionsAndMethods.md +364 -364
  101. package/fireflysite/assets/markdown/reference/JavascriptInterop.md +235 -172
  102. package/fireflysite/assets/markdown/reference/ModulesAndPackages.md +162 -162
  103. package/fireflysite/assets/markdown/reference/OldStructuredConcurrency.md +48 -48
  104. package/fireflysite/assets/markdown/reference/PatternMatching.md +224 -224
  105. package/fireflysite/assets/markdown/reference/StatementsAndExpressions.md +86 -86
  106. package/fireflysite/assets/markdown/reference/StructuredConcurrency.md +99 -99
  107. package/fireflysite/assets/markdown/reference/TraitsAndInstances.md +100 -100
  108. package/fireflysite/assets/markdown/reference/UserDefinedTypes.md +184 -184
  109. package/fireflysite/assets/markdown/scratch/ControlFlow.md +136 -136
  110. package/fireflysite/assets/markdown/scratch/Toc.md +40 -40
  111. package/lsp/.firefly/package.ff +1 -1
  112. package/lsp/CompletionHandler.ff +827 -827
  113. package/lsp/Handler.ff +714 -714
  114. package/lsp/HoverHandler.ff +79 -79
  115. package/lsp/LanguageServer.ff +272 -272
  116. package/lsp/SignatureHelpHandler.ff +55 -55
  117. package/lsp/SymbolHandler.ff +181 -181
  118. package/lsp/TestReferences.ff +17 -17
  119. package/lsp/TestReferencesCase.ff +7 -7
  120. package/lsp/stderr.txt +1 -1
  121. package/lsp/stdout.txt +34 -34
  122. package/lux/.firefly/package.ff +1 -1
  123. package/lux/Css.ff +648 -648
  124. package/lux/CssTest.ff +48 -48
  125. package/lux/Lux.ff +608 -617
  126. package/lux/LuxEvent.ff +79 -116
  127. package/lux/Main.ff +123 -123
  128. package/lux/Main2.ff +143 -143
  129. package/lux/TestDry.ff +28 -28
  130. package/output/js/ff/compiler/Builder.mjs +72 -71
  131. package/output/js/ff/compiler/Compiler.mjs +19 -13
  132. package/output/js/ff/compiler/Dependencies.mjs +8 -7
  133. package/output/js/ff/compiler/DependencyLock.mjs +6 -4
  134. package/output/js/ff/compiler/Deriver.mjs +26 -24
  135. package/output/js/ff/compiler/Dictionaries.mjs +14 -18
  136. package/output/js/ff/compiler/Environment.mjs +6 -4
  137. package/output/js/ff/compiler/Inference.mjs +238 -164
  138. package/output/js/ff/compiler/JsEmitter.mjs +1160 -350
  139. package/output/js/ff/compiler/JsImporter.mjs +20 -18
  140. package/output/js/ff/compiler/LspHook.mjs +12 -10
  141. package/output/js/ff/compiler/Main.mjs +61 -41
  142. package/output/js/ff/compiler/ModuleCache.mjs +10 -8
  143. package/output/js/ff/compiler/Parser.mjs +153 -669
  144. package/output/js/ff/compiler/Patterns.mjs +12 -10
  145. package/output/js/ff/compiler/Resolver.mjs +52 -78
  146. package/output/js/ff/compiler/Substitution.mjs +12 -16
  147. package/output/js/ff/compiler/Syntax.mjs +50 -341
  148. package/output/js/ff/compiler/Token.mjs +126 -4
  149. package/output/js/ff/compiler/Tokenizer.mjs +62 -52
  150. package/output/js/ff/compiler/Unification.mjs +74 -90
  151. package/output/js/ff/compiler/Wildcards.mjs +4 -2
  152. package/output/js/ff/compiler/Workspace.mjs +26 -20
  153. package/output/js/ff/core/Any.mjs +20 -20
  154. package/output/js/ff/core/Array.mjs +268 -175
  155. package/output/js/ff/core/AssetSystem.mjs +8 -6
  156. package/output/js/ff/core/Atomic.mjs +84 -52
  157. package/output/js/ff/core/Bool.mjs +6 -4
  158. package/output/js/ff/core/BrowserSystem.mjs +38 -29
  159. package/output/js/ff/core/Buffer.mjs +285 -133
  160. package/output/js/ff/core/BuildSystem.mjs +36 -56
  161. package/output/js/ff/core/Channel.mjs +250 -97
  162. package/output/js/ff/core/Char.mjs +5 -3
  163. package/output/js/ff/core/Core.mjs +28 -34
  164. package/output/js/ff/core/Crypto.mjs +30 -52
  165. package/output/js/ff/core/Duration.mjs +4 -2
  166. package/output/js/ff/core/Equal.mjs +14 -12
  167. package/output/js/ff/core/Error.mjs +17 -11
  168. package/output/js/ff/core/FileHandle.mjs +76 -38
  169. package/output/js/ff/core/Float.mjs +92 -160
  170. package/output/js/ff/core/HttpClient.mjs +208 -76
  171. package/output/js/ff/core/Instant.mjs +8 -10
  172. package/output/js/ff/core/Int.mjs +36 -26
  173. package/output/js/ff/core/IntMap.mjs +79 -33
  174. package/output/js/ff/core/Js.mjs +751 -0
  175. package/output/js/ff/core/JsSystem.mjs +54 -60
  176. package/output/js/ff/core/JsValue.mjs +294 -143
  177. package/output/js/ff/core/Json.mjs +443 -253
  178. package/output/js/ff/core/List.mjs +262 -214
  179. package/output/js/ff/core/Lock.mjs +156 -125
  180. package/output/js/ff/core/Log.mjs +20 -10
  181. package/output/js/ff/core/Map.mjs +10 -8
  182. package/output/js/ff/core/NodeSystem.mjs +189 -123
  183. package/output/js/ff/core/Nothing.mjs +4 -2
  184. package/output/js/ff/core/Option.mjs +40 -38
  185. package/output/js/ff/core/Ordering.mjs +26 -20
  186. package/output/js/ff/core/Pair.mjs +4 -2
  187. package/output/js/ff/core/Path.mjs +517 -315
  188. package/output/js/ff/core/Queue.mjs +306 -0
  189. package/output/js/ff/core/Random.mjs +141 -77
  190. package/output/js/ff/core/RbMap.mjs +36 -34
  191. package/output/js/ff/core/Serializable.mjs +44 -28
  192. package/output/js/ff/core/Set.mjs +6 -4
  193. package/output/js/ff/core/Show.mjs +8 -6
  194. package/output/js/ff/core/SourceLocation.mjs +4 -2
  195. package/output/js/ff/core/Stream.mjs +30 -50
  196. package/output/js/ff/core/String.mjs +263 -172
  197. package/output/js/ff/core/StringMap.mjs +77 -31
  198. package/output/js/ff/core/Task.mjs +91 -76
  199. package/output/js/ff/core/Try.mjs +20 -18
  200. package/output/js/ff/core/Unit.mjs +4 -2
  201. package/package.json +1 -1
  202. package/postgresql/Pg.ff +53 -59
  203. package/rpc/.firefly/package.ff +1 -1
  204. package/rpc/Rpc.ff +70 -70
  205. package/s3/.firefly/package.ff +1 -1
  206. package/s3/S3.ff +92 -94
  207. package/vscode/LICENSE.txt +21 -21
  208. package/vscode/Prepublish.ff +15 -15
  209. package/vscode/README.md +16 -16
  210. package/vscode/client/package-lock.json +544 -544
  211. package/vscode/client/package.json +22 -22
  212. package/vscode/client/src/extension.ts +104 -104
  213. package/vscode/icons/firefly-icon.svg +10 -10
  214. package/vscode/language-configuration.json +61 -61
  215. package/vscode/package-lock.json +3623 -3623
  216. package/vscode/package.json +1 -1
  217. package/vscode/snippets.json +241 -241
  218. package/vscode/syntaxes/firefly-markdown-injection.json +45 -45
  219. package/webserver/.firefly/include/package.json +5 -5
  220. package/webserver/.firefly/package.ff +2 -2
  221. package/webserver/WebServer.ff +647 -685
  222. package/websocket/.firefly/package.ff +1 -1
  223. package/websocket/WebSocket.ff +100 -131
  224. package/core/UnsafeJs.ff +0 -42
  225. package/output/js/ff/core/UnsafeJs.mjs +0 -191
@@ -1,187 +1,186 @@
1
- import Parser
2
- import Syntax
3
- import Tokenizer
4
- import Workspace
5
- import LspHook
6
- import DependencyLock
7
-
8
- capability Dependencies(
9
- workspace: Workspace
10
- mutable packages: Map[PackagePair, PackageInfo]
11
- mutable packagePaths: Map[PackagePair, Path]
12
- mutable singleFilePackages: Set[PackagePair]
13
- )
14
-
15
- capability ResolvedDependencies(
16
- mainPackagePair: PackagePair
17
- packages: Map[PackagePair, PackageInfo]
18
- packagePaths: Map[PackagePair, Path]
19
- singleFilePackages: Set[PackagePair]
20
- )
21
-
22
- extend self: Dependencies {
23
-
24
- loadPackageInfo(
25
- packagePair: PackagePair
26
- path: Path
27
- ): PackageInfo {
28
- let packageDirectory = if(path.extension() == ".ff") {path.parent().grab()} else {path}
29
- let sharedPackageFile = packageDirectory.slash(".firefly").slash("package.ff")
30
- let packageFile = if(sharedPackageFile.exists()) {
31
- sharedPackageFile
32
- } else {
33
- self.singleFilePackages = self.singleFilePackages.add(packagePair)
34
- path
35
- }
36
- let code = packageFile.readText()
37
- self.parsePackageFile(packagePair, packageFile.relativeTo(path), code)
38
- }
39
-
40
- parsePackageFile(
41
- packagePair: PackagePair
42
- fileName: String
43
- code: String
44
- ): PackageInfo {
45
- let tokens = Tokenizer.tokenize(fileName, code, None, True)
46
- let parser = Parser.new(packagePair, fileName, tokens, False, LspHook.disabled())
47
- let info = parser.parsePackageInfo()
48
- self.addCoreDependencyIfMissing(info)
49
- }
50
-
51
- addCoreDependencyIfMissing(info: PackageInfo): PackageInfo {
52
- if(info.dependencies.any {d =>
53
- d.packagePair.group == "ff" && d.packagePair.name == "core"
54
- }) {
55
- info
56
- } else {
57
- let coreDependency = DDependency(
58
- at = info.package.at
59
- packagePair = PackagePair("ff", "core")
60
- version = Version(info.package.at, 0, 0, 0)
61
- safety = Trusted
62
- targets = info.package.targets
63
- )
64
- info.PackageInfo(dependencies = [coreDependency, ...info.dependencies])
65
- }
66
- }
67
-
68
- processPackageInfo(
69
- packageInfo: PackageInfo
70
- ): List[DDependency] {
71
- self.packages = self.packages.add(packageInfo.package.packagePair, packageInfo)
72
- packageInfo.dependencies.filter {!self.packages.contains(_.packagePair)}
73
- }
74
-
75
- fetchDependency(
76
- path: Path
77
- httpClient: HttpClient
78
- dependencyLock: DependencyLock
79
- dependency: DDependency
80
- ): Path {
81
- let location = self.workspace.findPackageLocation(dependency.packagePair, dependency.version)
82
- if(location.contains(":") && !location.dropFirst(1).startsWith(":")) {
83
- if(location.startsWith("http://") || location.startsWith("https://")) {
84
- let packagePair = dependency.packagePair
85
- let directory = if(path.isDirectory()) {path} else {path.parent().grab()}
86
- let dependenciesPath = directory.slash(".firefly").slash("dependencies")
87
- let dependencyPath = dependenciesPath.slash(packagePair.group).slash(packagePair.name)
88
- let tarGzPath = dependenciesPath.slash(Workspace.tarGzName(packagePair, dependency.version))
89
- let donePath = dependenciesPath.slash(Workspace.tarGzName(packagePair, dependency.version) + ".done")
90
- if(!donePath.exists()) {
91
- dependencyLock.do(donePath.absolute()) {
92
- if(!donePath.exists()) {
93
- Log.trace("Fetching " + location)
94
- let buffer = httpClient.get(location, []) {response =>
95
- if(!response.ok()) {
96
- panic("Could not download dependency: " + location)
97
- }
98
- response.readBuffer()
99
- }
100
- if(dependencyPath.exists()) {
101
- dependencyPath.delete()
102
- }
103
- dependencyPath.createDirectory(createParentDirectories = True)
104
- tarGzPath.writeStream([buffer].toStream())
105
- internalExtractTarGz(tarGzPath, dependencyPath)
106
- tarGzPath.renameTo(donePath)
107
- }
108
- }
109
- }
110
- dependencyPath
111
- } else {
112
- panic("Loading packages by this protocol is not supported: " + location)
113
- }
114
- } else {
115
- path.path(location)
116
- }
117
- }
118
-
119
- processDependencies(
120
- path: Path
121
- httpClient: HttpClient
122
- dependencyLock: DependencyLock
123
- dependencies: List[DDependency]
124
- ): Unit {
125
- // Remember to check for cycles
126
- let packageInfos = dependencies.map {dependency =>
127
- let dependencyPath = self.fetchDependency(path, httpClient, dependencyLock, dependency)
128
- self.packagePaths = self.packagePaths.add(dependency.packagePair, dependencyPath)
129
- let packageInfo = self.loadPackageInfo(dependency.packagePair, dependencyPath)
130
- checkPackagePairs(dependency.packagePair, packageInfo.package.packagePair)
131
- packageInfo
132
- }
133
- let newDependencies = packageInfos.flatMap {self.processPackageInfo(_)}
134
- if(newDependencies != []) {
135
- self.processDependencies(path, httpClient, dependencyLock, newDependencies)
136
- }
137
- }
138
-
139
- }
140
-
141
- process(fetch: HttpClient, dependencyLock: DependencyLock, path: Path): ResolvedDependencies {
142
- let workspace = Workspace.loadWorkspace(path)
143
- let self = Dependencies(workspace, [].toMap(), [].toMap(), [].toSet())
144
- let packageInfo = self.loadPackageInfo(PackagePair("script", "script"), path)
145
- let newDependencies = self.processPackageInfo(packageInfo)
146
- self.processDependencies(path, fetch, dependencyLock, newDependencies)
147
- let packagePaths = self.packagePaths.add(packageInfo.package.packagePair, findScriptPackageLocation(path))
148
- ResolvedDependencies(
149
- mainPackagePair = packageInfo.package.packagePair
150
- packages = self.packages
151
- packagePaths = packagePaths
152
- singleFilePackages = self.singleFilePackages
153
- )
154
- }
155
-
156
- findScriptPackageLocation(path: Path): Path {
157
- let packageDirectory = if(path.extension() == ".ff") {path.parent().grab()} else {path}
158
- function go(directory: Path): Path {
159
- let packageFile = directory.slash(".firefly").slash("package.ff")
160
- if(packageFile.exists()) {
161
- directory
162
- } elseIf {!directory.parent().isEmpty()} {
163
- go(directory.parent().grab())
164
- } else {
165
- packageDirectory
166
- }
167
- }
168
- go(packageDirectory)
169
- }
170
-
171
- checkPackagePairs(dependencyPair: PackagePair, packagePair: PackagePair): Unit {
172
- if(
173
- packagePair.group != dependencyPair.group ||
174
- packagePair.name != dependencyPair.name
175
- ) {
176
- panic(
177
- "Dependency declaration and package declaration disagree on package name: " +
178
- dependencyPair.groupName() + " vs. " + packagePair.groupName()
179
- )
180
- }
181
- }
182
-
183
- internalExtractTarGz(tarGzPath: Path, path: Path): Unit
184
- target node async """
185
- import * as tar from 'tar'
186
- await tar.extract({file: tarGzPath_, cwd: path_, strict: true})
187
- """
1
+ import Parser
2
+ import Syntax
3
+ import Tokenizer
4
+ import Workspace
5
+ import LspHook
6
+ import DependencyLock
7
+
8
+ capability Dependencies(
9
+ workspace: Workspace
10
+ mutable packages: Map[PackagePair, PackageInfo]
11
+ mutable packagePaths: Map[PackagePair, Path]
12
+ mutable singleFilePackages: Set[PackagePair]
13
+ )
14
+
15
+ capability ResolvedDependencies(
16
+ mainPackagePair: PackagePair
17
+ packages: Map[PackagePair, PackageInfo]
18
+ packagePaths: Map[PackagePair, Path]
19
+ singleFilePackages: Set[PackagePair]
20
+ )
21
+
22
+ extend self: Dependencies {
23
+
24
+ loadPackageInfo(
25
+ packagePair: PackagePair
26
+ path: Path
27
+ ): PackageInfo {
28
+ let packageDirectory = if(path.extension() == ".ff") {path.parent().grab()} else {path}
29
+ let sharedPackageFile = packageDirectory.slash(".firefly").slash("package.ff")
30
+ let packageFile = if(sharedPackageFile.exists()) {
31
+ sharedPackageFile
32
+ } else {
33
+ self.singleFilePackages = self.singleFilePackages.add(packagePair)
34
+ path
35
+ }
36
+ let code = packageFile.readText()
37
+ self.parsePackageFile(packagePair, packageFile.relativeTo(path), code)
38
+ }
39
+
40
+ parsePackageFile(
41
+ packagePair: PackagePair
42
+ fileName: String
43
+ code: String
44
+ ): PackageInfo {
45
+ let tokens = Tokenizer.tokenize(fileName, code, None, True)
46
+ let parser = Parser.new(packagePair, fileName, tokens, False, LspHook.disabled())
47
+ let info = parser.parsePackageInfo()
48
+ self.addCoreDependencyIfMissing(info)
49
+ }
50
+
51
+ addCoreDependencyIfMissing(info: PackageInfo): PackageInfo {
52
+ if(info.dependencies.any {d =>
53
+ d.packagePair.group == "ff" && d.packagePair.name == "core"
54
+ }) {
55
+ info
56
+ } else {
57
+ let coreDependency = DDependency(
58
+ at = info.package.at
59
+ packagePair = PackagePair("ff", "core")
60
+ version = Version(info.package.at, 0, 0, 0)
61
+ safety = Trusted
62
+ targets = info.package.targets
63
+ )
64
+ info.PackageInfo(dependencies = [coreDependency, ...info.dependencies])
65
+ }
66
+ }
67
+
68
+ processPackageInfo(
69
+ packageInfo: PackageInfo
70
+ ): List[DDependency] {
71
+ self.packages = self.packages.add(packageInfo.package.packagePair, packageInfo)
72
+ packageInfo.dependencies.filter {!self.packages.contains(_.packagePair)}
73
+ }
74
+
75
+ fetchDependency(
76
+ path: Path
77
+ httpClient: HttpClient
78
+ dependencyLock: DependencyLock
79
+ dependency: DDependency
80
+ ): Path {
81
+ let location = self.workspace.findPackageLocation(dependency.packagePair, dependency.version)
82
+ if(location.contains(":") && !location.dropFirst(1).startsWith(":")) {
83
+ if(location.startsWith("http://") || location.startsWith("https://")) {
84
+ let packagePair = dependency.packagePair
85
+ let directory = if(path.isDirectory()) {path} else {path.parent().grab()}
86
+ let dependenciesPath = directory.slash(".firefly").slash("dependencies")
87
+ let dependencyPath = dependenciesPath.slash(packagePair.group).slash(packagePair.name)
88
+ let tarGzPath = dependenciesPath.slash(Workspace.tarGzName(packagePair, dependency.version))
89
+ let donePath = dependenciesPath.slash(Workspace.tarGzName(packagePair, dependency.version) + ".done")
90
+ if(!donePath.exists()) {
91
+ dependencyLock.do(donePath.absolute()) {
92
+ if(!donePath.exists()) {
93
+ Log.trace("Fetching " + location)
94
+ let buffer = httpClient.get(location, []) {response =>
95
+ if(!response.ok()) {
96
+ panic("Could not download dependency: " + location)
97
+ }
98
+ response.readBuffer()
99
+ }
100
+ if(dependencyPath.exists()) {
101
+ dependencyPath.delete()
102
+ }
103
+ dependencyPath.createDirectory(createParentDirectories = True)
104
+ tarGzPath.writeStream([buffer].toStream())
105
+ internalExtractTarGz(tarGzPath, dependencyPath)
106
+ tarGzPath.renameTo(donePath)
107
+ }
108
+ }
109
+ }
110
+ dependencyPath
111
+ } else {
112
+ panic("Loading packages by this protocol is not supported: " + location)
113
+ }
114
+ } else {
115
+ path.path(location)
116
+ }
117
+ }
118
+
119
+ processDependencies(
120
+ path: Path
121
+ httpClient: HttpClient
122
+ dependencyLock: DependencyLock
123
+ dependencies: List[DDependency]
124
+ ): Unit {
125
+ // Remember to check for cycles
126
+ let packageInfos = dependencies.map {dependency =>
127
+ let dependencyPath = self.fetchDependency(path, httpClient, dependencyLock, dependency)
128
+ self.packagePaths = self.packagePaths.add(dependency.packagePair, dependencyPath)
129
+ let packageInfo = self.loadPackageInfo(dependency.packagePair, dependencyPath)
130
+ checkPackagePairs(dependency.packagePair, packageInfo.package.packagePair)
131
+ packageInfo
132
+ }
133
+ let newDependencies = packageInfos.flatMap {self.processPackageInfo(_)}
134
+ if(newDependencies != []) {
135
+ self.processDependencies(path, httpClient, dependencyLock, newDependencies)
136
+ }
137
+ }
138
+
139
+ }
140
+
141
+ process(fetch: HttpClient, dependencyLock: DependencyLock, path: Path): ResolvedDependencies {
142
+ let workspace = Workspace.loadWorkspace(path)
143
+ let self = Dependencies(workspace, [].toMap(), [].toMap(), [].toSet())
144
+ let packageInfo = self.loadPackageInfo(PackagePair("script", "script"), path)
145
+ let newDependencies = self.processPackageInfo(packageInfo)
146
+ self.processDependencies(path, fetch, dependencyLock, newDependencies)
147
+ let packagePaths = self.packagePaths.add(packageInfo.package.packagePair, findScriptPackageLocation(path))
148
+ ResolvedDependencies(
149
+ mainPackagePair = packageInfo.package.packagePair
150
+ packages = self.packages
151
+ packagePaths = packagePaths
152
+ singleFilePackages = self.singleFilePackages
153
+ )
154
+ }
155
+
156
+ findScriptPackageLocation(path: Path): Path {
157
+ let packageDirectory = if(path.extension() == ".ff") {path.parent().grab()} else {path}
158
+ function go(directory: Path): Path {
159
+ let packageFile = directory.slash(".firefly").slash("package.ff")
160
+ if(packageFile.exists()) {
161
+ directory
162
+ } elseIf {!directory.parent().isEmpty()} {
163
+ go(directory.parent().grab())
164
+ } else {
165
+ packageDirectory
166
+ }
167
+ }
168
+ go(packageDirectory)
169
+ }
170
+
171
+ checkPackagePairs(dependencyPair: PackagePair, packagePair: PackagePair): Unit {
172
+ if(
173
+ packagePair.group != dependencyPair.group ||
174
+ packagePair.name != dependencyPair.name
175
+ ) {
176
+ panic(
177
+ "Dependency declaration and package declaration disagree on package name: " +
178
+ dependencyPair.groupName() + " vs. " + packagePair.groupName()
179
+ )
180
+ }
181
+ }
182
+
183
+ internalExtractTarGz(tarGzPath: Path, path: Path): Unit {
184
+ let tar = Js.import("tar")
185
+ Js.await(tar->extract(Js->(file = tarGzPath.absolutePath, cwd = path.absolutePath, strict = True)))
186
+ }
@@ -1,17 +1,17 @@
1
- capability DependencyLock(
2
- doneLocks: StringMap[Lock]
3
- task: Task
4
- )
5
-
6
- new(task: Task): DependencyLock {
7
- DependencyLock(StringMap.new(), task)
8
- }
9
-
10
- extend self: DependencyLock {
11
- do[T](doneFile: String, body: () => T): T {
12
- let lock = self.doneLocks.getOrSet(doneFile) {self.task.lock()}
13
- lock.do(reentrant = False) {
14
- body()
15
- }
16
- }
17
- }
1
+ capability DependencyLock(
2
+ doneLocks: StringMap[Lock]
3
+ task: Task
4
+ )
5
+
6
+ new(task: Task): DependencyLock {
7
+ DependencyLock(StringMap.new(), task)
8
+ }
9
+
10
+ extend self: DependencyLock {
11
+ do[T](doneFile: String, body: () => T): T {
12
+ let lock = self.doneLocks.getOrSet(doneFile) {self.task.lock()}
13
+ lock.do {
14
+ body()
15
+ }
16
+ }
17
+ }
@@ -75,18 +75,16 @@ extend self: Deriver {
75
75
  }
76
76
  let strings =
77
77
  [EString(at, "\"[\""), ...typeArgumentStrings.separate([EString(at, "\",\"")]), EString(at, "\"]\"")]
78
- let body = FireflyTarget(
79
- Lambda(at, noEffect, [MatchCase(
80
- at = at
81
- patterns = []
82
- guards = []
83
- body = self.makeSimpleCall(at, "ff:core/Any.internalAnyTag", [
84
- strings.foldLeft(EString(at, "\"" + selfTypeName + "\"")) {a, b =>
85
- self.makeSimpleCall(at, "+", [a, b])
86
- }
87
- ])
88
- )])
89
- )
78
+ let body = Lambda(at, noEffect, [MatchCase(
79
+ at = at
80
+ patterns = []
81
+ guards = []
82
+ body = self.makeSimpleCall(at, "ff:core/Any.internalAnyTag", [
83
+ strings.foldLeft(EString(at, "\"" + selfTypeName + "\"")) {a, b =>
84
+ self.makeSimpleCall(at, "+", [a, b])
85
+ }
86
+ ])
87
+ )])
90
88
  let method = DFunction(at, signature, body)
91
89
  DInstance(
92
90
  at = at
@@ -130,9 +128,8 @@ extend self: Deriver {
130
128
  returnType = TConstructor(at, "ff:core/String.String", [])
131
129
  effect = noEffect
132
130
  )
133
- let body = FireflyTarget(
131
+ let body =
134
132
  Lambda(at, noEffect, self.makeShowCases(modulePrefix, declaration, selfType))
135
- )
136
133
  let showMethod = DFunction(at, signature, body)
137
134
  DInstance(
138
135
  at = at
@@ -209,9 +206,8 @@ extend self: Deriver {
209
206
  returnType = TConstructor(at, "ff:core/Ordering.Ordering", [])
210
207
  effect = noEffect
211
208
  )
212
- let body = FireflyTarget(
209
+ let body =
213
210
  Lambda(at, noEffect, self.makeOrderingCases(modulePrefix, declaration, selfType))
214
- )
215
211
  let compareMethod = DFunction(at, signature, body)
216
212
  DInstance(
217
213
  at = at
@@ -275,12 +271,12 @@ extend self: Deriver {
275
271
  )
276
272
  }
277
273
  let differentVariant = MatchCase(
278
- at = at,
274
+ at = at
279
275
  patterns = [wildcardPattern, wildcardPattern]
280
276
  guards = []
281
277
  body =
282
- EFunctions(at,
283
- [DFunction(at, numberSignature, FireflyTarget(Lambda(at, noEffect, numberCases)))],
278
+ EFunctions(at
279
+ [DFunction(at, numberSignature, Lambda(at, noEffect, numberCases))]
284
280
  self.makeSimpleCall(at, "ff:core/Ordering.compare", [
285
281
  self.makeSimpleCall(at, "number", [EVariable(at, "x")])
286
282
  self.makeSimpleCall(at, "number", [EVariable(at, "y")])
@@ -350,9 +346,8 @@ extend self: Deriver {
350
346
  returnType = TConstructor(at, "ff:core/Bool.Bool", [])
351
347
  effect = noEffect
352
348
  )
353
- let body = FireflyTarget(
349
+ let body =
354
350
  Lambda(at, noEffect, self.makeEqualsCases(modulePrefix, declaration, selfType))
355
- )
356
351
  let equalsMethod = DFunction(at, signature, body)
357
352
  DInstance(
358
353
  at = at
@@ -484,17 +479,14 @@ extend self: Deriver {
484
479
  effect = noEffect
485
480
  )
486
481
  let wildcardPattern = PVariable(at, None)
487
- let serializeBody = FireflyTarget(
482
+ let serializeBody =
488
483
  Lambda(at, noEffect, self.makeSerializeBody(modulePrefix, declaration, selfType))
489
- )
490
- let deserializeBody = FireflyTarget(
491
- Lambda(at, noEffect, [MatchCase(
492
- at = at
493
- patterns = [wildcardPattern]
494
- guards = []
495
- body = self.makeDeserializeBody(modulePrefix, declaration, selfType)
496
- )])
497
- )
484
+ let deserializeBody = Lambda(at, noEffect, [MatchCase(
485
+ at = at
486
+ patterns = [wildcardPattern]
487
+ guards = []
488
+ body = self.makeDeserializeBody(modulePrefix, declaration, selfType)
489
+ )])
498
490
  DInstance(
499
491
  at = at
500
492
  generics = declaration.generics
@@ -53,7 +53,7 @@ extend self: Dictionaries {
53
53
  let instances = constraintsToInstances(definition.signature.constraints)
54
54
  let self2 = self.Dictionaries(instances = self.instances.addAll(instances))
55
55
  definition.DFunction(
56
- body = definition.body.mapFirefly {self2.processLambda(functions, _)}
56
+ body = self2.processLambda(functions, definition.body)
57
57
  )
58
58
  }
59
59
 
@@ -149,15 +149,13 @@ extend self: Inference {
149
149
  constraints = [...definition.constraints, ...method.signature.constraints]
150
150
  parameters = [selfParameter, ...method.signature.parameters]
151
151
  )
152
- let body = method.body.mapFirefly {lambda =>
153
- lambda.Lambda(
154
- cases = lambda.cases.map {case =>
155
- case.MatchCase(
156
- patterns = [PVariable(method.at, None), ...case.patterns]
157
- )
158
- }
159
- )
160
- }
152
+ let body = method.body.Lambda(
153
+ cases = method.body.cases.map {case =>
154
+ case.MatchCase(
155
+ patterns = [PVariable(method.at, None), ...case.patterns]
156
+ )
157
+ }
158
+ )
161
159
  let function = method.DFunction(
162
160
  signature = signature
163
161
  body = body
@@ -198,7 +196,7 @@ extend self: Inference {
198
196
  let instances = constraintsToInstances(definition.signature.constraints)
199
197
  self.unification.withLocalInstances(instances) {
200
198
  definition.DFunction(
201
- body = definition.body.mapFirefly {self.inferLambda(environment2, functionType, _)}
199
+ body = self.inferLambda(environment2, functionType, definition.body)
202
200
  )
203
201
  }
204
202
  }
@@ -765,12 +763,19 @@ extend self: Inference {
765
763
  signature: Signature
766
764
  ): Term {
767
765
  let t = signature.returnType
768
- if(operator == "+" || operator == "-") {
769
- self.unification.unify(at, t, TConstructor(at, core("Int"), []))
766
+ let newValue = self.inferTerm(environment, t, value)
767
+ if(operator == "+" || operator == "-" || operator == "*" || operator == "/") {
768
+ self.unification.substitute(t).{
769
+ | TConstructor(_, name, _) {
770
+ name == core("Int") || name == core("Float") || name == core("JsValue") ||
771
+ (name == core("String") && operator == "+")
772
+ } =>
773
+ | _ =>
774
+ self.unification.unify(at, t, TConstructor(at, core("Int"), []))
775
+ }
770
776
  } elseIf {operator != ""} {
771
- throw(CompileError(at, "Only +=, -= and = assignments are supported. Got: " + operator + "="))
777
+ throw(CompileError(at, "Only +=, -=, *=, /= and = assignments are supported. Got: " + operator + "="))
772
778
  }
773
- let newValue = self.inferTerm(environment, t, value)
774
779
  self.unification.unify(at, expected, TConstructor(at, core("Unit"), []))
775
780
  newValue
776
781
  }
@@ -818,18 +823,29 @@ extend self: Inference {
818
823
  ): Term {
819
824
  term.{
820
825
  | ECall e =>
826
+ mutable isUnsafeJsAwaitCall = False
821
827
  let tailCall = e.target.{
822
- | DynamicCall call => call.tailCall
823
- | StaticCall _ => fail(e.at, "Internal error: Static calls not expected in inferFunctionCall")
828
+ | DynamicCall call =>
829
+ call.function.{
830
+ | EVariable(_, "ff:core/Js.await") =>
831
+ isUnsafeJsAwaitCall = True
832
+ | EVariable(_, "ff:core/Js.awaitCancellablePromise") =>
833
+ isUnsafeJsAwaitCall = True
834
+ | _ =>
835
+ }
836
+ call.tailCall
837
+ | StaticCall _ =>
838
+ fail(e.at, "Internal error: Static calls not expected in inferFunctionCall")
824
839
  }
825
840
  self.unification.unify(e.at, expected, signature.returnType)
826
841
  let arguments = self.inferArguments(e.at, name, environment, signature.parameters, e.arguments)
827
- self.unification.affect(term.at, signature.effect, environment.effect)
842
+ let effect = if(isUnsafeJsAwaitCall) {TConstructor(term.at, "Q$", [])} else {signature.effect}
843
+ self.unification.affect(term.at, effect, environment.effect)
828
844
  e.ECall(
829
845
  target = StaticCall(name, instanceCall = instanceCall, tailCall = tailCall)
830
846
  typeArguments = instantiation.map {_.second}
831
847
  arguments = arguments
832
- effect = signature.effect
848
+ effect = effect
833
849
  )
834
850
  | _ => fail(term.at, "Call expected")
835
851
  }
@@ -941,6 +957,7 @@ extend self: Inference {
941
957
  let e2 = self.inferTerm(environment, t2, a2.value)
942
958
  let magic: Type => Option[String] = {t =>
943
959
  self.unification.substitute(t).{
960
+ | TConstructor(_, name, []) {name == core("JsValue")} => Some("JsValue")
944
961
  | TConstructor(_, name, []) {name == core("Float")} => Some("Float")
945
962
  | TConstructor(_, name, []) {name == core("Int")} => Some("Int")
946
963
  | TConstructor(_, name, []) {operator == "+" && name == core("String")} => Some("String")
@@ -948,6 +965,12 @@ extend self: Inference {
948
965
  }
949
966
  }
950
967
  let chooseType: (Option[String], Option[String]) => Unit = {
968
+ | Some("JsValue"), _ =>
969
+ self.unification.unify(e2.at, t1, t2)
970
+ self.unification.unify(e.at, expected, t1)
971
+ | _, Some("JsValue") =>
972
+ self.unification.unify(e1.at, t2, t1)
973
+ self.unification.unify(e.at, expected, t2)
951
974
  | Some("String"), Some(_) => self.unification.unify(e.at, expected, t1)
952
975
  | Some(_), Some("String") => self.unification.unify(e.at, expected, t2)
953
976
  | Some("Float"), Some(_) => self.unification.unify(e.at, expected, t1)
@@ -955,10 +978,10 @@ extend self: Inference {
955
978
  | Some("Int"), Some(_) => self.unification.unify(e.at, expected, t1)
956
979
  | Some(_), Some("Int") => self.unification.unify(e.at, expected, t2)
957
980
  | Some(_), None =>
958
- self.unification.unify(e.at, t1, t2)
981
+ self.unification.unify(e2.at, t1, t2)
959
982
  self.unification.unify(e.at, expected, t1)
960
983
  | None, Some(_) =>
961
- self.unification.unify(e.at, t2, t1)
984
+ self.unification.unify(e1.at, t2, t1)
962
985
  self.unification.unify(e.at, expected, t2)
963
986
  | _, _ {self.lspHook.isEnabled()} =>
964
987
  | Some(_), Some(_) =>