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
package/core/Stream.ff ADDED
@@ -0,0 +1,406 @@
1
+ capability Stream[T](
2
+ next: () => Option[T]
3
+ close: () => Unit
4
+ )
5
+
6
+ make[T](next: () => Option[T], close: () => Unit = {}): Stream[T] {
7
+ Stream(next, close)
8
+ }
9
+
10
+ init[T](body: () => Stream[T]): Stream[T] {
11
+ mutable initialized = False
12
+ mutable stream = Stream {None} {}
13
+ Stream({
14
+ if(initialized) {
15
+ stream.next()
16
+ } else {
17
+ initialized = True
18
+ stream = body()
19
+ stream.next()
20
+ }
21
+ }, {
22
+ initialized = True
23
+ stream.close()
24
+ })
25
+ }
26
+
27
+ extend self[T]: Stream[T] {
28
+
29
+ addAll(that: Stream[T]): Stream[T] {
30
+ mutable firstDone = False
31
+ Stream {
32
+ if(firstDone) {
33
+ that.next()
34
+ } else {
35
+ self.next().orElse {
36
+ firstDone = True
37
+ that.next()
38
+ }
39
+ }
40
+ } {
41
+ try {
42
+ self.close()
43
+ } finally {
44
+ that.close()
45
+ } grab()
46
+ }
47
+ }
48
+
49
+ map[S](body: T => S): Stream[S] {
50
+ Stream {
51
+ self.next().map(body)
52
+ } {
53
+ self.close()
54
+ }
55
+ }
56
+
57
+ flatMap[S](body: T => Stream[S]): Stream[S] {
58
+ mutable inner = Stream {None} {}
59
+ Stream {
60
+ mutable result = None
61
+ while {result.isEmpty()} {
62
+ inner.next().{
63
+ | Some(_)@i => result = Some(i)
64
+ | None =>
65
+ self.next().{
66
+ | None => result = Some(None)
67
+ | Some(o) =>
68
+ inner.close()
69
+ inner = body(o)
70
+ }
71
+ }
72
+ }
73
+ result.grab()
74
+ } {
75
+ try {
76
+ inner.close()
77
+ } finally {
78
+ self.close()
79
+ } grab()
80
+ }
81
+ }
82
+
83
+ collect[S](body: T => Option[S]): Stream[S] {
84
+ self.flatMap {body(_).toStream()}
85
+ }
86
+
87
+ filter(body: T => Bool): Stream[T] {
88
+ Stream {
89
+ mutable result = None
90
+ while {result.isEmpty()} {
91
+ self.next().{
92
+ | Some(x) {body(x)} => result = Some(Some(x))
93
+ | Some(_) =>
94
+ | None => result = Some(None)
95
+ }
96
+ }
97
+ result.grab()
98
+ } {
99
+ self.close()
100
+ }
101
+ }
102
+
103
+ zip[S](that: Stream[S]): Stream[Pair[T, S]] {
104
+ Stream {
105
+ Pair(self.next(), that.next()).{
106
+ | Pair(Some(x), Some(y)) => Some(Pair(x, y))
107
+ | _ => None
108
+ }
109
+ } {
110
+ try {
111
+ self.close()
112
+ } finally {
113
+ that.close()
114
+ } grab()
115
+ }
116
+ }
117
+
118
+ takeFirst(count: Int = 1): Stream[T] {
119
+ mutable remaining = count
120
+ Stream {
121
+ self.next().filter {_ =>
122
+ remaining -= 1
123
+ remaining >= 0
124
+ }
125
+ } {
126
+ self.close()
127
+ }
128
+ }
129
+
130
+ dropFirst(count: Int = 1): Stream[T] {
131
+ mutable remaining = count
132
+ Stream {
133
+ while {remaining >= 1} {
134
+ self.next().{
135
+ | None => remaining = 0
136
+ | Some(_) => remaining -= 1
137
+ }
138
+ }
139
+ self.next()
140
+ } {
141
+ self.close()
142
+ }
143
+ }
144
+
145
+ takeWhile(body: T => Bool): Stream[T] {
146
+ mutable done = False
147
+ Stream {
148
+ if(done) {None} else:
149
+ self.next().{
150
+ | None =>
151
+ done = True
152
+ None
153
+ | Some(x)@o =>
154
+ done = !body(x)
155
+ if(done) {None} else {o}
156
+ }
157
+ } {
158
+ self.close()
159
+ }
160
+ }
161
+
162
+ dropWhile(body: T => Bool): Stream[T] {
163
+ mutable done = False
164
+ Stream {
165
+ if(!done) {
166
+ mutable result = None
167
+ while {!done} {
168
+ self.next().{
169
+ | None => done = True
170
+ | Some(x) {body(x)} =>
171
+ | Some(x)@o =>
172
+ result = o
173
+ done = True
174
+ }
175
+ }
176
+ result
177
+ } else {
178
+ self.next()
179
+ }
180
+ } {
181
+ self.close()
182
+ }
183
+ }
184
+
185
+ pairs(): Stream[Pair[Int, T]] {
186
+ mutable i = 0
187
+ self.map {x =>
188
+ let r = Pair(i, x)
189
+ i += 1
190
+ r
191
+ }
192
+ }
193
+
194
+ chunked(size: Int): Stream[List[T]] {
195
+ mutable remaining = size
196
+ Stream {
197
+ if(remaining <= 0) {None} else:
198
+ self.next().{
199
+ | None =>
200
+ remaining = -1
201
+ None
202
+ | Some(x) =>
203
+ mutable list = [x]
204
+ remaining -= 1
205
+ while {remaining > 0} {
206
+ remaining -= 1
207
+ self.next().{
208
+ | None => remaining = -1
209
+ | Some(x) => list = [x, ...list]
210
+ }
211
+ }
212
+ if(remaining != -1) {remaining = size}
213
+ Some(list.reverse())
214
+ }
215
+ } {
216
+ self.close()
217
+ }
218
+ }
219
+
220
+ // Consuming methods
221
+
222
+ use[R](body: Stream[T] => R): R {
223
+ try {
224
+ body(self)
225
+ } finally {
226
+ self.close()
227
+ } grab()
228
+ }
229
+
230
+ each(body: T => Unit): Unit {
231
+ try {
232
+ mutable done = False
233
+ while {!done} {
234
+ self.next().{
235
+ | None => done = True
236
+ | Some(x) => body(x)
237
+ }
238
+ }
239
+ } finally {
240
+ self.close()
241
+ } grab()
242
+ }
243
+
244
+ eachWhile(body: T => Bool): Unit {
245
+ try {
246
+ mutable done = False
247
+ while {!done} {
248
+ self.next().{
249
+ | None => done = True
250
+ | Some(x) => done = !body(x)
251
+ }
252
+ }
253
+ } finally {
254
+ self.close()
255
+ } grab()
256
+ }
257
+
258
+ all(body: T => Bool): Bool {
259
+ mutable result = True
260
+ self.eachWhile {x =>
261
+ result = result && body(x)
262
+ result
263
+ }
264
+ result
265
+ }
266
+
267
+ any(body: T => Bool): Bool {
268
+ mutable result = False
269
+ self.eachWhile {x =>
270
+ result = result || body(x)
271
+ (!result)
272
+ }
273
+ result
274
+ }
275
+
276
+ first(): Option[T] {
277
+ try {
278
+ self.next()
279
+ } finally {
280
+ self.close()
281
+ } grab()
282
+ }
283
+
284
+ last(): Option[T] {
285
+ try {
286
+ mutable done = False
287
+ mutable result = None
288
+ while {!done} {
289
+ self.next().{
290
+ | None => done = True
291
+ | Some(x)@o => result = o
292
+ }
293
+ }
294
+ result
295
+ } finally {
296
+ self.close()
297
+ } grab()
298
+ }
299
+
300
+ grabFirst(): T {
301
+ self.first().else {panic("grabFirst() on empty iterator")}
302
+ }
303
+
304
+ grabLast(): T {
305
+ self.last().else {panic("grabLast() on empty iterator")}
306
+ }
307
+
308
+ collectFirst[R](body: T => Option[R]): Option[R] {
309
+ try {
310
+ mutable done = False
311
+ mutable result = None
312
+ while {!done} {
313
+ self.next().{
314
+ | None => done = True
315
+ | Some(x) =>
316
+ body(x).{
317
+ | None =>
318
+ | o =>
319
+ done = True
320
+ result = o
321
+ }
322
+ }
323
+ }
324
+ result
325
+ } finally {
326
+ self.close()
327
+ } grab()
328
+ }
329
+
330
+ find(body: T => Bool): Option[T] {
331
+ self.filter(body).first()
332
+ }
333
+
334
+ foldLeft[R](initial: R, body: (R, T) => R): R {
335
+ mutable result = initial
336
+ self.each {result = body(result, _)}
337
+ result
338
+ }
339
+
340
+ toStack(): Stack[T] {
341
+ let stack = Stack.make()
342
+ self.each {stack.push(_)}
343
+ stack
344
+ }
345
+
346
+ toArray(): Array[T] {
347
+ self.toStack().drain()
348
+ }
349
+
350
+ toList(): List[T] {
351
+ self.toStack().toList()
352
+ }
353
+
354
+ }
355
+
356
+ extend self[T]: Stream[Stream[T]] {
357
+ flatten(): Stream[T] {
358
+ self.flatMap {_}
359
+ }
360
+ }
361
+
362
+ extend self[T: Order]: Stream[T] {
363
+ toSet(): Set[T] {
364
+ self.toArray().toSet()
365
+ }
366
+ }
367
+
368
+ extend self[K: Order, V]: Stream[Pair[K, V]] {
369
+ toMap(): Map[K, V] {
370
+ self.toArray().toMap()
371
+ }
372
+ }
373
+
374
+ extend self: Stream[Buffer] {
375
+
376
+ toBuffer(): Buffer {
377
+ let builder = Stack.make()
378
+ self.each {builder.push(_)}
379
+ Buffer.fromBufferArray(builder.drain())
380
+ }
381
+
382
+ toString(encoding: String = "utf8"): String {
383
+ self.toBuffer().toString(encoding)
384
+ }
385
+
386
+ readBytes(bytes: Int): Pair[Array[Buffer], Stream[Buffer]] {
387
+ if(bytes <= 0) {Pair([].toArray(), self)} else:
388
+ let buffers = Stack.make()
389
+ mutable buffer = self.next().grab()
390
+ mutable taken = 0
391
+ mutable remainder = None
392
+ while {remainder == None} {
393
+ let needed = bytes - taken
394
+ if(needed > buffer.size()) {
395
+ buffers.push(buffer)
396
+ taken += buffer.size()
397
+ buffer = self.next().grab()
398
+ } else {
399
+ buffers.push(buffer.view(0, needed))
400
+ remainder = Some(buffer.view(needed, buffer.size()))
401
+ }
402
+ }
403
+ Pair(buffers.drain(), remainder.toStream().addAll(self))
404
+ }
405
+
406
+ }
package/core/String.ff ADDED
@@ -0,0 +1,175 @@
1
+ data String {}
2
+
3
+ extend self: String {
4
+
5
+ size(): Int
6
+ target js sync "return self_.length"
7
+
8
+ grab(index: Int): Char
9
+ target js sync """
10
+ if(index_ < 0 || index_ >= self_.length) {
11
+ ff_core_Try.internalThrowGrabException_()
12
+ }
13
+ return self_.charCodeAt(index_)
14
+ """
15
+
16
+ replace(needle: String, replacement: String): String
17
+ target js sync "return self_.replaceAll(needle_, replacement_)"
18
+
19
+ replaceFirst(needle: String, replacement: String): String
20
+ target js sync "return self_.replace(needle_, replacement_)"
21
+
22
+ reverse(): String
23
+ target js sync "return [...self_].reverse().join('')"
24
+
25
+ lower(): String
26
+ target js sync "return self_.toLowerCase()"
27
+
28
+ upper(): String
29
+ target js sync "return self_.toUpperCase()"
30
+
31
+ dropWhile(p: Char => Bool): String
32
+ target js sync """
33
+ let i = 0
34
+ for(; i < self_.length && p_(self_.codePointAt(i)); i++);
35
+ return self_.slice(i)
36
+ """
37
+ target js async """
38
+ let i = 0
39
+ for(; i < self_.length && await p_(self_.codePointAt(i), $task); i++);
40
+ return self_.slice(i)
41
+ """
42
+
43
+ takeWhile(p: Char => Bool): String
44
+ target js sync """
45
+ let i = 0
46
+ for(; i < self_.length && p_(self_.codePointAt(i)); i++);
47
+ return self_.slice(0, i)
48
+ """
49
+ target js async """
50
+ let i = 0
51
+ for(; i < self_.length && await p_(self_.codePointAt(i), $task); i++);
52
+ return self_.slice(0, i)
53
+ """
54
+
55
+ slice(from: Int, until: Int): String
56
+ target js sync "return self_.slice(from_, until_)"
57
+
58
+ split(char: Char): Array[String]
59
+ target js sync "return self_.split(String.fromCharCode(char_))"
60
+
61
+ splitFirst(char: Char): Option[Pair[String, String]]
62
+ target js sync """
63
+ const array = self_.split(String.fromCharCode(char_), 2)
64
+ return array.length === 2
65
+ ? ff_core_Option.Some(ff_core_Pair.Pair(array[0], array[1]))
66
+ : ff_core_Option.None()
67
+ """
68
+
69
+ lines(): List[String]
70
+ target js sync """
71
+ return ff_core_Array.Array_toList(self_.split(
72
+ new RegExp("[" + String.fromCharCode(13) + "]?[" + String.fromCharCode(10) + "]", "g")
73
+ ))
74
+ """
75
+
76
+ dropFirst(count: Int = 1): String
77
+ target js sync "return self_.slice(count_)"
78
+
79
+ dropLast(count: Int = 1): String
80
+ target js sync "return self_.slice(0, self_.length - count_)"
81
+
82
+ getInt(): Option[Int]
83
+ target js sync """
84
+ if(self_.length == 0) {
85
+ return ff_core_Option.None()
86
+ }
87
+ for(let i = 0; i < self_.length; i++) {
88
+ const c = self_.codePointAt(i)
89
+ if(c < 48 || c > 57) ff_core_Option.None()
90
+ }
91
+ return ff_core_Option.Some(parseInt(self_, 10));
92
+ """
93
+
94
+ grabInt(): Int
95
+ target js sync """
96
+ if(self_.length == 0) {
97
+ ff_core_Try.internalThrowGrabException_()
98
+ }
99
+ for(let i = 0; i < self_.length; i++) {
100
+ const c = self_.codePointAt(i)
101
+ if(c < 48 || c > 57) ff_core_Try.internalThrowGrabException_()
102
+ }
103
+ return parseInt(self_, 10);
104
+ """
105
+
106
+ first(): Option[Char]
107
+ target js sync """
108
+ return self_.length > 0
109
+ ? ff_core_Option.Some(self_.charCodeAt(0))
110
+ : ff_core_Option.None()
111
+ """
112
+
113
+ last(): Option[Char]
114
+ target js sync """
115
+ return self_.length > 0
116
+ ? ff_core_Option.Some(self_.charCodeAt(self_.length - 1))
117
+ : ff_core_Option.None()
118
+ """
119
+
120
+ grabFirst(): Char { self.first().else {Try.internalThrowGrabException()} }
121
+
122
+ grabLast(): Char { self.last().else {Try.internalThrowGrabException()} }
123
+
124
+ contains(substring: String): Bool
125
+ target js sync "return self_.includes(substring_)"
126
+
127
+ startsWith(prefix: String, offset: Int = 0): Bool
128
+ target js sync "return self_.startsWith(prefix_, offset_)"
129
+
130
+ endsWith(prefix: String): Bool
131
+ target js sync "return self_.endsWith(prefix_)"
132
+
133
+ removeFirst(prefix: String): Option[String] {
134
+ if(self.startsWith(prefix)) {Some(self.dropFirst(prefix.size()))} else {None}
135
+ }
136
+
137
+ removeLast(suffix: String): Option[String] {
138
+ if(self.endsWith(suffix)) {Some(self.dropLast(suffix.size()))} else {None}
139
+ }
140
+
141
+ any(body: Char => Bool): Bool
142
+ target js sync """
143
+ for(let i = 0; i < self_.length; i++) {
144
+ if(body_(self_.charCodeAt(i))) return true;
145
+ }
146
+ return false;
147
+ """
148
+ target js async """
149
+ for(let i = 0; i < self_.length; i++) {
150
+ if(await body_(self_.charCodeAt(i), $task)) return true;
151
+ }
152
+ return false;
153
+ """
154
+
155
+ all(body: Char => Bool): Bool
156
+ target js sync """
157
+ for(let i = 0; i < self_.length; i++) {
158
+ if(!body_(self_.charCodeAt(i))) return false;
159
+ }
160
+ return true;
161
+ """
162
+ target js async """
163
+ for(let i = 0; i < self_.length; i++) {
164
+ if(!await body_(self_.charCodeAt(i), $task)) return false;
165
+ }
166
+ return true;
167
+ """
168
+
169
+ toBuffer(): Buffer
170
+ target js sync """
171
+ const encoded = new TextEncoder().encode(self_)
172
+ return new DataView(encoded.buffer, encoded.byteOffset, encoded.byteLength)
173
+ """
174
+
175
+ }
@@ -0,0 +1,85 @@
1
+ class StringMap[V] {}
2
+
3
+ make[V](): StringMap[V]
4
+ target js sync "return new Map()"
5
+
6
+ extend self[V]: StringMap[V] {
7
+
8
+ get(key: String): Option[V]
9
+ target js sync "return self_.has(key_) ? ff_core_Option.Some(self_.get(key_)) : ff_core_Option.None()"
10
+
11
+ grab(key: String): V
12
+ target js sync """
13
+ const result = self_.get(key_)
14
+ if(key_ === void 0 && !self_.has(key_)) {
15
+ ff_core_Try.internalThrowGrabException_()
16
+ }
17
+ return result
18
+ """
19
+
20
+ set(key: String, value: V): Unit
21
+ target js sync "self_.set(key_, value_)"
22
+
23
+ has(key: String): Bool
24
+ target js sync "return self_.has(key_)"
25
+
26
+ remove(key: String): Bool
27
+ target js sync "return self_.delete(key_)"
28
+
29
+ clear(): Unit
30
+ target js sync "self_.clear()"
31
+
32
+ size(): Int
33
+ target js sync "return self_.size"
34
+
35
+ each(body: (String, V) => Unit): Bool
36
+ target js sync "return self_.forEach((v, k) => body_(k, v))"
37
+ target js async "for(const [k, v] of self_) await body_(k, v)"
38
+
39
+ eachWhile(body: (String, V) => Bool): Bool
40
+ target js sync "for(const [k, v] of self_) if(!body_(k, v)) break"
41
+ target js async "for(const [k, v] of self_) if(!await body_(k, v)) break"
42
+
43
+ toStack(): Stack[Pair[String, V]] {
44
+ let stack = Stack.make()
45
+ self.each {k, v => stack.push(Pair(k, v))}
46
+ stack
47
+ }
48
+
49
+ toArray(): Array[Pair[String, V]] {
50
+ self.toStack().drain()
51
+ }
52
+
53
+ toList(): List[Pair[String, V]] {
54
+ self.toArray().toList()
55
+ }
56
+
57
+ toStream(): Stream[Pair[String, V]] {
58
+ self.toArray().toStream()
59
+ }
60
+
61
+ toMap(): Map[String, V] {
62
+ self.toArray().toMap()
63
+ }
64
+
65
+ keys(): List[String] {
66
+ let stack = Stack.make()
67
+ self.each {k, v => stack.push(k)}
68
+ stack.toList()
69
+ }
70
+
71
+ values(): List[V] {
72
+ let stack = Stack.make()
73
+ self.each {k, v => stack.push(v)}
74
+ stack.toList()
75
+ }
76
+
77
+ copy(): StringMap[V]
78
+ target js sync "return new Map(self_)"
79
+
80
+ getOrSet(key: String, body: () => V): V {
81
+ if(!self.has(key)) {self.set(key, body())}
82
+ self.grab(key)
83
+ }
84
+
85
+ }