firefly-compiler 0.5.34 → 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 (228) 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/.firefly/include/package-lock.json +0 -564
  225. package/core/UnsafeJs.ff +0 -42
  226. package/output/js/ff/core/UnsafeJs.mjs +0 -191
  227. package/postgresql/.firefly/include/package-lock.json +0 -250
  228. package/webserver/.firefly/include/package-lock.json +0 -22
package/core/StringMap.ff CHANGED
@@ -1,45 +1,66 @@
1
1
  class StringMap[V] {}
2
2
 
3
- new[V](): StringMap[V]
4
- target js sync "return new Map()"
5
-
3
+ new[V](): StringMap[V] {
4
+ Js->Map->()?
5
+ }
6
+
6
7
  extend self[V]: StringMap[V] {
7
8
 
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_)"
9
+ get(key: String): Option[V] {
10
+ let result = self!->get(key)
11
+ if(!result.isUndefined() || self!->has(key)?) {result?}
12
+ }
25
13
 
26
- remove(key: String): Bool
27
- target js sync "return self_.delete(key_)"
14
+ grab(key: String): V {
15
+ let result = self!->get(key)
16
+ if(result.isUndefined() && !self.has(key)) {throw(GrabException())}
17
+ result?
18
+ }
19
+
20
+ set(key: String, value: V): Unit {
21
+ self!->set(key, value!)
22
+ }
28
23
 
29
- clear(): Unit
30
- target js sync "self_.clear()"
24
+ has(key: String): Bool {
25
+ self!->has(key)?
26
+ }
31
27
 
32
- size(): Int
33
- target js sync "return self_.size"
28
+ remove(key: String): Bool {
29
+ self!->delete(key)?
30
+ }
34
31
 
35
- each(body: (String, V) => Unit): Unit
36
- target js sync "self_.forEach((v, k) => body_(k, v))"
37
- target js async "for(const [k, v] of self_) await body_(k, v)"
32
+ clear(): Unit {
33
+ self!->clear()
34
+ }
38
35
 
39
- eachWhile(body: (String, V) => Bool): Unit
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"
36
+ size(): Int {
37
+ self!->size?
38
+ }
39
+
40
+ isEmpty(): Bool {
41
+ self.size() == 0
42
+ }
42
43
 
