firefly-compiler 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/.firefly-workspace +1 -0
  2. package/.vscode/settings.json +5 -0
  3. package/LICENSE.txt +21 -0
  4. package/README.md +96 -0
  5. package/bin/firefly.mjs +2 -0
  6. package/compiler/.firefly/package.ff +1 -0
  7. package/compiler/Builder.ff +218 -0
  8. package/compiler/Compiler.ff +241 -0
  9. package/compiler/Dependencies.ff +179 -0
  10. package/compiler/Deriver.ff +647 -0
  11. package/compiler/Dictionaries.ff +205 -0
  12. package/compiler/Environment.ff +166 -0
  13. package/compiler/Inference.ff +1117 -0
  14. package/compiler/JsEmitter.ff +861 -0
  15. package/compiler/JsImporter.ff +56 -0
  16. package/compiler/LspHook.ff +188 -0
  17. package/compiler/Main.ff +237 -0
  18. package/compiler/Parser.ff +1383 -0
  19. package/compiler/Patterns.ff +111 -0
  20. package/compiler/Resolver.ff +620 -0
  21. package/compiler/Substitution.ff +178 -0
  22. package/compiler/Syntax.ff +299 -0
  23. package/compiler/Token.ff +180 -0
  24. package/compiler/Tokenizer.ff +278 -0
  25. package/compiler/Unification.ff +220 -0
  26. package/compiler/Wildcards.ff +50 -0
  27. package/compiler/Workspace.ff +88 -0
  28. package/core/.firefly/package.ff +2 -0
  29. package/core/Any.ff +30 -0
  30. package/core/Array.ff +249 -0
  31. package/core/AssetSystem.ff +61 -0
  32. package/core/Atomic.ff +64 -0
  33. package/core/Bool.ff +13 -0
  34. package/core/BrowserSystem.ff +14 -0
  35. package/core/Buffer.ff +211 -0
  36. package/core/BuildSystem.ff +144 -0
  37. package/core/Channel.ff +131 -0
  38. package/core/Char.ff +18 -0
  39. package/core/Core.ff +58 -0
  40. package/core/Duration.ff +15 -0
  41. package/core/Equal.ff +52 -0
  42. package/core/Error.ff +20 -0
  43. package/core/FileHandle.ff +41 -0
  44. package/core/Float.ff +41 -0
  45. package/core/HttpClient.ff +84 -0
  46. package/core/Instant.ff +9 -0
  47. package/core/Int.ff +61 -0
  48. package/core/IntMap.ff +85 -0
  49. package/core/JsSystem.ff +66 -0
  50. package/core/JsValue.ff +240 -0
  51. package/core/List.ff +440 -0
  52. package/core/Lock.ff +144 -0
  53. package/core/Log.ff +24 -0
  54. package/core/Map.ff +126 -0
  55. package/core/NodeSystem.ff +88 -0
  56. package/core/Nothing.ff +1 -0
  57. package/core/Option.ff +133 -0
  58. package/core/Ordering.ff +157 -0
  59. package/core/Pair.ff +55 -0
  60. package/core/Path.ff +393 -0
  61. package/core/RbMap.ff +216 -0
  62. package/core/Serializable.ff +173 -0
  63. package/core/Set.ff +38 -0
  64. package/core/Show.ff +43 -0
  65. package/core/Stack.ff +263 -0
  66. package/core/Stream.ff +406 -0
  67. package/core/String.ff +175 -0
  68. package/core/StringMap.ff +85 -0
  69. package/core/Task.ff +138 -0
  70. package/core/Try.ff +81 -0
  71. package/core/Unit.ff +3 -0
  72. package/experimental/random/AltGeneric.ff +44 -0
  73. package/experimental/random/Async.ff +68 -0
  74. package/experimental/random/Buffer2.ff +77 -0
  75. package/experimental/random/Cat.ff +12 -0
  76. package/experimental/random/Dictionary.ff +52 -0
  77. package/experimental/random/Example.ff +46 -0
  78. package/experimental/random/Generic.ff +102 -0
  79. package/experimental/random/HappyEyeballs.ff +40 -0
  80. package/experimental/random/HashMap.ff +72 -0
  81. package/experimental/random/IfElseUnit.ff +9 -0
  82. package/experimental/random/InputOutput.ff +23 -0
  83. package/experimental/random/ListVsArray.ff +45 -0
  84. package/experimental/random/Main.ff +44 -0
  85. package/experimental/random/MapTest.ff +67 -0
  86. package/experimental/random/OldTaskSystem.ff +210 -0
  87. package/experimental/random/PatternTest.ff +39 -0
  88. package/experimental/random/Patterns.ff +226 -0
  89. package/experimental/random/ReadBytesTest.ff +10 -0
  90. package/experimental/random/RunLength.ff +65 -0
  91. package/experimental/random/Scrape.ff +51 -0
  92. package/experimental/random/Serialization.ff +217 -0
  93. package/experimental/random/SerializationTest.ff +46 -0
  94. package/experimental/random/Serializer.ff +36 -0
  95. package/experimental/random/StdInOutErr.ff +4 -0
  96. package/experimental/random/Symbols.ff +74 -0
  97. package/experimental/random/Tag.ff +49 -0
  98. package/experimental/random/Tensor.ff +52 -0
  99. package/experimental/random/Try.ff +56 -0
  100. package/experimental/random/Tsv.ff +9 -0
  101. package/experimental/random/TypesAreModules.ff +87 -0
  102. package/experimental/random/blueprints/Blueprint.ff +52 -0
  103. package/experimental/random/blueprints/Main.ff +11 -0
  104. package/experimental/random/blueprints/Pretty.ff +58 -0
  105. package/experimental/random/blueprints/User.ff +64 -0
  106. package/experimental/random/blueprintsystem/BlueprintSystem.ff +48 -0
  107. package/experimental/random/blueprintsystem/Deserialize.ff +53 -0
  108. package/experimental/random/blueprintsystem/ReadJs.ff +13 -0
  109. package/experimental/random/blueprintsystem/User.ff +2 -0
  110. package/experimental/random/kahrs/Kahrs.ff +112 -0
  111. package/experimental/random/kahrs/TestKahrs.ff +22 -0
  112. package/experimental/random/kahrs/TestMap.ff +18 -0
  113. package/experimental/random/streaming/Gzip.ff +3 -0
  114. package/experimental/random/streaming/Main.ff +34 -0
  115. package/experimental/random/streaming/S3Bucket.ff +11 -0
  116. package/experimental/random/streaming/Tar.ff +5 -0
  117. package/experimental/rhymeapp/Main.ff +81 -0
  118. package/experimental/rhymeapp/index.html +14 -0
  119. package/firefly.sh +5 -0
  120. package/fireflysite/Main.ff +13 -0
  121. package/httpserver/.firefly/package.ff +1 -0
  122. package/httpserver/HttpServer.ff +184 -0
  123. package/lsp/.firefly/package.ff +1 -0
  124. package/lsp/CompletionHandler.ff +814 -0
  125. package/lsp/Handler.ff +551 -0
  126. package/lsp/HoverHandler.ff +82 -0
  127. package/lsp/LanguageServer.ff +229 -0
  128. package/lsp/SignatureHelpHandler.ff +55 -0
  129. package/lsp/SymbolHandler.ff +167 -0
  130. package/output/js/ff/compiler/Builder.mjs +483 -0
  131. package/output/js/ff/compiler/Compiler.mjs +410 -0
  132. package/output/js/ff/compiler/Dependencies.mjs +388 -0
  133. package/output/js/ff/compiler/Deriver.mjs +1166 -0
  134. package/output/js/ff/compiler/Dictionaries.mjs +1305 -0
  135. package/output/js/ff/compiler/Environment.mjs +1005 -0
  136. package/output/js/ff/compiler/Inference.mjs +4264 -0
  137. package/output/js/ff/compiler/JsEmitter.mjs +5353 -0
  138. package/output/js/ff/compiler/JsImporter.mjs +262 -0
  139. package/output/js/ff/compiler/LspHook.mjs +789 -0
  140. package/output/js/ff/compiler/Main.mjs +1695 -0
  141. package/output/js/ff/compiler/Parser.mjs +4004 -0
  142. package/output/js/ff/compiler/Patterns.mjs +923 -0
  143. package/output/js/ff/compiler/Resolver.mjs +2303 -0
  144. package/output/js/ff/compiler/Substitution.mjs +1146 -0
  145. package/output/js/ff/compiler/Syntax.mjs +12430 -0
  146. package/output/js/ff/compiler/Token.mjs +3092 -0
  147. package/output/js/ff/compiler/Tokenizer.mjs +589 -0
  148. package/output/js/ff/compiler/Unification.mjs +1748 -0
  149. package/output/js/ff/compiler/Wildcards.mjs +604 -0
  150. package/output/js/ff/compiler/Workspace.mjs +683 -0
  151. package/output/js/ff/core/Any.mjs +139 -0
  152. package/output/js/ff/core/Array.mjs +594 -0
  153. package/output/js/ff/core/AssetSystem.mjs +270 -0
  154. package/output/js/ff/core/Atomic.mjs +186 -0
  155. package/output/js/ff/core/Bool.mjs +141 -0
  156. package/output/js/ff/core/BrowserSystem.mjs +122 -0
  157. package/output/js/ff/core/Buffer.mjs +467 -0
  158. package/output/js/ff/core/BuildSystem.mjs +320 -0
  159. package/output/js/ff/core/Channel.mjs +268 -0
  160. package/output/js/ff/core/Char.mjs +145 -0
  161. package/output/js/ff/core/Core.mjs +300 -0
  162. package/output/js/ff/core/Duration.mjs +112 -0
  163. package/output/js/ff/core/Equal.mjs +175 -0
  164. package/output/js/ff/core/Error.mjs +138 -0
  165. package/output/js/ff/core/FileHandle.mjs +164 -0
  166. package/output/js/ff/core/Float.mjs +214 -0
  167. package/output/js/ff/core/HttpClient.mjs +210 -0
  168. package/output/js/ff/core/Instant.mjs +105 -0
  169. package/output/js/ff/core/Int.mjs +254 -0
  170. package/output/js/ff/core/IntMap.mjs +282 -0
  171. package/output/js/ff/core/JsSystem.mjs +234 -0
  172. package/output/js/ff/core/JsValue.mjs +678 -0
  173. package/output/js/ff/core/List.mjs +2335 -0
  174. package/output/js/ff/core/Lock.mjs +322 -0
  175. package/output/js/ff/core/Log.mjs +159 -0
  176. package/output/js/ff/core/Map.mjs +358 -0
  177. package/output/js/ff/core/NodeSystem.mjs +288 -0
  178. package/output/js/ff/core/Nothing.mjs +100 -0
  179. package/output/js/ff/core/Option.mjs +1002 -0
  180. package/output/js/ff/core/Ordering.mjs +734 -0
  181. package/output/js/ff/core/Pair.mjs +318 -0
  182. package/output/js/ff/core/Path.mjs +768 -0
  183. package/output/js/ff/core/RbMap.mjs +1936 -0
  184. package/output/js/ff/core/Serializable.mjs +434 -0
  185. package/output/js/ff/core/Set.mjs +250 -0
  186. package/output/js/ff/core/Show.mjs +201 -0
  187. package/output/js/ff/core/Stack.mjs +595 -0
  188. package/output/js/ff/core/Stream.mjs +1300 -0
  189. package/output/js/ff/core/String.mjs +433 -0
  190. package/output/js/ff/core/StringMap.mjs +282 -0
  191. package/output/js/ff/core/Task.mjs +345 -0
  192. package/output/js/ff/core/Try.mjs +503 -0
  193. package/output/js/ff/core/Unit.mjs +103 -0
  194. package/package.json +29 -0
  195. package/postgresql/.firefly/include/package-lock.json +250 -0
  196. package/postgresql/.firefly/include/package.json +5 -0
  197. package/postgresql/.firefly/include/prepare.sh +2 -0
  198. package/postgresql/.firefly/package.ff +3 -0
  199. package/postgresql/Pg.ff +530 -0
  200. package/unsafejs/.firefly/package.ff +1 -0
  201. package/unsafejs/UnsafeJs.ff +19 -0
  202. package/vscode/.vscode/launch.json +18 -0
  203. package/vscode/.vscode/tasks.json +33 -0
  204. package/vscode/LICENSE.txt +21 -0
  205. package/vscode/Prepublish.ff +15 -0
  206. package/vscode/README.md +17 -0
  207. package/vscode/client/package-lock.json +544 -0
  208. package/vscode/client/package.json +22 -0
  209. package/vscode/client/src/extension.ts +64 -0
  210. package/vscode/client/tsconfig.json +12 -0
  211. package/vscode/icons/firefly-icon.png +0 -0
  212. package/vscode/icons/firefly-icon.svg +10 -0
  213. package/vscode/icons/firefly-logo-notext.png +0 -0
  214. package/vscode/icons/firefly-logo.png +0 -0
  215. package/vscode/language-configuration.json +39 -0
  216. package/vscode/package-lock.json +3623 -0
  217. package/vscode/package.json +144 -0
  218. package/vscode/snippets-none.json +1 -0
  219. package/vscode/snippets.json +241 -0
  220. package/vscode/syntaxes/firefly.tmLanguage.json +294 -0
  221. package/vscode/tsconfig.json +20 -0
