firefly-compiler 0.5.35 → 0.5.37

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,68 +1,68 @@
1
- newtype SourceLocation(location: String) // E.g. "directory/Module:line:column,group,package>Type>function"
2
-
3
- here(location: SourceLocation = SourceLocation.callSite()): SourceLocation {
4
- location
5
- }
6
-
7
- callSite(): SourceLocation {
8
- panic("SourceLocation.callSite() can only occur as the default value of an argument")
9
- }
10
-
11
- extend self: SourceLocation {
12
-
13
- group(): String {
14
- self.location.dropWhile {_ != ','}.dropFirst().takeWhile {_ != ','}
15
- }
16
-
17
- package(): String {
18
- self.location.dropWhile {_ != ','}.dropFirst().dropWhile {_ != ','}.dropFirst().takeWhile {_ != '>'}
19
- }
20
-
21
- directory(): String {
22
- self.location.takeWhile {_ != ':'}.reverse().dropWhile {_ != '/'}.dropFirst().reverse()
23
- }
24
-
25
- module(): String {
26
- self.location.takeWhile {_ != ':'}.reverse().takeWhile {_ != '/'}.reverse()
27
- }
28
-
29
- line(): Int {
30
- self.location.dropWhile {_ != ':'}.dropFirst().takeWhile {_ != ':'}.grabInt()
31
- }
32
-
33
- column(): Int {
34
- self.location.dropWhile {_ != ':'}.dropFirst().dropWhile {_ != ':'}.dropFirst().takeWhile {_ != ','}.grabInt()
35
- }
36
-
37
- breadcrumbs(): List[String] {
38
- self.location.dropWhile {_ != '>'}.dropFirst().split('>')
39
- }
40
-
41
- }
42
-
43
- instance SourceLocation: Show {
44
- show(self: SourceLocation): String {
45
- self.location
46
- }
47
- }
48
-
49
- instance SourceLocation: Equal {
50
- equals(a: SourceLocation, b: SourceLocation): Bool {
51
- a.location == b.location
52
- }
53
- }
54
-
55
- instance SourceLocation: Order {
56
- compare(a: SourceLocation, b: SourceLocation): Ordering {
57
- Ordering.compare(a.location, b.location)
58
- }
59
- }
60
-
61
- instance SourceLocation: Serializable {
62
- serializeUsing(serialization: Serialization, self: SourceLocation) {
63
- Serializable.serializeUsing(serialization, self.location)
64
- }
65
- deserializeUsing(serialization: Serialization): SourceLocation {
66
- SourceLocation(Serializable.deserializeUsing(serialization))
67
- }
68
- }
1
+ newtype SourceLocation(location: String) // E.g. "directory/Module:line:column,group,package>Type>function"
2
+
3
+ here(location: SourceLocation = SourceLocation.callSite()): SourceLocation {
4
+ location
5
+ }
6
+
7
+ callSite(): SourceLocation {
8
+ panic("SourceLocation.callSite() can only occur as the default value of an argument")
9
+ }
10
+
11
+ extend self: SourceLocation {
12
+
13
+ group(): String {
14
+ self.location.dropWhile {_ != ','}.dropFirst().takeWhile {_ != ','}
15
+ }
16
+
17
+ package(): String {
18
+ self.location.dropWhile {_ != ','}.dropFirst().dropWhile {_ != ','}.dropFirst().takeWhile {_ != '>'}
19
+ }
20
+
21
+ directory(): String {
22
+ self.location.takeWhile {_ != ':'}.reverse().dropWhile {_ != '/'}.dropFirst().reverse()
23
+ }
24
+
25
+ module(): String {
26
+ self.location.takeWhile {_ != ':'}.reverse().takeWhile {_ != '/'}.reverse()
27
+ }
28
+
29
+ line(): Int {
30
+ self.location.dropWhile {_ != ':'}.dropFirst().takeWhile {_ != ':'}.grabInt()
31
+ }
32
+
33
+ column(): Int {
34
+ self.location.dropWhile {_ != ':'}.dropFirst().dropWhile {_ != ':'}.dropFirst().takeWhile {_ != ','}.grabInt()
35
+ }
36
+
37
+ breadcrumbs(): List[String] {
38
+ self.location.dropWhile {_ != '>'}.dropFirst().split('>')
39
+ }
40
+
41
+ }
42
+
43
+ instance SourceLocation: Show {
44
+ show(self: SourceLocation): String {
45
+ self.location
46
+ }
47
+ }
48
+
49
+ instance SourceLocation: Equal {
50
+ equals(a: SourceLocation, b: SourceLocation): Bool {
51
+ a.location == b.location
52
+ }
53
+ }
54
+
55
+ instance SourceLocation: Order {
56
+ compare(a: SourceLocation, b: SourceLocation): Ordering {
57
+ Ordering.compare(a.location, b.location)
58
+ }
59
+ }
60
+
61
+ instance SourceLocation: Serializable {
62
+ serializeUsing(serialization: Serialization, self: SourceLocation) {
63
+ Serializable.serializeUsing(serialization, self.location)
64
+ }
65
+ deserializeUsing(serialization: Serialization): SourceLocation {
66
+ SourceLocation(Serializable.deserializeUsing(serialization))
67
+ }
68
+ }
package/core/Stream.ff CHANGED
@@ -7,7 +7,7 @@ new[T](next: () => Option[T], close: () => Unit = {}): Stream[T] {
7
7
  Stream(next, close)
8
8
  }