44
+ each(body: (String, V) => Unit): Unit {
45
+ if(Js.inAsync()) {
46
+ let iterator = self!->entries()
47
+ mutable result = iterator->next()
48
+ while {!result->done?} {
49
+ let value = result->value
50
+ body(value.get(0)?, value.get(1)?)
51
+ result = iterator->next()
52
+ }
53
+ } else {
54
+ self!->forEach(Js->{v, k => body(k?, v?)})
55
+ }
56
+ }
57
+
58
+ eachWhile(body: (String, V) => Bool): Unit {
59
+ self!.eachWhile {value =>
60
+ body(value.get(0)?, value.get(1)?)
61
+ }
62
+ }
63
+
43
64
  toArray(): Array[Pair[String, V]] {
44
65
  let array = Array.new()
45
66
  self.each {k, v => array.push(Pair(k, v))}
@@ -61,17 +82,18 @@ extend self[V]: StringMap[V] {
61
82
  keys(): List[String] {
62
83
  let array = Array.new()
63
84
  self.each {k, v => array.push(k)}
64
- array.toList()
85
+ array.drain()
65
86
  }
66
87
 
67
88
  values(): List[V] {
68
89
  let array = Array.new()
69
90
  self.each {k, v => array.push(v)}
70
- array.toList()
91
+ array.drain()
71
92
  }
72
93
 
73
- copy(): StringMap[V]
74
- target js sync "return new Map(self_)"
94
+ copy(): StringMap[V] {
95
+ Js->Map->(self!)?
96
+ }
75
97
 
76
98
  getOrSet(key: String, body: () => V): V {
77
99
  if(!self.has(key)) {self.set(key, body())}
package/core/Task.ff CHANGED
@@ -1,149 +1,165 @@
1
- capability Task {}
2
-
3
- extend self: Task {
4
- // Spawns a task running body. The return value as well as the argument to body is the task handle.
5
- // Automatically aborts and then joins subtasks when body returns or throws an unhandled exception.
6
- // If body throws, the parent task is also aborted with the dueToSubtask flag set to true.
7
- spawn(body: Task => Unit): Task
8
- target js async """
9
- return ff_core_Task.Task_spawn(self_, body_)
10
- """
11
- target js sync """
12
- ff_core_Task.Task_throwIfAborted(self_)
13
- const task = {controller: new AbortController(), subtasks: new Set(), started: performance.now() * 0.001}
14
- self_.subtasks.add(task)
15
- task.promise = Promise.resolve(task).then(async () => {
16
- try {
17
- await body_(task, task)
18
- } catch(e) {
19
- await ff_core_Task.Task_abort$(self_)
20
- throw e
21
- } finally {
22
- for(const subtask of task.subtasks) subtask.controller.abort()
23
- await Promise.allSettled([...task.subtasks].map(subtask => subtask.promise))
24
- self_.subtasks.delete(task)
25
- }
26
- })
27
- return task
28
- """
29
-
30
- // If the aborted flag is set for the current task, clears it and throws TaskAbortedException.
31
- // You don't normally need to call this, but you might want to before doing an expensive computation.
32
- throwIfAborted(): Unit
33
- target js async """
34
- ff_core_Task.Task_throwIfAborted(self_)
35
- """
36
- target js sync """
37
- if(self_.controller.signal.aborted) {
38
- const signal = self_.controller.signal
39
- self_.controller = new AbortController()
40
- signal.throwIfAborted()
41
- }
42
- """
43
-
44
- // Sets the tasks aborted flag, which causes the ongoing/next async call to throw TaskAbortedException.
45
- abort(): Unit
46
- target js async """
47
- self_.controller.abort()
48
- """
49
- target js sync """
50
- self_.controller.abort()
51
- """
52
-
53
- // Create a blocking channel with the specified capacity. The channel is not tied to the task.
54
- channel[T](capacity: Int = 0): Channel[T]
55
- target js async """return ff_core_Task.Task_channel(capacity_)"""
56
- target js sync """return {capacity: capacity_, buffer: [], readers: new Set(), writers: new Set()}"""
57
-
58
- // Create a mutex. The mutex is not tied to the task.
59
- lock(): Lock
60
- target js async """return {owner: null, level: 0, stack: [], queue: []}"""
61
-
62
- now(): Instant
63
- target js sync "return Date.now() * 0.001"
64
- target js async "return Date.now() * 0.001" // TODO: Mark now() as sync and remove async version
65
-
66
- elapsed(): Duration
67
- target js sync "return performance.now() * 0.001 - self_.started"
68
- target js async "return performance.now() * 0.001 - self_.started" // TODO: Mark sync and remove async version
69
-
70
- time[R](body: () => R): Pair[R, Duration] {
71
- let start = self.elapsed()
72
- let result = body()
73
- let stop = self.elapsed()
74
- let duration = Duration(stop.seconds - start.seconds)
75
- Pair(result, duration)
76
- }
77
-
78
- }
79
-
80
- // Convenience methods
81
- extend self: Task {
82
-
83
- sleep(duration: Duration): Unit {
84
- Channel.
85
- readOr(self.channel()) {_ => }.
86
- timeout(duration) {}
87
- }
88
-
89
- mapList[T, R](list: List[T], body: T => R): List[R] {
90
- self.all(list.map {x => {body(x)}})
91
- }
92
-
93
- raceList[T, R](list: List[T], body: T => R): R {
94
- self.race(list.map {x => {body(x)}})
95
- }
96
-
97
- all[T](tasks: List[() => T]): List[T] {
98
- let successChannel = self.channel()
99
- let failureChannel = self.channel()
100
- self.spawn {t =>
101
- let channel = t.channel()
102
- try {
103
- tasks.pairs().each {| Pair(i, task) =>
104
- t.spawn {_ =>
105
- channel.write(Pair(i, task()))
106
- }
107
- }
108
- let result = tasks.map {_ =>
109
- channel.read()
110
- }.sortBy {_.first}.map {_.second}
111
- successChannel.write(result)
112
- } catchAny {error =>
113
- failureChannel.write(error)
114
- t.abort()
115
- }
116
- }
117
- Channel.
118
- readOr(successChannel, {_}).
119
- readOr(failureChannel, {_.rethrow()}).
120
- wait()
121
- }
122
-
123
- race[T](tasks: List[() => T]): T {
124
- let successChannel = self.channel()
125
- let failureChannel = self.channel()
126
- mutable live = tasks.size()
127
- let started = tasks.map {task =>
128
- self.spawn {_ =>
129
- try {
130
- successChannel.write(task())
131
- } catchAny {e =>
132
- live -= 1 // Not thread safe (but OK in JS)
133
- if(live == 0) {
134
- failureChannel.write(e)
135
- }
136
- }
137
- }
138
- }
139
- try {
140
- Channel.
141
- readOr(successChannel, {_}).
142
- readOr(failureChannel, {_.rethrow()}).
143
- wait()
144
- } finally {
145
- started.each {_.abort()}
146
- }
147
- }
148
-
149
- }
1
+ capability Task(
2
+ mutable controller: JsValue
3
+ subtasks: JsValue
4
+ mutable promise: JsValue
5
+ started: Duration
6
+ )
7
+
8
+ extend self: Task {
9
+
10
+ // Spawns a task running body. The return value as well as the argument to body is the task handle.
11
+ // Automatically aborts and then joins subtasks when body returns or throws an unhandled exception.
12
+ // If body throws, the parent task is also aborted with the dueToSubtask flag set to true.
13
+ spawn(body: Task => Unit): Task {
14
+ self.throwIfAborted()
15
+ let task = Task(
16
+ controller = Js->AbortController->()
17
+ subtasks = Js->Set->()
18
+ promise = Js.undefined()
19
+ started = Duration(Js->performance->now()? * 0.001)
20
+ )
21
+ self.subtasks->add(task!)
22
+ task.promise = Js->Promise->resolve(task!)->then(Js.async0 {
23
+ try {
24
+ Js.await(body!.callValue2(task!, task!))
25
+ } tryCatchAny {e =>
26
+ Js.await(self.controller->abort())
27
+ e.rethrow()
28
+ } finally {
29
+ task.subtasks.each {subtask =>
30
+ Js.fromValue[Task](subtask).controller->abort()
31
+ }
32
+ Js.await(Js->Promise->allSettled(
33
+ task.subtasks.spreadToArray().map {subtask =>
34
+ Js.fromValue[Task](subtask).promise
35
+ }
36
+ ))
37
+ self.subtasks->delete(task!)
38
+ }
39
+ })
40
+ task
41
+ }
42
+
43
+ // If the aborted flag is set for the current task, clears it and throws TaskAbortedException.
44
+ // You don't normally need to call this, but you might want to before doing an expensive computation.
45
+ throwIfAborted(): Unit {
46
+ let signal = self.controller->signal
47
+ if(signal->aborted?) {
48
+ self.controller = Js->AbortController->()
49
+ signal->throwIfAborted()
50
+ }
51
+ }
52
+
53
+ // Sets the tasks aborted flag, which causes the ongoing/next async call to throw TaskAbortedException.
54
+ abort(): Unit {
55
+ self.controller->abort()
56
+ }
57
+
58
+ // Create a blocking channel with the specified capacity. The channel is not tied to the task.
59
+ channel[T](capacity: Int = 0): Channel[T] {
60
+ Channel(
61
+ capacity = capacity
62
+ buffer = Array.new()
63
+ readers = Js->Set->()
64
+ writers = Js->Set->()
65
+ )
66
+ }
67
+
68
+ // Create a mutex. The mutex is not tied to the task.
69
+ lock(): Lock {
70
+ Lock(
71
+ owner = Js.undefined()
72
+ level = 0
73
+ queue = Queue.new()
74
+ )
75
+ }
76
+
77
+ now(): Instant {
78
+ Instant(Duration(Js->Date->now()? * 0.001))
79
+ }
80
+
81
+ elapsed(): Duration {
82
+ let now = Js->performance->now()? * 0.001
83
+ Duration(now - self.started.seconds)
84
+ }
85
+
86
+ time[R](body: () => R): Pair[R, Duration] {
87
+ let start = self.elapsed()
88
+ let result = body()
89
+ let stop = self.elapsed()
90
+ let duration = Duration(stop.seconds - start.seconds)
91
+ Pair(result, duration)
92
+ }
93
+
94
+ }
95
+
96
+ // Convenience methods
97
+ extend self: Task {
98
+
99
+ sleep(duration: Duration): Unit {
100
+ Channel.
101
+ readOr(self.channel()) {_ => }.
102
+ timeout(duration) {}
103
+ }
104
+
105
+ mapList[T, R](list: List[T], body: T => R): List[R] {
106
+ self.all(list.map {x => {body(x)}})
107
+ }
108
+
109
+ raceList[T, R](list: List[T], body: T => R): R {
110
+ self.race(list.map {x => {body(x)}})
111
+ }
112
+
113
+ all[T](tasks: List[() => T]): List[T] {
114
+ let successChannel = self.channel()
115
+ let failureChannel = self.channel()
116
+ self.spawn {t =>
117
+ let channel = t.channel()
118
+ try {
119
+ tasks.pairs().each {| Pair(i, task) =>
120
+ t.spawn {_ =>
121
+ channel.write(Pair(i, task()))
122
+ }
123
+ }
124
+ let result = tasks.map {_ =>
125
+ channel.read()
126
+ }.sortBy {_.first}.map {_.second}
127
+ successChannel.write(result)
128
+ } catchAny {error =>
129
+ failureChannel.write(error)
130
+ t.abort()
131
+ }
132
+ }
133
+ Channel.
134
+ readOr(successChannel, {_}).
135
+ readOr(failureChannel, {_.rethrow()}).
136
+ wait()
137
+ }
138
+
139
+ race[T](tasks: List[() => T]): T {
140
+ let successChannel = self.channel()
141
+ let failureChannel = self.channel()
142
+ mutable live = tasks.size()
143
+ let started = tasks.map {task =>
144
+ self.spawn {_ =>
145
+ try {
146
+ successChannel.write(task())
147
+ } catchAny {e =>
148
+ live -= 1 // Not thread safe (but OK in JS)
149
+ if(live == 0) {
150
+ failureChannel.write(e)
151
+ }
152
+ }
153
+ }
154
+ }
155
+ try {
156
+ Channel.
157
+ readOr(successChannel, {_}).
158
+ readOr(failureChannel, {_.rethrow()}).
159
+ wait()
160
+ } finally {
161
+ started.each {_.abort()}
162
+ }
163
+ }
164
+
165
+ }
@@ -1,23 +1,23 @@
1
- nodeMain(system: NodeSystem) {
2
- let list = 1.to(10000)
3
- benchmark(list, 100000)
4
- let time = system.mainTask().time {
5
- benchmark(list, 100000)
6
- }
7
- Log.trace(time.second.show())
8
- }
9
-
10
- benchmark(list: List[Int], iterations: Int): Int {
11
- mutable sum = 0
12
- mutable i = 0
13
- while {i < iterations} {
14
- mutable j = 0
15
- sum = 0
16
- while {j < 10000} {
17
- sum += list.grab(j)
18
- j += 1
19
- }
20
- i += 1
21
- }
22
- sum
23
- }
1
+ nodeMain(system: NodeSystem) {
2
+ let list = 1.to(10000)
3
+ benchmark(list, 100000)
4
+ let time = system.mainTask().time {
5
+ benchmark(list, 100000)
6
+ }
7
+ Log.trace(time.second.show())
8
+ }
9
+
10
+ benchmark(list: List[Int], iterations: Int): Int {
11
+ mutable sum = 0
12
+ mutable i = 0
13
+ while {i < iterations} {
14
+ mutable j = 0
15
+ sum = 0
16
+ while {j < 10000} {
17
+ sum += list.grab(j)
18
+ j += 1
19
+ }
20
+ i += 1
21
+ }
22
+ sum
23
+ }
@@ -1,55 +1,55 @@
1
- /*
2
-
3
- nodeMain(system: NodeSystem) {
4
- let list = 1.to(10000)
5
- benchmark(list, 10000)
6
- let time = system.mainTask().time {
7
- benchmark(list, 10000)
8
- }
9
- Log.trace(time.second.show())
10
- }
11
-
12
- benchmark(list: List[Int], iterations: Int): Int {
13
- mutable sum = 0
14
- mutable i = 0
15
- while {i < iterations} {
16
- mutable j = 0
17
- while {j < 10000} {
18
- sum += list.grab(j)
19
- j += 1
20
- }
21
- i += 1
22
- }
23
- sum
24
- }
25
-
26
- */
27
-
28
- // Rewrite the above to Java
29
-
30
- import java.util.ArrayList;
31
-
32
- public class ListGrab {
33
- public static void main(String[] args) {
34
- ArrayList<Integer> list = new ArrayList<>();
35
- for (int i = 1; i <= 10000; i++) {
36
- list.add(i);
37
- }
38
- benchmark(list, 100000);
39
- long time = System.currentTimeMillis();
40
- benchmark(list, 100000);
41
- time = System.currentTimeMillis() - time;
42
- System.out.println(time / 1000.0);
43
- }
44
-
45
- public static long benchmark(ArrayList<Integer> list, int iterations) {
46
- long sum = 0;
47
- for (int i = 0; i < iterations; i++) {
48
- sum = 0;
49
- for (int j = 0; j < 10000; j++) {
50
- sum += list.get(j);
51
- }
52
- }
53
- return sum;
54
- }
55
- }
1
+ /*
2
+
3
+ nodeMain(system: NodeSystem) {
4
+ let list = 1.to(10000)
5
+ benchmark(list, 10000)
6
+ let time = system.mainTask().time {
7
+ benchmark(list, 10000)
8
+ }
9
+ Log.trace(time.second.show())
10
+ }
11
+
12
+ benchmark(list: List[Int], iterations: Int): Int {
13
+ mutable sum = 0
14
+ mutable i = 0
15
+ while {i < iterations} {
16
+ mutable j = 0
17
+ while {j < 10000} {
18
+ sum += list.grab(j)
19
+ j += 1
20
+ }
21
+ i += 1
22
+ }
23
+ sum
24
+ }
25
+
26
+ */
27
+
28
+ // Rewrite the above to Java
29
+
30
+ import java.util.ArrayList;
31
+
32
+ public class ListGrab {
33
+ public static void main(String[] args) {
34
+ ArrayList<Integer> list = new ArrayList<>();
35
+ for (int i = 1; i <= 10000; i++) {
36
+ list.add(i);
37
+ }
38
+ benchmark(list, 100000);
39
+ long time = System.currentTimeMillis();
40
+ benchmark(list, 100000);
41
+ time = System.currentTimeMillis() - time;
42
+ System.out.println(time / 1000.0);
43
+ }
44
+
45
+ public static long benchmark(ArrayList<Integer> list, int iterations) {
46
+ long sum = 0;
47
+ for (int i = 0; i < iterations; i++) {
48
+ sum = 0;
49
+ for (int j = 0; j < 10000; j++) {
50
+ sum += list.get(j);
51
+ }
52
+ }
53
+ return sum;
54
+ }
55
+ }
@@ -1,30 +1,30 @@
1
- nodeMain(system: NodeSystem) {
2
- benchmark()
3
- let time = system.mainTask().time {
4
- benchmark()
5
- }
6
- Log.trace(time.second.show())
7
- }
8
-
9
- benchmark() {
10
- mutable num = 20000
11
- let v = num
12
- mutable i = 1
13
- mutable j = 1
14
- mutable sum = 0
15
- while {i < v} {
16
- j = 1
17
- while {j < num - 1} {
18
- if(num % j == 0) {
19
- sum += j
20
- }
21
- j += 1
22
- }
23
- if(num == sum) {
24
- Log.show(sum)
25
- }
26
- sum = 0
27
- num -= 1
28
- i += 1
29
- }
30
- }
1
+ nodeMain(system: NodeSystem) {
2
+ benchmark()
3
+ let time = system.mainTask().time {
4
+ benchmark()
5
+ }
6
+ Log.trace(time.second.show())
7
+ }
8
+
9
+ benchmark() {
10
+ mutable num = 20000
11
+ let v = num
12
+ mutable i = 1
13
+ mutable j = 1
14
+ mutable sum = 0
15
+ while {i < v} {
16
+ j = 1
17
+ while {j < num - 1} {
18
+ if(num % j == 0) {
19
+ sum += j
20
+ }
21
+ j += 1
22
+ }
23
+ if(num == sum) {
24
+ Log.show(sum)
25
+ }
26
+ sum = 0
27
+ num -= 1
28
+ i += 1
29
+ }
30
+ }