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,178 +1,178 @@
1
- import Syntax
2
-
3
- class ModuleCache(
4
- version: Int
5
- mutable parsedModules: Map[String, Pair[Module, Int]]
6
- mutable resolvedModules: Map[String, Pair[Module, Int]]
7
- mutable derivedModules: Map[String, Pair[Module, Int]]
8
- mutable inferredModules: Map[String, Pair[Module, Int]]
9
- mutable emittedModules: Map[String, Int]
10
- )
11
-
12
- new(version: Int): ModuleCache {
13
- ModuleCache(
14
- version = version
15
- parsedModules = Map.new()
16
- resolvedModules = Map.new()
17
- derivedModules = Map.new()
18
- inferredModules = Map.new()
19
- emittedModules = Map.new()
20
- )
21
- }
22
-
23
- extend self: ModuleCache {
24
-
25
- remove(keys: List[String]) {
26
- if(!keys.isEmpty()):
27
- self.parsedModules = self.parsedModules.removeList(keys)
28
- self.resolvedModules = self.resolvedModules.removeList(keys)
29
- self.derivedModules = self.derivedModules.removeList(keys)
30
- self.inferredModules = self.inferredModules.removeList(keys)
31
- self.emittedModules = self.emittedModules.removeList(keys)
32
- }
33
-
34
- invalidate(key: String) {
35
- //Log.trace("Invalidate: " + uri)
36
- self.parsedModules.get(key).each: | Pair(module, _) =>
37
- let moduleName = module.file.dropLast(3)
38
- self.remove([key])
39
- self.parsedModules.each {| k, Pair(m, _) =>
40
- if(m.imports.any {i => i.package == module.packagePair && i.file == moduleName}) {
41
- //Log.trace("Invalidating due to import of invalidated module: " + m.packagePair.groupName() + "/" + m.file)
42
- self.remove([k])
43
- }
44
- }
45
- }
46
-
47
- filesNotImporting(packagePair: PackagePair, moduleName: String): List[String] {
48
- self.parsedModules.toList().collect {| Pair(k, Pair(m, _)) =>
49
- if(!m.imports.any {i => i.package == packagePair && i.file == moduleName}): k
50
- }
51
- }
52
-
53
- without(newVersion: Int, path: Path): ModuleCache {
54
- let key = path.absolute()
55
- if(path.isFile()) {
56
- self.ModuleCache(
57
- version = newVersion
58
- parsedModules = self.parsedModules.remove(key)
59
- resolvedModules = self.resolvedModules.remove(key)
60
- derivedModules = self.derivedModules.remove(key)
61
- inferredModules = self.inferredModules.remove(key)
62
- emittedModules = self.emittedModules.remove(key)
63
- )
64
- } else {
65
- function invalidated(p: String): Bool {
66
- p.startsWith(key) && !p.contains(".firefly/dependencies") && !p.contains(".firefly\\dependencies")
67
- }
68
- self.ModuleCache(
69
- version = newVersion
70
- parsedModules = self.parsedModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
71
- resolvedModules = self.resolvedModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
72
- derivedModules = self.derivedModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
73
- inferredModules = self.inferredModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
74
- emittedModules = self.emittedModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
75
- )
76
- }
77
- }
78
-
79
- mergeVersions(cache: ModuleCache): Unit {
80
- self.parsedModules = mergeVersionedMap(self.parsedModules, cache.parsedModules) {_.second}
81
- self.resolvedModules = mergeVersionedMap(self.resolvedModules, cache.resolvedModules) {_.second}
82
- self.derivedModules = mergeVersionedMap(self.derivedModules, cache.derivedModules) {_.second}
83
- self.inferredModules = mergeVersionedMap(self.inferredModules, cache.inferredModules) {_.second}
84
- self.emittedModules = mergeVersionedMap(self.emittedModules, cache.emittedModules) {_}
85
- }
86
-
87
- cacheParsedModule(
88
- packagePaths: Map[PackagePair, Path]
89
- packagePair: PackagePair
90
- moduleName: String
91
- body: Path => Module
92
- ): Module {
93
- let path = modulePath(packagePaths, packagePair, moduleName)
94
- self.parsedModules.get(path.absolute()).map {_.first}.else:
95
- let result = body(path)
96
- self.parsedModules = self.parsedModules.add(path.absolute(), Pair(result, self.version))
97
- result
98
- }
99
-
100
- cacheResolvedModule(
101
- packagePaths: Map[PackagePair, Path]
102
- packagePair: PackagePair
103
- moduleName: String
104
- body: Path => Module
105
- ): Module {
106
- let path = modulePath(packagePaths, packagePair, moduleName)
107
- self.resolvedModules.get(path.absolute()).map {_.first}.else:
108
- let result = body(path)
109
- self.resolvedModules = self.resolvedModules.add(path.absolute(), Pair(result, self.version))
110
- result
111
- }
112
-
113
- cacheDerivedModule(
114
- packagePaths: Map[PackagePair, Path]
115
- packagePair: PackagePair
116
- moduleName: String
117
- body: Path => Module
118
- ): Module {
119
- let path = modulePath(packagePaths, packagePair, moduleName)
120
- self.derivedModules.get(path.absolute()).map {_.first}.else:
121
- let result = body(path)
122
- self.derivedModules = self.derivedModules.add(path.absolute(), Pair(result, self.version))
123
- result
124
- }
125
-
126
- cacheInferredModule(
127
- packagePaths: Map[PackagePair, Path]
128
- packagePair: PackagePair
129
- moduleName: String
130
- body: Path => Module
131
- ): Module {
132
- let path = modulePath(packagePaths, packagePair, moduleName)
133
- self.inferredModules.get(path.absolute()).map {_.first}.else:
134
- let result = body(path)
135
- self.inferredModules = self.inferredModules.add(path.absolute(), Pair(result, self.version))
136
- result
137
- }
138
-
139
- cacheEmittedModule(
140
- packagePaths: Map[PackagePair, Path]
141
- packagePair: PackagePair
142
- moduleName: String
143
- body: Path => Unit
144
- ): Unit {
145
- let path = modulePath(packagePaths, packagePair, moduleName)
146
- if(!self.emittedModules.contains(path.absolute())):
147
- self.emittedModules = self.emittedModules.add(path.absolute(), self.version)
148
- try {
149
- body(path)
150
- } catchAny {error =>
151
- self.emittedModules = self.emittedModules.remove(path.absolute())
152
- error.rethrow()
153
- }
154
- }
155
-
156
- }
157
-
158
- mergeVersionedMap[T](oldMap: Map[String, T], newMap: Map[String, T], getVersion: T => Int): Map[String, T] {
159
- mutable result = newMap
160
- oldMap.each {k, v =>
161
- if(!newMap.get(k).any {getVersion(_) >= getVersion(v)}) {
162
- result = result.add(k, v)
163
- }
164
- }
165
- result
166
- }
167
-
168
- modulePath(
169
- packagePaths: Map[PackagePair, Path]
170
- packagePair: PackagePair
171
- moduleName: String
172
- ): Path {
173
- let packagePath = packagePaths.get(packagePair).else {
174
- panic("Internal error - package path missing: " + packagePair.groupName())
175
- }
176
- let file = moduleName + ".ff"
177
- packagePath.slash(file)
178
- }
1
+ import Syntax
2
+
3
+ class ModuleCache(
4
+ version: Int
5
+ mutable parsedModules: Map[String, Pair[Module, Int]]
6
+ mutable resolvedModules: Map[String, Pair[Module, Int]]
7
+ mutable derivedModules: Map[String, Pair[Module, Int]]
8
+ mutable inferredModules: Map[String, Pair[Module, Int]]
9
+ mutable emittedModules: Map[String, Int]
10
+ )
11
+
12
+ new(version: Int): ModuleCache {
13
+ ModuleCache(
14
+ version = version
15
+ parsedModules = Map.new()
16
+ resolvedModules = Map.new()
17
+ derivedModules = Map.new()
18
+ inferredModules = Map.new()
19
+ emittedModules = Map.new()
20
+ )
21
+ }
22
+
23
+ extend self: ModuleCache {
24
+
25
+ remove(keys: List[String]) {
26
+ if(!keys.isEmpty()):
27
+ self.parsedModules = self.parsedModules.removeList(keys)
28
+ self.resolvedModules = self.resolvedModules.removeList(keys)
29
+ self.derivedModules = self.derivedModules.removeList(keys)
30
+ self.inferredModules = self.inferredModules.removeList(keys)
31
+ self.emittedModules = self.emittedModules.removeList(keys)
32
+ }
33
+
34
+ invalidate(key: String) {
35
+ //Log.trace("Invalidate: " + uri)
36
+ self.parsedModules.get(key).each: | Pair(module, _) =>
37
+ let moduleName = module.file.dropLast(3)
38
+ self.remove([key])
39
+ self.parsedModules.each {| k, Pair(m, _) =>
40
+ if(m.imports.any {i => i.package == module.packagePair && i.file == moduleName}) {
41
+ //Log.trace("Invalidating due to import of invalidated module: " + m.packagePair.groupName() + "/" + m.file)
42
+ self.remove([k])
43
+ }
44
+ }
45
+ }
46
+
47
+ filesNotImporting(packagePair: PackagePair, moduleName: String): List[String] {
48
+ self.parsedModules.toList().collect {| Pair(k, Pair(m, _)) =>
49
+ if(!m.imports.any {i => i.package == packagePair && i.file == moduleName}): k
50
+ }
51
+ }
52
+
53
+ without(newVersion: Int, path: Path): ModuleCache {
54
+ let key = path.absolute()
55
+ if(path.isFile()) {
56
+ self.ModuleCache(
57
+ version = newVersion
58
+ parsedModules = self.parsedModules.remove(key)
59
+ resolvedModules = self.resolvedModules.remove(key)
60
+ derivedModules = self.derivedModules.remove(key)
61
+ inferredModules = self.inferredModules.remove(key)
62
+ emittedModules = self.emittedModules.remove(key)
63
+ )
64
+ } else {
65
+ function invalidated(p: String): Bool {
66
+ p.startsWith(key) && !p.contains(".firefly/dependencies") && !p.contains(".firefly\\dependencies")
67
+ }
68
+ self.ModuleCache(
69
+ version = newVersion
70
+ parsedModules = self.parsedModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
71
+ resolvedModules = self.resolvedModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
72
+ derivedModules = self.derivedModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
73
+ inferredModules = self.inferredModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
74
+ emittedModules = self.emittedModules.toList().filter {| Pair(p, _) => !invalidated(p)}.toMap()
75
+ )
76
+ }
77
+ }
78
+
79
+ mergeVersions(cache: ModuleCache): Unit {
80
+ self.parsedModules = mergeVersionedMap(self.parsedModules, cache.parsedModules) {_.second}
81
+ self.resolvedModules = mergeVersionedMap(self.resolvedModules, cache.resolvedModules) {_.second}
82
+ self.derivedModules = mergeVersionedMap(self.derivedModules, cache.derivedModules) {_.second}
83
+ self.inferredModules = mergeVersionedMap(self.inferredModules, cache.inferredModules) {_.second}
84
+ self.emittedModules = mergeVersionedMap(self.emittedModules, cache.emittedModules) {_}
85
+ }
86
+
87
+ cacheParsedModule(
88
+ packagePaths: Map[PackagePair, Path]
89
+ packagePair: PackagePair
90
+ moduleName: String
91
+ body: Path => Module
92
+ ): Module {
93
+ let path = modulePath(packagePaths, packagePair, moduleName)
94
+ self.parsedModules.get(path.absolute()).map {_.first}.else:
95
+ let result = body(path)
96
+ self.parsedModules = self.parsedModules.add(path.absolute(), Pair(result, self.version))
97
+ result
98
+ }
99
+
100
+ cacheResolvedModule(
101
+ packagePaths: Map[PackagePair, Path]
102
+ packagePair: PackagePair
103
+ moduleName: String
104
+ body: Path => Module
105
+ ): Module {
106
+ let path = modulePath(packagePaths, packagePair, moduleName)
107
+ self.resolvedModules.get(path.absolute()).map {_.first}.else:
108
+ let result = body(path)
109
+ self.resolvedModules = self.resolvedModules.add(path.absolute(), Pair(result, self.version))
110
+ result
111
+ }
112
+
113
+ cacheDerivedModule(
114
+ packagePaths: Map[PackagePair, Path]
115
+ packagePair: PackagePair
116
+ moduleName: String
117
+ body: Path => Module
118
+ ): Module {
119
+ let path = modulePath(packagePaths, packagePair, moduleName)
120
+ self.derivedModules.get(path.absolute()).map {_.first}.else:
121
+ let result = body(path)
122
+ self.derivedModules = self.derivedModules.add(path.absolute(), Pair(result, self.version))
123
+ result
124
+ }
125
+
126
+ cacheInferredModule(
127
+ packagePaths: Map[PackagePair, Path]
128
+ packagePair: PackagePair
129
+ moduleName: String
130
+ body: Path => Module
131
+ ): Module {
132
+ let path = modulePath(packagePaths, packagePair, moduleName)
133
+ self.inferredModules.get(path.absolute()).map {_.first}.else:
134
+ let result = body(path)
135
+ self.inferredModules = self.inferredModules.add(path.absolute(), Pair(result, self.version))
136
+ result
137
+ }
138
+
139
+ cacheEmittedModule(
140
+ packagePaths: Map[PackagePair, Path]
141
+ packagePair: PackagePair
142
+ moduleName: String
143
+ body: Path => Unit
144
+ ): Unit {
145
+ let path = modulePath(packagePaths, packagePair, moduleName)
146
+ if(!self.emittedModules.contains(path.absolute())):
147
+ self.emittedModules = self.emittedModules.add(path.absolute(), self.version)
148
+ try {
149
+ body(path)
150
+ } catchAny {error =>
151
+ self.emittedModules = self.emittedModules.remove(path.absolute())
152
+ error.rethrow()
153
+ }
154
+ }
155
+
156
+ }
157
+
158
+ mergeVersionedMap[T](oldMap: Map[String, T], newMap: Map[String, T], getVersion: T => Int): Map[String, T] {
159
+ mutable result = newMap
160
+ oldMap.each {k, v =>
161
+ if(!newMap.get(k).any {getVersion(_) >= getVersion(v)}) {
162
+ result = result.add(k, v)
163
+ }
164
+ }
165
+ result
166
+ }
167
+
168
+ modulePath(
169
+ packagePaths: Map[PackagePair, Path]
170
+ packagePair: PackagePair
171
+ moduleName: String
172
+ ): Path {
173
+ let packagePath = packagePaths.get(packagePair).else {
174
+ panic("Internal error - package path missing: " + packagePair.groupName())
175
+ }
176
+ let file = moduleName + ".ff"
177
+ packagePath.slash(file)
178
+ }
@@ -17,18 +17,6 @@ class Parser(
17
17
 
18
18
  data Poly(generics: List[String], constraints: List[Constraint])
19
19
 
20
- data ParsedTargets(
21
- js: Option[Lambda]
22
- jsSync: Option[String]
23
- jsAsync: Option[String]
24
- browser: Option[Lambda]
25
- browserSync: Option[String]
26
- browserAsync: Option[String]
27
- node: Option[Lambda]
28
- nodeSync: Option[String]
29
- nodeAsync: Option[String]
30
- )
31
-
32
20
  new(
33
21
  packagePair: PackagePair
34
22
  file: String
@@ -245,13 +233,11 @@ extend self: Parser {
245
233
  parseFunctionDefinition(member: Bool): DFunction {
246
234
  if(self.lspHook.trackSymbols) {self.lspHook.emit(ParseSymbolBegin)}
247
235
  let signature = self.parseSignature(member)
248
- let body = if(self.current().rawIs("{")) {self.parseLambda(signature.parameters.size())}
249
- let targets = self.parseTargets(signature.parameters.size())
250
- let bestTarget = findBestTarget(self.targetIsNode, body, targets)
236
+ let body = self.parseLambda(signature.parameters.size())
251
237
  let result = DFunction(
252
238
  signature.at
253
239
  signature
254
- bestTarget
240
+ body
255
241
  )
256
242
  if(self.lspHook.trackSymbols) {
257
243
  self.lspHook.emit(ParseSymbolEnd(
@@ -266,66 +252,6 @@ extend self: Parser {
266
252
  result
267
253
  }
268
254
 
269
- parseTargets(parameterCount: Int): ParsedTargets {
270
- function processCode(code: String): String {
271
- let dropCount = if(code.startsWith("\"\"\"")) {3} else {1}
272
- code.dropFirst(dropCount).dropLast(dropCount)
273
- .replace("\\\"", "\"")
274
- .replace("\\r", "\r")
275
- .replace("\\n", "\n")
276
- .replace("\\t", "\t")
277
- .replace("\\\\", "\\")
278
- }
279
- mutable targets = ParsedTargets(None, None, None, None, None, None, None, None, None)
280
- while {self.currentIsSeparator(LSemicolon) && self.ahead().is(LKeyword) && self.ahead().rawIs("target")} {
281
- self.skip(LSeparator)
282
- let at = self.skip(LKeyword).at()
283
- let target = if(self.current().is(LLower)) {self.skip(LLower).raw()} else {self.skip(LKeyword).raw()}
284
- if(self.current().rawIs("{")) {
285
- let lambda = self.parseLambda(parameterCount)
286
- target.{
287
- | "js" =>
288
- if(targets.jsSync != None) {throw(CompileError(at, "Duplicate target definition"))}
289
- targets = targets.ParsedTargets(js = Some(lambda))
290
- | "browser" =>
291
- if(targets.browserSync != None) {throw(CompileError(at, "Duplicate target definition"))}
292
- targets = targets.ParsedTargets(browser = Some(lambda))
293
- | "node" =>
294
- if(targets.nodeAsync != None) {throw(CompileError(at, "Duplicate target definition"))}
295
- targets = targets.ParsedTargets(node = Some(lambda))
296
- | _ =>
297
- throw(CompileError(at, "Unknown target"))
298
- }
299
- } else {
300
- let mode = self.skip(LKeyword).raw()
301
- let code = processCode(self.skip(LString).raw())
302
- Pair(target, mode).{
303
- | Pair("js", "sync") =>
304
- if(targets.jsSync != None) {throw(CompileError(at, "Duplicate target definition"))}
305
- targets = targets.ParsedTargets(jsSync = Some(code))
306
- | Pair("js", "async") =>
307
- if(targets.jsAsync != None) {throw(CompileError(at, "Duplicate target definition"))}
308
- targets = targets.ParsedTargets(jsAsync = Some(code))
309
- | Pair("browser", "sync") =>
310
- if(targets.browserSync != None) {throw(CompileError(at, "Duplicate target definition"))}
311
- targets = targets.ParsedTargets(browserSync = Some(code))
312
- | Pair("browser", "async") =>
313
- if(targets.browserAsync != None) {throw(CompileError(at, "Duplicate target definition"))}
314
- targets = targets.ParsedTargets(browserAsync = Some(code))
315
- | Pair("node", "sync") =>
316
- if(targets.nodeSync != None) {throw(CompileError(at, "Duplicate target definition"))}
317
- targets = targets.ParsedTargets(nodeSync = Some(code))
318
- | Pair("node", "async") =>
319
- if(targets.nodeAsync != None) {throw(CompileError(at, "Duplicate target definition"))}
320
- targets = targets.ParsedTargets(nodeAsync = Some(code))
321
- | Pair(_, _) =>
322
- throw(CompileError(at, "Unknown target or mode"))
323
- }
324
- }
325
- }
326
- targets
327
- }
328
-
329
255
  parseSignature(member: Bool): Signature {
330
256
  let nameToken = self.skip(LLower)
331
257
  let poly = if(self.current().rawIs("[")) {self.parseTypeParameters()} else {Poly([], [])}
@@ -1025,10 +951,14 @@ extend self: Parser {
1025
951
  if(self.current().is(LKeyword) && (self.current().rawIs("let") || self.current().rawIs("mutable"))) {self.parseLet()} else:
1026
952
  if(self.current().is(LKeyword) && self.current().rawIs("function")) {self.parseFunctions()} else:
1027
953
  let term = self.parseTerm()
1028
- if(!self.current().is(LAssign) && !self.current().is2(LAssignPlus, LAssignMinus)) {term} else:
954
+ if(!self.current().is5(
955
+ LAssign, LAssignPlus, LAssignMinus, LAssignMultiplication, LAssignDivision
956
+ )) {term} else:
1029
957
  let token = do {
1030
958
  if(self.current().is(LAssignPlus)) {self.skip(LAssignPlus)} else:
1031
959
  if(self.current().is(LAssignMinus)) {self.skip(LAssignMinus)} else:
960
+ if(self.current().is(LAssignMultiplication)) {self.skip(LAssignMultiplication)} else:
961
+ if(self.current().is(LAssignDivision)) {self.skip(LAssignDivision)} else:
1032
962
  self.skip(LAssign)
1033
963
  }
1034
964
  let operator = token.raw().dropLast(1)
@@ -1088,7 +1018,7 @@ extend self: Parser {
1088
1018
  } else {
1089
1019
  self.parseLambda(defaultParameterCount = signature.parameters.size())
1090
1020
  }
1091
- functions.push(DFunction(signature.at, signature, FireflyTarget(body)))
1021
+ functions.push(DFunction(signature.at, signature, body))
1092
1022
  if(self.lspHook.trackSymbols) {
1093
1023
  self.lspHook.emit(ParseSymbolEnd(
1094
1024
  name = signature.name
@@ -1126,6 +1056,8 @@ extend self: Parser {
1126
1056
  | "<=" => DynamicCall(EVariable(token.at(), "ff:core/Ordering.notAfter"), False)
1127
1057
  | ">" => DynamicCall(EVariable(token.at(), "ff:core/Ordering.after"), False)
1128
1058
  | ">=" => DynamicCall(EVariable(token.at(), "ff:core/Ordering.notBefore"), False)
1059
+ | "===" => DynamicCall(EVariable(token.at(), "ff:core/JsValue.JsValue_equals"), False)
1060
+ | "!==" => DynamicCall(EVariable(token.at(), "ff:core/JsValue.JsValue_notEquals"), False)
1129
1061
  | o => DynamicCall(EVariable(token.at(), o), False)
1130
1062
  }
1131
1063
  result = ECall(token.at(), target, effect, [], arguments, [])
@@ -1166,10 +1098,10 @@ extend self: Parser {
1166
1098
  result = EField(token.at(), False, result, token.raw())
1167
1099
  }
1168
1100
  } elseIf {self.current().is(LArrowThin)} {
1169
- result = self.parseDynamicMember(result)
1101
+ result = self.parseDynamicMember(result, False)
1170
1102
  } elseIf {self.current().is(LUnary)} {
1171
1103
  let token = self.skip(LUnary)
1172
- let method = if(token.rawIs("!")) {"ff:core/UnsafeJs.value"} else {"ff:core/UnsafeJs.fromValue"}
1104
+ let method = if(token.rawIs("!")) {"ff:core/Js.value"} else {"ff:core/Js.fromValue"}
1173
1105
  let target = DynamicCall(EVariable(token.at(), method), False)
1174
1106
  let effect = self.freshUnificationVariable(token.at())
1175
1107
  result = ECall(token.at(), target, effect, [], [
@@ -1191,17 +1123,23 @@ extend self: Parser {
1191
1123
  result
1192
1124
  }
1193
1125
 
1194
- parseDynamicMember(record: Term): Term {
1126
+ parseDynamicMember(record: Term, isModule: Bool): Term {
1127
+ function recordField(at: Location, name: String): Term {
1128
+ record.{
1129
+ | EVariant e {isModule} => EVariable(at, e.name + "." + name)
1130
+ | _ => EField(at, False, record, name)
1131
+ }
1132
+ }
1195
1133
  let token = self.skip(LArrowThin)
1196
1134
  if(self.current().rawIs("(")) {
1197
1135
  let arguments = self.parseFunctionArguments(token.at(), trailing = False)
1198
1136
  let effect = self.freshUnificationVariable(record.at)
1199
1137
  arguments.first.indexWhere {!_.name.isEmpty()}.{
1200
1138
  | None =>
1201
- let target = DynamicCall(EField(token.at(), False, record, "new" + arguments.first.size()), False)
1139
+ let target = DynamicCall(recordField(token.at(), "new" + arguments.first.size()), False)
1202
1140
  ECall(record.at, target, effect, [], arguments.first, [])
1203
1141
  | Some(0) =>
1204
- let objectTarget = DynamicCall(EField(token.at(), False, record, "object"), False)
1142
+ let objectTarget = DynamicCall(recordField(token.at(), "object"), False)
1205
1143
  mutable result = ECall(record.at, objectTarget, effect, [], [], [])
1206
1144
  arguments.first.each {argument =>
1207
1145
  if(argument.name.isEmpty()) {
@@ -1221,7 +1159,7 @@ extend self: Parser {
1221
1159
  let lambda = self.parseLambda()
1222
1160
  let effect = self.freshUnificationVariable(record.at)
1223
1161
  let arguments = lambda.cases.grabFirst().patterns.size()
1224
- let target = DynamicCall(EField(token.at(), False, record, "function" + arguments), False)
1162
+ let target = DynamicCall(recordField(token.at(), "function" + arguments), False)
1225
1163
  ECall(record.at, target, effect, [], [
1226
1164
  Argument(lambda.at, None, ELambda(lambda.at, lambda))
1227
1165
  ], [])
@@ -1240,12 +1178,12 @@ extend self: Parser {
1240
1178
  throw(CompileError(argument.at, "Unexpected named argument"))
1241
1179
  }
1242
1180
  let effect = self.freshUnificationVariable(record.at)
1243
- let target = DynamicCall(EField(token.at(), False, record, "call" + arguments.first.size()), False)
1181
+ let target = DynamicCall(recordField(token.at(), "call" + arguments.first.size()), False)
1244
1182
  ECall(record.at, target, effect, [], [
1245
1183
  Argument(member.at, None, member)
1246
1184
  ...arguments.first
1247
1185
  ], [])
1248
- } elseIf {self.current().is3(LAssign, LAssignPlus, LAssignMinus)} {
1186
+ } elseIf {self.current().is5(LAssign, LAssignPlus, LAssignMinus, LAssignMultiplication, LAssignDivision)} {
1249
1187
  let method =
1250
1188
  if(self.current().is(LAssign)) {
1251
1189
  self.skip(LAssign)
@@ -1253,20 +1191,26 @@ extend self: Parser {
1253
1191
  } elseIf {self.current().is(LAssignPlus)} {
1254
1192
  self.skip(LAssignPlus)
1255
1193
  "increment"
1256
- } else {
1194
+ } elseIf {self.current().is(LAssignMinus)} {
1257
1195
  self.skip(LAssignMinus)
1258
1196
  "decrement"
1197
+ } elseIf {self.current().is(LAssignMultiplication)} {
1198
+ self.skip(LAssignMultiplication)
1199
+ "multiply"
1200
+ } else {
1201
+ self.skip(LAssignDivision)
1202
+ "divide"
1259
1203
  }
1260
1204
  let value = self.parseTerm()
1261
1205
  let effect = self.freshUnificationVariable(record.at)
1262
- let target = DynamicCall(EField(token.at(), False, record, "set"), False)
1206
+ let target = DynamicCall(recordField(token.at(), method), False)
1263
1207
  ECall(record.at, target, effect, [], [
1264
1208
  Argument(member.at, None, member)
1265
1209
  Argument(value.at, None, value)
1266
1210
  ], [])
1267
1211
  } else {
1268
1212
  let effect = self.freshUnificationVariable(record.at)
1269
- let target = DynamicCall(EField(token.at(), False, record, "get"), False)
1213
+ let target = DynamicCall(recordField(token.at(), "get"), False)
1270
1214
  ECall(record.at, target, effect, [], [
1271
1215
  Argument(member.at, None, member)
1272
1216
  ], [])
@@ -1299,6 +1243,8 @@ extend self: Parser {
1299
1243
  } else {
1300
1244
  self.parseVariant(prefix)
1301
1245
  }
1246
+ } elseIf {self.current().is(LUpper) && self.ahead().is(LArrowThin)} {
1247
+ self.parseDynamicMember(self.parseVariant(""), True)
1302
1248
  } elseIf {self.current().is(LUpper)} {
1303
1249
  self.parseVariant("")
1304
1250
  } elseIf {self.current().rawIs("{")} {
@@ -1445,28 +1391,9 @@ extend self: Parser {
1445
1391
  binaryOperators = [
1446
1392
  ["||"]
1447
1393
  ["&&"]
1448
- ["!=", "=="]
1394
+ ["!=", "==", "!==", "==="]
1449
1395
  ["<=", ">=", "<", ">"]
1450
1396
  ["+", "-"]
1451
1397
  ["*", "/", "%"]
1452
1398
  ["^"]
1453
1399
  ]
1454
-
1455
- findBestTarget(targetIsNode: Bool, body: Option[Lambda], targets: ParsedTargets): Target {
1456
- let foreignTarget = if(targetIsNode) {
1457
- let sync = targets.nodeSync.orElse {targets.jsSync}
1458
- let async = targets.nodeAsync.orElse {targets.jsAsync}
1459
- ForeignTarget(sync, async)
1460
- } else {
1461
- let sync = targets.browserSync.orElse {targets.jsSync}
1462
- let async = targets.browserAsync.orElse {targets.jsAsync}
1463
- ForeignTarget(sync, async)
1464
- }
1465
- foreignTarget.{
1466
- | ForeignTarget(None, None) {targetIsNode} =>
1467
- targets.node.orElse {targets.js.orElse {body}}.map {FireflyTarget(_)}.else {foreignTarget}
1468
- | ForeignTarget(None, None) {!targetIsNode} =>
1469
- targets.browser.orElse {targets.js.orElse {body}}.map {FireflyTarget(_)}.else {foreignTarget}
1470
- | _ => foreignTarget
1471
- }
1472
- }
@@ -212,12 +212,9 @@ extend self: Resolver {
212
212
  methods = definition.methods.map {self2.resolveSignature(_, True, False)}
213
213
  methodDefaults = definition.methodDefaults.map {| Pair(name, lambda) =>
214
214
  let signature = definition.methods.find {_.name == name}.grab()
215
- let function1 = DFunction(signature.at, signature, FireflyTarget(lambda))
215
+ let function1 = DFunction(signature.at, signature, lambda)
216
216
  let function2 = self2.resolveFunctionDefinition(function1, True, False)
217
- Pair(name, function2.body.{
218
- | FireflyTarget(lambda) => lambda
219
- | _ => throw(CompileError(signature.at, "Internal error: Expected method default to be a lambda"))
220
- })
217
+ Pair(name, function2.body)
221
218
  }
222
219
  )
223
220
  }
@@ -490,10 +487,10 @@ extend self: Resolver {
490
487
  resolveFunctionDefinition(definition: DFunction, topLevel: Bool, isInstanceMethod: Bool): DFunction {
491
488
  let signature = self.resolveSignature(definition.signature, topLevel, isInstanceMethod)
492
489
  let self2 = self.withSignature(signature)
493
- let body = definition.body.mapFirefly {lambda => lambda.Lambda(
490
+ let body = definition.body.Lambda(
494
491
  effect = signature.effect
495
- cases = lambda.cases.map {self2.resolveCase(_, False)}
496
- )}
492
+ cases = definition.body.cases.map {self2.resolveCase(_, False)}
493
+ )
497
494
  DFunction(definition.at, signature, body)
498
495
  }
499
496
 
@@ -39,7 +39,7 @@ extend self: Substitution {
39
39
  substituteFunctionDefinition(definition: DFunction): DFunction {
40
40
  definition.DFunction(
41
41
  signature = self.substituteSignature(definition.signature)
42
- body = definition.body.mapFirefly {self.substituteLambda(_)}
42
+ body = self.substituteLambda(definition.body)
43
43
  )
44
44
  }
45
45