9
9
 
10
- init[T](body: () => Stream[T]): Stream[T] {
10
+ do[T](body: () => Stream[T]): Stream[T] {
11
11
  mutable initialized = False
12
12
  mutable stream = Stream {None} {}
13
13
  Stream({
package/core/String.ff CHANGED
@@ -2,163 +2,157 @@ data String {}
2
2
 
3
3
  extend self: String {
4
4
 
5
- size(): Int
6
- target js sync "return self_.length"
5
+ size(): Int {
6
+ self!->length?
7
+ }
7
8
 
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
- repeat(count: Int): String
26
- target js sync "return self_.repeat(count_)"
27
-
28
- trim(): String
29
- target js sync "return self_.trim()"
30
-
31
- trimStart(): String
32
- target js sync "return self_.trimStart()"
33
-
34
- trimEnd(): String
35
- target js sync "return self_.trimEnd()"
36
-
37
- lower(): String
38
- target js sync "return self_.toLowerCase()"
39
-
40
- upper(): String
41
- target js sync "return self_.toUpperCase()"
42
-
43
- dropWhile(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(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(i)
53
- """
54
-
55
- takeWhile(p: Char => Bool): String
56
- target js sync """
57
- let i = 0
58
- for(; i < self_.length && p_(self_.codePointAt(i)); i++);
59
- return self_.slice(0, i)
60
- """
61
- target js async """
62
- let i = 0
63
- for(; i < self_.length && await p_(self_.codePointAt(i), $task); i++);
64
- return self_.slice(0, i)
65
- """
66
-
67
- slice(from: Int, until: Int): String
68
- target js sync "return self_.slice(from_, until_)"
69
-
70
- split(char: Char): List[String]
71
- target js sync "return self_.split(String.fromCharCode(char_))"
72
-
73
- splitFirst(char: Char): Option[Pair[String, String]]
74
- target js sync """
75
- const array = self_.split(String.fromCharCode(char_), 2)
76
- return array.length === 2
77
- ? ff_core_Option.Some(ff_core_Pair.Pair(array[0], array[1]))
78
- : ff_core_Option.None()
79
- """
80
-
81
- lines(): List[String]
82
- target js sync """
83
- return self_.split(
84
- new RegExp("[" + String.fromCharCode(13) + "]?[" + String.fromCharCode(10) + "]", "g")
85
- )
86
- """
87
-
88
- dropFirst(count: Int = 1): String
89
- target js sync "return self_.slice(count_)"
90
-
91
- dropLast(count: Int = 1): String
92
- target js sync "return self_.slice(0, self_.length - count_)"
93
-
94
- getInt(): Option[Int]
95
- target js sync """
96
- if(self_.length == 0) {
97
- return ff_core_Option.None()
98
- }
99
- for(let i = 0; i < self_.length; i++) {
100
- const c = self_.codePointAt(i)
101
- if(c < 48 || c > 57) return ff_core_Option.None()
102
- }
103
- return ff_core_Option.Some(parseInt(self_, 10));
104
- """
105
-
106
- getFloat(): Float
107
- target js sync """
108
- const result = parseFloat(self_, 10);
109
- if(!isFinite(result)) {
110
- return ff_core_Option.None()
111
- }
112
- return ff_core_Option.Some(result);
113
- """
9
+ grab(index: Int): Char {
10
+ if(index < 0 || index >= self.size()) {
11
+ throw(GrabException())
12
+ }
13
+ self!->charCodeAt(index)?
14
+ }
15
+
16
+ replace(needle: String, replacement: String): String {
17
+ self!->replaceAll(needle, replacement)?
18
+ }
114
19
 
115
- grabInt(): Int
116
- target js sync """
117
- if(self_.length == 0) {
118
- ff_core_Try.internalThrowGrabException_()
119
- }
120
- for(let i = 0; i < self_.length; i++) {
121
- const c = self_.codePointAt(i)
122
- if(c < 48 || c > 57) ff_core_Try.internalThrowGrabException_()
123
- }
124
- return parseInt(self_, 10);
125
- """
20
+ replaceFirst(needle: String, replacement: String): String {
21
+ self!->replace(needle, replacement)?
22
+ }
23
+
24
+ reverse(): String {
25
+ self!->split("")->reverse()->join("")?
26
+ }
27
+
28
+ repeat(count: Int): String {
29
+ self!->repeat(count)?
30
+ }
31
+
32
+ trim(): String {
33
+ self!->trim()?
34
+ }
35
+
36
+ trimStart(): String {
37
+ self!->trimStart()?
38
+ }
39
+
40
+ trimEnd(): String {
41
+ self!->trimEnd()?
42
+ }
43
+
44
+ lower(): String {
45
+ self!->toLowerCase()?
46
+ }
47
+
48
+ upper(): String {
49
+ self!->toUpperCase()?
50
+ }
51
+
52
+ dropWhile(p: Char => Bool): String {
53
+ mutable i = 0
54
+ while {i < self.size() && p(self!->charCodeAt(i)?)} {
55
+ i += 1
56
+ }
57
+ self!->slice(i)?
58
+ }
59
+
60
+ takeWhile(p: Char => Bool): String {
61
+ mutable i = 0
62
+ while {i < self.size() && p(self!->charCodeAt(i)?)} {
63
+ i += 1
64
+ }
65
+ self!->slice(0, i)?
66
+ }
67
+
68
+ slice(from: Int, until: Int): String {
69
+ self!->slice(from, until)?
70
+ }
71
+
72
+ split(char: Char): List[String] {
73
+ self!->split(Js->String->fromCharCode(char))?
74
+ }
75
+
76
+ splitFirst(char: Char): Option[Pair[String, String]] {
77
+ let array: List[String] = self!->split(Js->String->fromCharCode(char), 2)?
78
+ if(array.size() == 2) {
79
+ Pair(array!.get(0)?, array!.get(1)?)
80
+ }
81
+ }
82
+
83
+ lines(): List[String] {
84
+ self!->split(
85
+ Js->RegExp->("[" + Js->String->fromCharCode(13)? + "]?[" + Js->String->fromCharCode(10)? + "]", "g")
86
+ )?
87
+ }
88
+
89
+ dropFirst(count: Int = 1): String {
90
+ self!->slice(count)?
91
+ }
92
+
93
+ dropLast(count: Int = 1): String {
94
+ self!->slice(0, self.size() - count)?
95
+ }
96
+
97
+ getInt(): Option[Int] {
98
+ if(self.size() > 0 && self.all {c => 48 <= c.codeUnit && c.codeUnit <= 57}) {
99
+ Js->parseInt(self!, 10)?
100
+ }
101
+ }
102
+
103
+ getFloat(): Option[Float] {
104
+ // TODO return None for invalid input
105
+ let result = Js->parseFloat(self!, 10)
106
+ if(Js->isFinite(result)?) {result?}
107
+ }
108
+
109
+ grabInt(): Int {
110
+ self.getInt().else {
111
+ throw(GrabException())
112
+ }
113
+ }
126
114
 
127
- grabFloat(): Float
128
- target js sync """
129
- const result = parseFloat(self_, 10);
130
- if(!isFinite(result)) {
131
- ff_core_Try.internalThrowGrabException_()
132
- }
133
- return result;
134
- """
115
+ grabFloat(): Float {
116
+ self.getFloat().else {
117
+ throw(GrabException())
118
+ }
119
+ }
135
120
 
136
- first(): Option[Char]
137
- target js sync """
138
- return self_.length > 0
139
- ? ff_core_Option.Some(self_.charCodeAt(0))
140
- : ff_core_Option.None()
141
- """
121
+ first(): Option[Char] {
122
+ if(self.size() > 0) {
123
+ Char(self!->charCodeAt(0)?)
124
+ }
125
+ }
142
126
 
143
- last(): Option[Char]
144
- target js sync """
145
- return self_.length > 0
146
- ? ff_core_Option.Some(self_.charCodeAt(self_.length - 1))
147
- : ff_core_Option.None()
148
- """
127
+ last(): Option[Char] {
128
+ if(self.size() > 0) {
129
+ Char(self!->charCodeAt(self.size() - 1)?)
130
+ }
131
+ }
149
132
 
150
- grabFirst(): Char {self.first().else {Try.internalThrowGrabException()}}
133
+ grabFirst(): Char {
134
+ self.first().else {
135
+ throw(GrabException())
136
+ }
137
+ }
151
138
 
152
- grabLast(): Char {self.last().else {Try.internalThrowGrabException()}}
139
+ grabLast(): Char {
140
+ self.last().else {
141
+ throw(GrabException())
142
+ }
143
+ }
153
144
 
154
- contains(substring: String): Bool
155
- target js sync "return self_.includes(substring_)"
145
+ contains(substring: String): Bool {
146
+ self!->includes(substring)?
147
+ }
156
148
 
157
- startsWith(prefix: String, offset: Int = 0): Bool
158
- target js sync "return self_.startsWith(prefix_, offset_)"
149
+ startsWith(prefix: String, offset: Int = 0): Bool {
150
+ self!->startsWith(prefix, offset)?
151
+ }
159
152
 
160
- endsWith(prefix: String): Bool
161
- target js sync "return self_.endsWith(prefix_)"
153
+ endsWith(prefix: String): Bool {
154
+ self!->endsWith(prefix)?
155
+ }
162
156
 
163
157
  removeFirst(prefix: String): Option[String] {
164
158
  if(self.startsWith(prefix)) {Some(self.dropFirst(prefix.size()))} else {None}
@@ -168,64 +162,92 @@ extend self: String {
168
162
  if(self.endsWith(suffix)) {Some(self.dropLast(suffix.size()))} else {None}
169
163
  }
170
164
 
171
- padStart(length: Int, padding: String = " "): String
172
- target js sync """
173
- return self_.padStart(length_, padding_);
174
- """
175
-
176
- padEnd(length: Int, padding: String = " "): String
177
- target js sync """
178
- return self_.padEnd(length_, padding_);
179
- """
180
-
181
- any(body: Char => Bool): Bool
182
- target js sync """
183
- for(let i = 0; i < self_.length; i++) {
184
- if(body_(self_.charCodeAt(i))) return true;
185
- }
186
- return false;
187
- """
188
- target js async """
189
- for(let i = 0; i < self_.length; i++) {
190
- if(await body_(self_.charCodeAt(i), $task)) return true;
191
- }
192
- return false;
193
- """
165
+ padStart(length: Int, padding: String = " "): String {
166
+ self!->padStart(length, padding)?
167
+ }
194
168
 
195
- all(body: Char => Bool): Bool
196
- target js sync """
197
- for(let i = 0; i < self_.length; i++) {
198
- if(!body_(self_.charCodeAt(i))) return false;
199
- }
200
- return true;
201
- """
202
- target js async """
203
- for(let i = 0; i < self_.length; i++) {
204
- if(!await body_(self_.charCodeAt(i), $task)) return false;
205
- }
206
- return true;
207
- """
208
-
209
- filter(body: Char => Bool): String
210
- target js sync """
211
- const result = [];
212
- for(let i = 0; i < self_.length; i++) {
213
- if(body_(self_.charCodeAt(i))) result.push(self_.charAt(i));
169
+ padEnd(length: Int, padding: String = " "): String {
170
+ self!->padEnd(length, padding)?
171
+ }
172
+
173
+ each(body: Char => Unit): Unit {
174
+ mutable i = 0
175
+ while {i < self.size()} {
176
+ body(Char(self!->charCodeAt(i)?))
177
+ i += 1
178
+ }
179
+ }
180
+
181
+ eachWhile(body: Char => Bool): Unit {
182
+ mutable i = 0
183
+ while {i < self.size()} {
184
+ if(body(Char(self!->charCodeAt(i)?))) {
185
+ i += 1
186
+ } else {
187
+ i = self.size()
214
188
  }
215
- return result.join("");
216
- """
217
- target js async """
218
- const result = [];
219
- for(let i = 0; i < self_.length; i++) {
220
- if(await body_(self_.charCodeAt(i))) result.push(self_.charAt(i));
189
+ }
190
+ }
191
+
192
+ all(body: Char => Bool): Bool {
193
+ mutable result = True
194
+ self.eachWhile {x =>
195
+ result = body(x)
196
+ result
197
+ }
198
+ result
199
+ }
200
+
201
+ any(body: Char => Bool): Bool {
202
+ mutable result = False
203
+ self.eachWhile {x =>
204
+ result = body(x)
205
+ (!result)
206
+ }
207
+ result
208
+ }
209
+
210
+ find(body: Char => Bool): Option[Char] {
211
+ mutable result = None
212
+ self.eachWhile {x =>
213
+ if(body(x)) {
214
+ result = Some(x)
215
+ False
216
+ } else {
217
+ True
221
218
  }
222
- return result.join("");
223
- """
219
+ }
220
+ result
221
+ }
224
222
 
225
- toBuffer(): Buffer
226
- target js sync """
227
- const encoded = new TextEncoder().encode(self_)
228
- return new DataView(encoded.buffer, encoded.byteOffset, encoded.byteLength)
229
- """
223
+ indexOf(needle: String, position: Int = 0): Option[Int] {
224
+ let index = self!->indexOf(needle, position)?
225
+ if(index != -1) {index}
226
+ }
227
+
228
+ indexWhere(body: Char => Bool): Option[Int] {
229
+ mutable i = -1
230
+ mutable result = False
231
+ self.eachWhile {x =>
232
+ i += 1
233
+ result = body(x)
234
+ (!result)
235
+ }
236
+ if(result) {i}
237
+ }
238
+
239
+ filter(body: Char => Bool): String {
240
+ let result = Array.new()
241
+ self.each {x =>
242
+ if(body(x)) {
243
+ result.push(x.toString())
244
+ }
245
+ }
246
+ result.join()
247
+ }
230
248
 
249
+ toBuffer(): Buffer {
250
+ let encoded = Js->TextEncoder->()->encode(self)
251
+ Js->DataView->(encoded->buffer, encoded->byteOffset, encoded->byteLength)?
252
+ }
231
253
  }