@@ -0,0 +1,530 @@
1
+ import UnsafeJs from ff:unsafejs
2
+
3
+ capability PgPool(jsValue: JsValue)
4
+ capability PgConnection(jsValue: JsValue)
5
+ capability PgRow(jsValue: JsValue) // TODO: Should be a sync class, make deriver not touch those
6
+ capability PgStatement(sql: String, parameters: Map[String, JsValue], connection: Option[PgConnection])
7
+ data PgLevel {
8
+ PgReadCommitted
9
+ PgRepeatableRead
10
+ PgSerializable
11
+ }
12
+
13
+ makePool(
14
+ system: NodeSystem
15
+ user: String
16
+ host: String
17
+ database: String
18
+ password: () => String
19
+ port: Int = 5432
20
+ connectionTimeout: Duration = Duration(10.0)
21
+ idleTimeout: Duration = Duration(10.0)
22
+ maxConnections: Int = 10
23
+ allowExitOnIdle: Bool = True
24
+ ): PgPool {
25
+ UnsafeJs.throwIfCancelled()
26
+ let js = UnsafeJs.jsSystem()
27
+ let pg = UnsafeJs.import("pg").get("default")
28
+ PgPool(pg.get("Pool").new1(js.object()
29
+ .with("user", user)
30
+ .with("host", host)
31
+ .with("database", database)
32
+ .with("password", js.function0(password))
33
+ .with("port", port)
34
+ .with("connectionTimeoutMillis", connectionTimeout.seconds * 1000)
35
+ .with("idleTimeoutMillis", idleTimeout.seconds * 1000)
36
+ .with("max", maxConnections)
37
+ .with("allowExitOnIdle", allowExitOnIdle)
38
+ ))
39
+ }
40
+
41
+ makePoolFromConnectionString(
42
+ system: NodeSystem
43
+ connectionString: String
44
+ connectionTimeout: Duration = Duration(10.0)
45
+ idleTimeout: Duration = Duration(10.0)
46
+ maxConnections: Int = 10
47
+ allowExitOnIdle: Bool = True
48
+ ): PgPool {
49
+ UnsafeJs.throwIfCancelled()
50
+ let js = UnsafeJs.jsSystem()
51
+ let pg = UnsafeJs.import("pg").get("default")
52
+ PgPool(pg.get("Pool").new1(js.object()
53
+ .with("connectionString", connectionString)
54
+ .with("connectionTimeoutMillis", connectionTimeout.seconds * 1000)
55
+ .with("idleTimeoutMillis", idleTimeout.seconds * 1000)
56
+ .with("max", maxConnections)
57
+ .with("allowExitOnIdle", allowExitOnIdle)
58
+ ))
59
+ }
60
+
61
+ extend self: PgPool {
62
+
63
+ connect(): PgConnection {
64
+ UnsafeJs.throwIfCancelled()
65
+ PgConnection(UnsafeJs.await { self.jsValue.call0("connect") })
66
+ }
67
+
68
+ close(): Unit {
69
+ UnsafeJs.await { self.jsValue.call0("end") }
70
+ }
71
+
72
+ connectionCount(): Int {
73
+ self.jsValue.get("totalCount").grabInt()
74
+ }
75
+
76
+ idleCount(): Int {
77
+ self.jsValue.get("idleCount").grabInt()
78
+ }
79
+
80
+ waitingCount(): Int {
81
+ self.jsValue.get("waitingCount").grabInt()
82
+ }
83
+
84
+ transaction[T](body: PgConnection => T, level: PgLevel = PgReadCommitted): T {
85
+ let connection = self.connect()
86
+ mutable done = False
87
+ try {
88
+ connection.statement("begin").run()
89
+ level.{
90
+ | PgReadCommitted => 0 // Default level in PostgreSQL
91
+ | PgRepeatableRead => connection.statement("set transaction isolation level repeatable read").run()
92
+ | PgSerializable => connection.statement("set transaction isolation level serializable").run()
93
+ }
94
+ let result = body(connection)
95
+ done = True
96
+ connection.statement("commit").run()
97
+ result
98
+ } finally {
99
+ if(!done) {connection.statement("rollback").run()}
100
+ connection.release()
101
+ } grab()
102
+ }
103
+
104
+ }
105
+
106
+ extend self: PgConnection {
107
+
108
+ release(): Unit {
109
+ if(UnsafeJs.cancelled()) {
110
+ self.jsValue.call1("release", True)
111
+ } else {
112
+ self.jsValue.call0("release")
113
+ }
114
+ }
115
+
116
+ statement(sql: String): PgStatement {
117
+ PgStatement(sql, [].toMap(), Some(self))
118
+ }
119
+
120
+ batchRun(statements: List[PgStatement]): List[Int] {
121
+ internalBatchStatements(self, statements, None, None)
122
+ }
123
+
124
+ batchAll(statements: List[PgStatement], body: PgRow => Bool): List[Bool] {
125
+ internalBatchStatements(self, statements, Some(body), None).map {_ == 1}
126
+ }
127
+
128
+ batchAny(statements: List[PgStatement], body: PgRow => Bool): List[Bool] {
129
+ self.batchAll(statements, {!body(_)}).map {!_}
130
+ }
131
+
132
+ batchEach(statements: List[PgStatement], body: PgRow => Unit): Unit {
133
+ self.batchAll(statements, {body(_); True})
134
+ }
135
+
136
+ batchMap[T](statements: List[PgStatement], body: PgRow => T): List[List[T]] {
137
+ mutable results = []
138
+ mutable result = []
139
+ internalBatchStatements(self, statements, Some({row =>
140
+ result = [body(row), ...result]
141
+ True
142
+ }), Some({
143
+ results = [result.reverse(), ...results]
144
+ }))
145
+ results.reverse()
146
+ }
147
+
148
+ }
149
+
150
+ extend self: PgStatement {
151
+
152
+ withBool(name: String, value: Bool): PgStatement {
153
+ let p = UnsafeJs.jsSystem().value(value)
154
+ self.PgStatement(parameters = self.parameters.add(name, p))
155
+ }
156
+
157
+ withNullableBool(name: String, value: Option[Bool]): PgStatement {
158
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
159
+ self.PgStatement(parameters = self.parameters.add(name, p))
160
+ }
161
+
162
+ withInt(name: String, value: Int): PgStatement {
163
+ let p = UnsafeJs.jsSystem().value(value)
164
+ self.PgStatement(parameters = self.parameters.add(name, p))
165
+ }
166
+
167
+ withNullableInt(name: String, value: Option[Int]): PgStatement {
168
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
169
+ self.PgStatement(parameters = self.parameters.add(name, p))
170
+ }
171
+
172
+ withFloat(name: String, value: Float): PgStatement {
173
+ let p = UnsafeJs.jsSystem().value(value)
174
+ self.PgStatement(parameters = self.parameters.add(name, p))
175
+ }
176
+
177
+ withNullableFloat(name: String, value: Option[Float]): PgStatement {
178
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
179
+ self.PgStatement(parameters = self.parameters.add(name, p))
180
+ }
181
+
182
+ withString(name: String, value: String): PgStatement {
183
+ let p = UnsafeJs.jsSystem().value(value)
184
+ self.PgStatement(parameters = self.parameters.add(name, p))
185
+ }
186
+
187
+ withNullableString(name: String, value: Option[String]): PgStatement {
188
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
189
+ self.PgStatement(parameters = self.parameters.add(name, p))
190
+ }
191
+
192
+ withInstant(name: String, value: Instant): PgStatement {
193
+ let jsDate = UnsafeJs.jsSystem().global().get("Date")
194
+ function toJsDate(instant: Instant): JsValue {
195
+ jsDate.new1(instant.since1970.seconds * 1000.0)
196
+ }
197
+ let p = toJsDate(value)
198
+ self.PgStatement(parameters = self.parameters.add(name, p))
199
+ }
200
+
201
+ withNullableInstant(name: String, value: Option[Instant]): PgStatement {
202
+ let jsDate = UnsafeJs.jsSystem().global().get("Date")
203
+ function toJsDate(instant: Instant): JsValue {
204
+ jsDate.new1(instant.since1970.seconds * 1000.0)
205
+ }
206
+ let p = value.map(toJsDate).else {UnsafeJs.jsSystem().null()}
207
+ self.PgStatement(parameters = self.parameters.add(name, p))
208
+ }
209
+
210
+ withBuffer(name: String, value: Buffer): PgStatement {
211
+ let p = UnsafeJs.jsSystem().value(value)
212
+ self.PgStatement(parameters = self.parameters.add(name, p))
213
+ }
214
+
215
+ withNullableBuffer(name: String, value: Option[Buffer]): PgStatement {
216
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
217
+ self.PgStatement(parameters = self.parameters.add(name, p))
218
+ }
219
+
220
+ withBoolArray(name: String, value: Array[Bool]): PgStatement {
221
+ let p = UnsafeJs.jsSystem().value(value)
222
+ self.PgStatement(parameters = self.parameters.add(name, p))
223
+ }
224
+
225
+ withNullableBoolArray(name: String, value: Option[Array[Bool]]): PgStatement {
226
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
227
+ self.PgStatement(parameters = self.parameters.add(name, p))
228
+ }
229
+
230
+ withIntArray(name: String, value: Array[Int]): PgStatement {
231
+ let p = UnsafeJs.jsSystem().value(value)
232
+ self.PgStatement(parameters = self.parameters.add(name, p))
233
+ }
234
+
235
+ withNullableIntArray(name: String, value: Option[Array[Int]]): PgStatement {
236
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
237
+ self.PgStatement(parameters = self.parameters.add(name, p))
238
+ }
239
+
240
+ withFloatArray(name: String, value: Array[Float]): PgStatement {
241
+ let p = UnsafeJs.jsSystem().value(value)
242
+ self.PgStatement(parameters = self.parameters.add(name, p))
243
+ }
244
+
245
+ withNullableFloatArray(name: String, value: Option[Array[Float]]): PgStatement {
246
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
247
+ self.PgStatement(parameters = self.parameters.add(name, p))
248
+ }
249
+
250
+ withStringArray(name: String, value: Array[String]): PgStatement {
251
+ let p = UnsafeJs.jsSystem().value(value)
252
+ self.PgStatement(parameters = self.parameters.add(name, p))
253
+ }
254
+
255
+ withNullableStringArray(name: String, value: Option[Array[String]]): PgStatement {
256
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
257
+ self.PgStatement(parameters = self.parameters.add(name, p))
258
+ }
259
+
260
+ withInstantArray(name: String, value: Array[Instant]): PgStatement {
261
+ let jsDate = UnsafeJs.jsSystem().global().get("Date")
262
+ function toJsDate(instant: Instant): JsValue {
263
+ jsDate.new1(instant.since1970.seconds * 1000.0)
264
+ }
265
+ let p = UnsafeJs.jsSystem().value(value.map(toJsDate))
266
+ self.PgStatement(parameters = self.parameters.add(name, p))
267
+ }
268
+
269
+ withNullableInstantArray(name: String, value: Option[Array[Instant]]): PgStatement {
270
+ let jsDate = UnsafeJs.jsSystem().global().get("Date")
271
+ function toJsDate(instant: Instant): JsValue {
272
+ jsDate.new1(instant.since1970.seconds * 1000.0)
273
+ }
274
+ let p = value.map {_.map(toJsDate)}.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
275
+ self.PgStatement(parameters = self.parameters.add(name, p))
276
+ }
277
+
278
+ withBufferArray(name: String, value: Array[Buffer]): PgStatement {
279
+ let p = UnsafeJs.jsSystem().value(value)
280
+ self.PgStatement(parameters = self.parameters.add(name, p))
281
+ }
282
+
283
+ withNullableBufferArray(name: String, value: Option[Array[Buffer]]): PgStatement {
284
+ let p = value.map(UnsafeJs.jsSystem().value).else {UnsafeJs.jsSystem().null()}
285
+ self.PgStatement(parameters = self.parameters.add(name, p))
286
+ }
287
+
288
+ run(): Int {
289
+ internalRunStatement(self, None)
290
+ }
291
+
292
+ all(body: PgRow => Bool): Bool {
293
+ internalRunStatement(self, Some(body)) == 1
294
+ }
295
+
296
+ any(body: PgRow => Bool): Bool {
297
+ !self.all { row =>
298
+ !body(row)
299
+ }
300
+ }
301
+
302
+ each(body: PgRow => Unit): Unit {
303
+ self.all { row =>
304
+ body(row)
305
+ True
306
+ }
307
+ }
308
+
309
+ map[T](body: PgRow => T): List[T] {
310
+ mutable result = []
311
+ self.each { row =>
312
+ result = [body(row), ...result]
313
+ }
314
+ result.reverse()
315
+ }
316
+
317
+ }
318
+
319
+ extend self: PgRow {
320
+
321
+ getBool(name: String, lower: Bool = True): Option[Bool] {
322
+ internalGet(self, name, lower) {(_.grabBool() && True) || False}
323
+ }
324
+
325
+ getInt(name: String, lower: Bool = True): Option[Int] {
326
+ internalGet(self, name, lower) {_.grabInt() * 1}
327
+ }
328
+
329
+ getFloat(name: String, lower: Bool = True): Option[Float] {
330
+ internalGet(self, name, lower) {_.grabFloat() * 1.0}
331
+ }
332
+
333
+ getString(name: String, lower: Bool = True): Option[String] {
334
+ internalGet(self, name, lower) {"" + _.grabString()}
335
+ }
336
+
337
+ getInstant(name: String, lower: Bool = True): Option[Instant] {
338
+ internalGet(self, name, lower) {Instant(Duration(_.call0("getTime").grabInt() * 0.001))}
339
+ }
340
+
341
+ getBuffer(name: String, lower: Bool = True): Option[Buffer] {
342
+ internalGet(self, name, lower) {_.grabBuffer()}
343
+ }
344
+
345
+ getBoolArray(name: String, lower: Bool = True): Option[Array[Bool]] {
346
+ internalGet(self, name, lower) {_.grabArray().map {(_.grabBool() && True) || False}}
347
+ }
348
+
349
+ getIntArray(name: String, lower: Bool = True): Option[Array[Int]] {
350
+ internalGet(self, name, lower) {_.grabArray().map {_.grabInt() * 1}}
351
+ }
352
+
353
+ getFloatArray(name: String, lower: Bool = True): Option[Array[Float]] {
354
+ internalGet(self, name, lower) {_.grabArray().map {_.grabFloat() * 1.0}}
355
+ }
356
+
357
+ getStringArray(name: String, lower: Bool = True): Option[Array[String]] {
358
+ internalGet(self, name, lower) {_.grabArray().map {"" + _.grabString()}}
359
+ }
360
+
361
+ getInstantArray(name: String, lower: Bool = True): Option[Array[Instant]] {
362
+ internalGet(self, name, lower) {_.grabArray().map {Instant(Duration(_.call0("getTime").grabInt() * 0.001))}}
363
+ }
364
+
365
+ getBufferArray(name: String, lower: Bool = True): Option[Array[Buffer]] {
366
+ internalGet(self, name, lower) {_.grabArray().map {_.grabBuffer()}}
367
+ }
368
+
369
+ }
370
+
371
+ internalGet[T](row: PgRow, name: String, lower: Bool, body: JsValue => T): Option[T] {
372
+ let n = if(lower) {name.lower()} else {name}
373
+ if(!row.jsValue.hasOwn(n)) {panic("Column not found in result: " + n)}
374
+ let value = row.jsValue.get(n)
375
+ if(!value.isNull()) {Some(body(value))} else {None}
376
+ }
377
+
378
+ internalRunStatement(statement: PgStatement, body: Option[PgRow => Bool]): Int {
379
+ UnsafeJs.throwIfCancelled()
380
+ let pair = internalParseParameters(statement.sql)
381
+ let parameters = internalCheckParameters(pair.second, statement.parameters)
382
+ let result = UnsafeJs.await { statement.connection.grab().jsValue.call2("query", pair.first, parameters) }
383
+ body.{
384
+ | None =>
385
+ result.get("rowCount").grabInt()
386
+ | Some(f) =>
387
+ let all = result.get("rows").grabArray().toList().all { row =>
388
+ f(PgRow(row))
389
+ }
390
+ if(all) {1} else {0}
391
+ }
392
+ }
393
+
394
+ internalBatchStatements(
395
+ connection: PgConnection,
396
+ statements: List[PgStatement],
397
+ body: Option[PgRow => Bool],
398
+ endBody: Option[() => Unit]
399
+ ): List[Int] {
400
+ let sqlCache = statements.map {s => Pair(s.sql, s.sql)}.group().map {sql, list =>
401
+ let pair = internalParseParameters(sql)
402
+ let prepared = if(list.size() >= 10) {
403
+ let hash = UnsafeJs.import("crypto")
404
+ .call1("createHash", "md5")
405
+ .call1("update", pair.first)
406
+ .call1("update", "ffpgps")
407
+ .call1("digest", "hex")
408
+ "ffpgps" + hash.grabString()
409
+ }
410
+ Pair(sql, (newSql = pair.first, parameterNames = pair.second, prepared = prepared))
411
+ }
412
+ let promises = statements.map { statement =>
413
+ UnsafeJs.throwIfCancelled()
414
+ let record = sqlCache.grab(statement.sql)
415
+ let parameters = internalCheckParameters(record.parameterNames, statement.parameters)
416
+ let query = UnsafeJs.jsSystem().object()
417
+ .with("text", record.newSql)
418
+ .with("values", parameters)
419
+ connection.jsValue.call1("query", record.prepared.map {query.with("name", _)}.else {query})
420
+ }
421
+ let results = promises.map { promise =>
422
+ UnsafeJs.throwIfCancelled()
423
+ let result = UnsafeJs.await { promise }
424
+ UnsafeJs.throwIfCancelled()
425
+ body.{
426
+ | None =>
427
+ result.get("rowCount").grabInt()
428
+ | Some(f) =>
429
+ let all = result.get("rows").grabArray().toList().all { row =>
430
+ f(PgRow(row))
431
+ }
432
+ endBody.each {_()}
433
+ if(all) {1} else {0}
434
+ }
435
+ }
436
+ results
437
+ }
438
+
439
+ internalCheckParameters(parameterNames: List[String], parameters: Map[String, JsValue]): Array[JsValue] {
440
+ let arguments = parameterNames.map { name =>
441
+ parameters.get(name).else {
442
+ panic("No value for parameter: " + name)
443
+ }
444
+ }.toArray()
445
+ let unusedParameters = parameters.keys().removeAll(parameterNames.toSet())
446
+ if(unusedParameters.size() > 0) {
447
+ panic("Unused parameters: " + unusedParameters.toList().join(", "))
448
+ }
449
+ arguments
450
+ }
451
+
452
+ internalParseParameters(statementSql: String): Pair[String, List[String]] {
453
+ mutable parameters = []
454
+ mutable parameterIndexes = [].toMap()
455
+ mutable i = 0
456
+ mutable last = 0
457
+ mutable sql = ""
458
+ while {i < statementSql.size()} {
459
+ if(statementSql.grab(i) == '$') {
460
+ sql = sql + statementSql.slice(last, i)
461
+ i += 1
462
+ last = i
463
+ if(statementSql.grab(i) == '$') {
464
+ i += 1
465
+ } else {
466
+ while {i < statementSql.size() && statementSql.grab(i).isAsciiLetterOrDigit()} {
467
+ i += 1
468
+ }
469
+ let name = statementSql.slice(last, i)
470
+ if(name != "") {
471
+ let index = parameterIndexes.get(name).else {
472
+ let newIndex = parameterIndexes.size() + 1
473
+ parameterIndexes = parameterIndexes.add(name, newIndex)
474
+ parameters = [name, ...parameters]
475
+ newIndex
476
+ }
477
+ sql = sql + "$" + index
478
+ last = i
479
+ }
480
+ }
481
+ } else {
482
+ i += 1
483
+ }
484
+ }
485
+ sql = sql + statementSql.slice(last, i)
486
+ Pair(sql, parameters.reverse())
487
+ }
488
+
489
+ main(system: NodeSystem): Unit {
490
+
491
+ let pool = makePool(
492
+ system = system
493
+ host = system.arguments().grab(0)
494
+ database = system.arguments().grab(1)
495
+ user = system.arguments().grab(2)
496
+ password = {system.arguments().grab(3)}
497
+ )
498
+
499
+ pool.transaction {connection =>
500
+ let parties = connection.statement("""
501
+ select name, listCode, entityId
502
+ from election."PartyRow"
503
+ where entityId < $maxEntityId
504
+ """)
505
+ .withInt("maxEntityId", 200)
506
+ .map {row =>
507
+ (
508
+ name = row.getString("name").grab()
509
+ listCode = row.getString("listCode").grab()
510
+ entityId = row.getInt("entityId").grab()
511
+ )
512
+ }
513
+
514
+ connection.batchMap(
515
+ parties.map {item =>
516
+ connection.statement("""
517
+ select id
518
+ from election."PartyRow"
519
+ where name = $name and listCode = $listCode and entityId = $entityId
520
+ """)
521
+ .withString("name", item.name)
522
+ .withString("listCode", item.listCode)
523
+ .withInt("entityId", item.entityId)
524
+ }
525
+ ) {row =>
526
+ //Log.debug(row)
527
+ }
528
+
529
+ }
530
+ }
@@ -0,0 +1 @@
1
+ package ff:unsafejs:0.0.0
@@ -0,0 +1,19 @@
1
+ jsSystem(): JsSystem
2
+ target js async "return typeof globalThis !== 'undefined' ? globalThis : window"
3
+ target js sync "return typeof globalThis !== 'undefined' ? globalThis : window"
4
+
5
+ import(module: String): JsValue
6
+ // Replaced by the compiler ~ hoisted top level import - dynamic imports not currently supported
7
+ target js sync "throw Error('Dynamic JS imports are not currently supported.')"
8
+
9
+ await[T](body: () => T): T // This is never actually called async, but will be rewitten by the compiler
10
+ // Replaced by the compiler
11
+ target js sync "return body_()"
12
+
13
+ throwIfCancelled(): Unit
14
+ // Replaced by the compiler
15
+ target js sync ""
16
+
17
+ cancelled(): Bool
18
+ // Replaced by the compiler
19
+ target js sync "return false"
@@ -0,0 +1,18 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "type": "extensionHost",
6
+ "request": "launch",
7
+ "name": "Launch Client",
8
+ "runtimeExecutable": "${execPath}",
9
+ "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
10
+ "outFiles": ["${workspaceFolder}/client/out/**/*.js"],
11
+ "env": {"FIREFLY_HOME": "${workspaceFolder}/.."},
12
+ "preLaunchTask": {
13
+ "type": "npm",
14
+ "script": "watch"
15
+ }
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "tasks": [
4
+ {
5
+ "type": "npm",
6
+ "script": "compile",
7
+ "group": "build",
8
+ "presentation": {
9
+ "panel": "dedicated",
10
+ "reveal": "never"
11
+ },
12
+ "problemMatcher": [
13
+ "$tsc"
14
+ ]
15
+ },
16
+ {
17
+ "type": "npm",
18
+ "script": "watch",
19
+ "isBackground": true,
20
+ "group": {
21
+ "kind": "build",
22
+ "isDefault": true
23
+ },
24
+ "presentation": {
25
+ "panel": "dedicated",
26
+ "reveal": "never"
27
+ },
28
+ "problemMatcher": [
29
+ "$tsc-watch"
30
+ ]
31
+ }
32
+ ]
33
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020-2023 Joakim Ahnfelt-Rønne, Michael Werk Ravnsmed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,15 @@
1
+ nodeMain(system: NodeSystem) {
2
+ if(!system.path(".").endsWith(["vscode"])) {
3
+ panic("Must stand in the Firefly vscode/ directory.")
4
+ }
5
+ let fireflyOutputPath = system.path("firefly")
6
+ if(fireflyOutputPath.exists()) {fireflyOutputPath.delete()}
7
+ fireflyOutputPath.createDirectory()
8
+ system.path("../output").copyTo(fireflyOutputPath.slash("output"))
9
+ system.path("../compiler").copyTo(fireflyOutputPath.slash("compiler"))
10
+ system.path("../core").copyTo(fireflyOutputPath.slash("core"))
11
+ system.path("../lsp").copyTo(fireflyOutputPath.slash("lsp"))
12
+ system.path("../.firefly-workspace").copyTo(fireflyOutputPath.slash(".firefly-workspace"))
13
+ system.path("../package.json").copyTo(fireflyOutputPath.slash("package.json"))
14
+ system.path("../node_modules").copyTo(fireflyOutputPath.slash("node_modules"))
15
+ }
@@ -0,0 +1,17 @@
1
+ # Firefly language support
2
+
3
+ This extension adds support for the Firefly programming language (`.ff` files). It should work out of the box with no configuration, and comes with the following features:
4
+
5
+ - Autocompletion
6
+ - Go to definition
7
+ - Find references
8
+ - Signature help
9
+ - Symbol renaming
10
+ - Document and workspace symbols
11
+ - Show type on hover
12
+ - Diagnostics`*`
13
+
14
+ `*` Diagnostics don't currently update automatically when included files have been edited. It's disabled for performance reasons, and we're working on a solution.
15
+
16
+ You can run `.ff` main files via the usual *Run and Debug* side panel - just choose *create a launch.json file*. After that you can also press *F5* to run the currently open file.
17
+