firefly-compiler 0.4.18 → 0.4.20

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 (116) hide show
  1. package/compiler/Builder.ff +1 -1
  2. package/compiler/Compiler.ff +6 -5
  3. package/compiler/Inference.ff +31 -19
  4. package/compiler/JsEmitter.ff +98 -71
  5. package/compiler/JsImporter.ff +1 -1
  6. package/compiler/LspHook.ff +17 -5
  7. package/compiler/Main.ff +6 -6
  8. package/compiler/Parser.ff +50 -52
  9. package/compiler/Patterns.ff +2 -0
  10. package/compiler/Syntax.ff +1 -1
  11. package/compiler/Tokenizer.ff +2 -2
  12. package/compiler/Workspace.ff +2 -2
  13. package/core/Array.ff +135 -294
  14. package/core/Buffer.ff +3 -3
  15. package/core/BuildSystem.ff +1 -1
  16. package/core/Equal.ff +36 -52
  17. package/core/HttpClient.ff +1 -1
  18. package/core/IntMap.ff +14 -18
  19. package/core/JsSystem.ff +1 -1
  20. package/core/JsValue.ff +6 -12
  21. package/core/Json.ff +21 -30
  22. package/core/List.ff +281 -312
  23. package/core/Map.ff +4 -8
  24. package/core/NodeSystem.ff +2 -2
  25. package/core/Option.ff +0 -4
  26. package/core/Ordering.ff +10 -6
  27. package/core/Pair.ff +0 -4
  28. package/core/Random.ff +12 -26
  29. package/core/RbMap.ff +216 -216
  30. package/core/Serializable.ff +9 -18
  31. package/core/Set.ff +0 -1
  32. package/core/SourceLocation.ff +1 -1
  33. package/core/Stream.ff +10 -14
  34. package/core/String.ff +24 -6
  35. package/core/StringMap.ff +15 -19
  36. package/guide/Main.ff +20 -2
  37. package/lsp/CompletionHandler.ff +18 -18
  38. package/lsp/Handler.ff +45 -34
  39. package/lsp/HoverHandler.ff +2 -2
  40. package/lsp/LanguageServer.ff +2 -2
  41. package/lsp/SignatureHelpHandler.ff +1 -1
  42. package/lsp/SymbolHandler.ff +19 -5
  43. package/lux/Lux.ff +3 -3
  44. package/output/js/ff/compiler/Builder.mjs +19 -21
  45. package/output/js/ff/compiler/Compiler.mjs +18 -20
  46. package/output/js/ff/compiler/Dependencies.mjs +8 -10
  47. package/output/js/ff/compiler/Deriver.mjs +234 -236
  48. package/output/js/ff/compiler/Dictionaries.mjs +6 -8
  49. package/output/js/ff/compiler/Environment.mjs +42 -44
  50. package/output/js/ff/compiler/Inference.mjs +346 -304
  51. package/output/js/ff/compiler/JsEmitter.mjs +907 -833
  52. package/output/js/ff/compiler/JsImporter.mjs +0 -2
  53. package/output/js/ff/compiler/LspHook.mjs +872 -51
  54. package/output/js/ff/compiler/Main.mjs +109 -111
  55. package/output/js/ff/compiler/Parser.mjs +427 -441
  56. package/output/js/ff/compiler/Patterns.mjs +64 -50
  57. package/output/js/ff/compiler/Resolver.mjs +36 -38
  58. package/output/js/ff/compiler/Substitution.mjs +4 -6
  59. package/output/js/ff/compiler/Syntax.mjs +160 -162
  60. package/output/js/ff/compiler/Token.mjs +52 -54
  61. package/output/js/ff/compiler/Tokenizer.mjs +16 -18
  62. package/output/js/ff/compiler/Unification.mjs +24 -26
  63. package/output/js/ff/compiler/Wildcards.mjs +0 -2
  64. package/output/js/ff/compiler/Workspace.mjs +18 -20
  65. package/output/js/ff/core/Any.mjs +0 -2
  66. package/output/js/ff/core/Array.mjs +216 -613
  67. package/output/js/ff/core/AssetSystem.mjs +2 -4
  68. package/output/js/ff/core/Atomic.mjs +0 -2
  69. package/output/js/ff/core/Bool.mjs +0 -2
  70. package/output/js/ff/core/Box.mjs +0 -2
  71. package/output/js/ff/core/BrowserSystem.mjs +0 -2
  72. package/output/js/ff/core/Buffer.mjs +0 -2
  73. package/output/js/ff/core/BuildSystem.mjs +12 -14
  74. package/output/js/ff/core/Channel.mjs +0 -2
  75. package/output/js/ff/core/Char.mjs +0 -2
  76. package/output/js/ff/core/Core.mjs +0 -2
  77. package/output/js/ff/core/Duration.mjs +0 -2
  78. package/output/js/ff/core/Equal.mjs +0 -22
  79. package/output/js/ff/core/Error.mjs +0 -2
  80. package/output/js/ff/core/FileHandle.mjs +0 -2
  81. package/output/js/ff/core/Float.mjs +0 -2
  82. package/output/js/ff/core/HttpClient.mjs +2 -4
  83. package/output/js/ff/core/Instant.mjs +0 -2
  84. package/output/js/ff/core/Int.mjs +8 -10
  85. package/output/js/ff/core/IntMap.mjs +32 -42
  86. package/output/js/ff/core/JsSystem.mjs +1 -3
  87. package/output/js/ff/core/JsValue.mjs +5 -12
  88. package/output/js/ff/core/Json.mjs +25 -58
  89. package/output/js/ff/core/List.mjs +648 -1989
  90. package/output/js/ff/core/Lock.mjs +0 -2
  91. package/output/js/ff/core/Log.mjs +0 -2
  92. package/output/js/ff/core/Map.mjs +10 -20
  93. package/output/js/ff/core/NodeSystem.mjs +6 -8
  94. package/output/js/ff/core/Nothing.mjs +0 -2
  95. package/output/js/ff/core/Option.mjs +8 -18
  96. package/output/js/ff/core/Ordering.mjs +20 -98
  97. package/output/js/ff/core/Pair.mjs +6 -16
  98. package/output/js/ff/core/Path.mjs +12 -14
  99. package/output/js/ff/core/Random.mjs +24 -54
  100. package/output/js/ff/core/RbMap.mjs +54 -56
  101. package/output/js/ff/core/Serializable.mjs +19 -36
  102. package/output/js/ff/core/Set.mjs +0 -14
  103. package/output/js/ff/core/Show.mjs +0 -2
  104. package/output/js/ff/core/SourceLocation.mjs +0 -2
  105. package/output/js/ff/core/Stream.mjs +34 -44
  106. package/output/js/ff/core/String.mjs +31 -5
  107. package/output/js/ff/core/StringMap.mjs +32 -42
  108. package/output/js/ff/core/Task.mjs +0 -2
  109. package/output/js/ff/core/Try.mjs +0 -2
  110. package/output/js/ff/core/Unit.mjs +0 -2
  111. package/package.json +1 -1
  112. package/vscode/client/src/extension.ts +30 -2
  113. package/vscode/package.json +17 -1
  114. package/webserver/WebServer.ff +8 -8
  115. package/core/Stack.ff +0 -263
  116. package/output/js/ff/core/Stack.mjs +0 -603
package/core/List.ff CHANGED
@@ -1,108 +1,77 @@
1
- data List[T] {
2
- Empty
3
- Link(head: T, tail: List[T])
4
- }
1
+ data List[T] {}
5
2
 
6
- range(size: Int): List[Int]
3
+ empty[T](): List[T]
7
4
  target js sync """
8
- let result = ff_core_List.Empty();
9
- for(let i = size_ - 1; i >= 0; i--) {
10
- result = ff_core_List.Link(i, result);
11
- }
12
- return result;
5
+ return [];
6
+ """
7
+
8
+ fill[T](size: Int, value: T): List[T]
9
+ target js sync """
10
+ return new Array(size_).fill(value_);
13
11
  """
14
12
 
15
- build[A, B](initial: A, body: A => Option[Pair[A, B]]): List[B] {
16
- function go(state: A, result: List[B]): List[B] {
17
- body(state).{
18
- | None => result.reverse()
19
- | Some(Pair(s, x)) => tailcall go(s, [x, ...result])
13
+ fillBy[T](size: Int, body: Int => T): List[T]
14
+ target js sync """
15
+ return Array.from({length: size_}, (_, i) => body_(i));
16
+ """
17
+ target js async """
18
+ const array = new Array(size_);
19
+ for(let i = 0; i < size_; i++) {
20
+ array[i] = await(body_(_i));
20
21
  }
21
- }
22
- go(initial, [])
23
- }
22
+ return array;
23
+ """
24
+
25
+ range(size: Int): List[Int]
26
+ target js sync """
27
+ return Array.from({length: size_}, (_, i) => i);
28
+ """
24
29
 
25
30
  extend self[T]: List[T] {
26
31
 
27
- addAll(list: List[T]): List[T] {
28
- [self, list].flatten()
29
- }
32
+ addAll(that: List[T]): List[T]
33
+ target js sync "return self_.concat(that_)"
34
+
35
+ isEmpty(): Bool
36
+ target js sync "return self_.length === 0"
30
37
 
31
- toStack(): Stack[T]
38
+ size(): Int
39
+ target js sync "return self_.length"
40
+
41
+ get(index: Int): Option[T]
32
42
  target js sync """
33
- let current = self_;
34
- let result = [];
35
- while(current.Link) {
36
- result.push(current.head_);
37
- current = current.tail_;
38
- }
39
- return {array: result};
43
+ return index_ >= 0 && index_ < self_.length
44
+ ? ff_core_Option.Some(self_[index_])
45
+ : ff_core_Option.None()
40
46
  """
41
47
 
42
- toArray(): Array[T] {
43
- self.toStack().drain()
44
- }
45
-
46
- grab(index: Int): T {
47
- function go(list: List[T], i: Int): T {
48
- list.{
49
- | [] => Try.internalThrowGrabException()
50
- | [head, ...] {i == 0} => head
51
- | [_, ...tail] => tailcall go(tail, i - 1)
48
+ grab(index: Int): T
49
+ target js sync """
50
+ if(index_ < 0 || index_ >= self_.length) {
51
+ ff_core_Try.internalThrowGrabException_()
52
52
  }
53
- }
54
- go(self, index)
55
- }
53
+ return self_[index_]
54
+ """
56
55
 
57
- first(): Option[T] {
58
- self.{
59
- | [] => None
60
- | [head, ...] => Some(head)
61
- }
62
- }
56
+ first(): Option[T] {self.get(0)}
63
57
 
64
- last(): Option[T] {
65
- self.{
66
- | [] => None
67
- | [head] => Some(head)
68
- | [_, ...tail] => tailcall tail.last()
69
- }
70
- }
58
+ last(): Option[T] {self.get(self.size() - 1)}
71
59
 
72
- grabFirst(): T {
73
- self.first().else {Try.internalThrowGrabException()}
74
- }
60
+ grabFirst(): T {self.grab(0)}
75
61
 
76
- grabLast(): T {
77
- self.last().else {Try.internalThrowGrabException()}
78
- }
62
+ grabLast(): T {self.grab(self.size() - 1)}
79
63
 
80
- dropFirst(count: Int = 1): List[T] {
81
- self.{
82
- | _ {count <= 0} => self
83
- | [] => self
84
- | [_, ...tail] => tailcall tail.dropFirst(count - 1)
85
- }
86
- }
64
+ takeFirst(count: Int = 1): List[T]
65
+ target js sync "return self_.slice(0, count_)"
87
66
 
88
- dropLast(count: Int = 1): List[T] {
89
- self.reverse().dropFirst(count).reverse()
90
- }
67
+ takeLast(count: Int = 1): List[T]
68
+ target js sync "return self_.slice(-count_)"
91
69
 
92
- takeFirst(count: Int = 1): List[T] {
93
- function go(list: List[T], count: Int, result: List[T]): List[T] {
94
- list.{
95
- | _ {count <= 0} => result.reverse()
96
- | [] => result.reverse()
97
- | [head, ...tail] => tailcall go(tail, count - 1, [head, ...result])
98
- }
99
- }
100
- go(self, count, [])
101
- }
70
+ dropFirst(count: Int = 1): List[T]
71
+ target js sync "return self_.slice(count_)"
102
72
 
103
- takeLast(count: Int = 1): List[T] {
104
- self.reverse().takeFirst(count).reverse()
105
- }
73
+ dropLast(count: Int = 1): List[T]
74
+ target js sync "return self_.slice(0, self_.length - count_)"
106
75
 
107
76
  pairs(): List[Pair[Int, T]] {
108
77
  mutable i = 0
@@ -112,244 +81,220 @@ extend self[T]: List[T] {
112
81
  r
113
82
  }
114
83
  }
115
-
84
+
116
85
  slice(from: Int, until: Int): List[T] {
117
86
  self.dropFirst(from).takeFirst(until - from)
118
87
  }
88
+
89
+ foldLeft[R](initial: R, body: (R, T) => R): R {
90
+ mutable result = initial
91
+ self.each {x =>
92
+ result = body(result, x)
93
+ }
94
+ result
95
+ }
119
96
 
120
- isEmpty(): Bool {
121
- self.{
122
- | [] => True
123
- | _ => False
97
+ update(index: Int, value: T): List[T] {
98
+ self.modify(index) {_ => value}
99
+ }
100
+
101
+ modify(index: Int, body: T => T): List[T]
102
+ target js sync """
103
+ if(index_ < 0 || index_ >= self_.length) {
104
+ ff_core_Try.internalThrowGrabException_()
105
+ }
106
+ let result = self_.slice();
107
+ result[index_] = body_(result[index_]);
108
+ return result;
109
+ """
110
+ target js async """
111
+ if(index_ < 0 || index_ >= self_.length) {
112
+ ff_core_Try.internalThrowGrabException_()
113
+ }
114
+ let result = self_.slice();
115
+ result[index_] = await body_(result[index_], $task);
116
+ return result;
117
+ """
118
+
119
+ zip[S](that: List[S]): List[Pair[T, S]] {
120
+ if(self.size() <= that.size()) {
121
+ mutable i = -1
122
+ self.map {x =>
123
+ i += 1
124
+ Pair(x, that.grab(i))
125
+ }
126
+ } else {
127
+ mutable i = -1
128
+ that.map {y =>
129
+ i += 1
130
+ Pair(self.grab(i), y)
131
+ }
124
132
  }
125
133
  }
126
134
 
127
- size(): Int {
128
- function go(list: List[T], result: Int): Int {
129
- list.{
130
- | [] => result
131
- | [_, ...tail] => tailcall go(tail, result + 1)
135
+ chunk(chunkSize: Int): List[List[T]] {
136
+ let results = Array.make()
137
+ let result = Array.make()
138
+ mutable added = 0
139
+ self.each {item =>
140
+ if(added < chunkSize) {
141
+ added += 1
142
+ } else {
143
+ results.push(result.drain())
144
+ added = 1
132
145
  }
146
+ result.push(item)
147
+ }
148
+ if(added != 0) {
149
+ results.push(result.drain())
133
150
  }
134
- go(self, 0)
151
+ results.drain()
135
152
  }
136
153
 
137
- each(body: T => Unit): Unit {
138
- self.{
139
- | [] =>
140
- | [head, ...tail] =>
141
- body(head)
142
- tailcall tail.each(body)
154
+ toStream(cycle: Bool = False): Stream[T] {
155
+ mutable index = 0
156
+ Stream.make {
157
+ if(index < self.size()) {
158
+ let result = self.grab(index)
159
+ index += 1
160
+ result
161
+ } elseIf {cycle && index != 0} {
162
+ let result = self.grab(0)
163
+ index = 1
164
+ result
165
+ }
143
166
  }
144
167
  }
145
-
146
- eachWhile(body: T => Bool): Bool {
147
- self.all(body)
148
- }
168
+
169
+ toArray(): Array[T]
170
+ target js sync "return {array: self_.slice()}"
171
+
172
+ each(body: T => Unit): Unit
173
+ target js sync """
174
+ return self_.forEach(body_);
175
+ """
176
+ target js async """
177
+ for(let i = 0; i < self_.length; i++) {
178
+ await body_(self_[i], $task)
179
+ }
180
+ """
181
+
182
+ eachWhile(body: T => Bool): Unit
183
+ target js sync "for(const value of self_) if(!body_(value)) break"
184
+ target js async "for(const value of self_) if(!await body_(value, $task)) break"
149
185
 
150
186
  all(body: T => Bool): Bool {
151
- self.{
152
- | [] => True
153
- | [head, ...] {!body(head)} => False
154
- | [_, ...tail] => tailcall tail.all(body)
187
+ mutable result = True
188
+ self.eachWhile {x =>
189
+ result = result && body(x)
190
+ result
155
191
  }
192
+ result
156
193
  }
157
194
 
158
195
  any(body: T => Bool): Bool {
159
- self.{
160
- | [] => False
161
- | [head, ...] {body(head)} => True
162
- | [_, ...tail] => tailcall tail.any(body)
196
+ mutable result = False
197
+ self.eachWhile {x =>
198
+ result = result || body(x)
199
+ (!result)
163
200
  }
201
+ result
164
202
  }
165
-
203
+
166
204
  find(body: T => Bool): Option[T] {
167
- self.{
168
- | [] => None
169
- | [head, ...] {body(head)} => Some(head)
170
- | [_, ...tail] => tailcall tail.find(body)
205
+ mutable result = None
206
+ self.eachWhile {x =>
207
+ if(body(x)) {
208
+ result = Some(x)
209
+ False
210
+ } else {
211
+ True
212
+ }
171
213
  }
214
+ result
172
215
  }
173
216
 
174
217
  filter(body: T => Bool): List[T] {
175
- function go(list: List[T], result: List[T]): List[T] {
176
- list.{
177
- | [] =>
178
- result.reverse()
179
- | [head, ...tail] {body(head)} =>
180
- tailcall go(tail, [head, ...result])
181
- | [_, ...tail] =>
182
- tailcall go(tail, result)
218
+ let result = Array.make()
219
+ self.each {x =>
220
+ if(body(x)) {
221
+ result.push(x)
183
222
  }
184
223
  }
185
- go(self, [])
224
+ result.drain()
186
225
  }
187
-
226
+
188
227
  partition(body: T => Bool): Pair[List[T], List[T]] {
189
228
  Pair(self.filter(body), self.filter {!body(_)})
190
229
  }
191
230
 
192
- map[R](body: T => R): List[R] {
193
- function go(list: List[T], result: List[R]): List[R] {
194
- list.{
195
- | [] =>
196
- result.reverse()
197
- | [head, ...tail] =>
198
- tailcall go(tail, [body(head), ...result])
199
- }
200
- }
201
- go(self, [])
202
- }
203
-
204
- flatMap[R](body: T => List[R]): List[R] {
205
- function go(list: List[T], result: List[List[R]]): List[R] {
206
- list.{
207
- | [] =>
208
- result.reverse().flatten()
209
- | [head, ...tail] =>
210
- tailcall go(tail, [body(head), ...result])
231
+ map[S](body: T => S): List[S]
232
+ target js sync """
233
+ return self_.map(body_)
234
+ """
235
+ target js async """
236
+ let result = [];
237
+ for(let i = 0; i < self_.length; i++) {
238
+ result.push(await body_(self_[i], $task));
211
239
  }
240
+ return result;
241
+ """
242
+
243
+ flatMap[S](body: T => List[S]): List[S] {
244
+ let results = Array.make()
245
+ self.each {x =>
246
+ results.pushList(body(x))
212
247
  }
213
- go(self, [])
248
+ results.drain()
214
249
  }
215
-
250
+
216
251
  collect[R](body: T => Option[R]): List[R] {
217
- self.toStream().collect(body).toList()
218
- }
219
-
220
- collectFirst[R](body: T => Option[R]): Option[R] {
221
- self.{
222
- | [] =>
223
- None
224
- | [head, ...tail] =>
225
- body(head).{
226
- | None => tailcall tail.collectFirst(body)
227
- | Some(value) => Some(value)
228
- }
229
- }
230
- }
231
-
232
- foldLeft[R](initial: R, body: (R, T) => R): R {
233
- function go(state: R, list: List[T]): R {
234
- list.{
235
- | [] =>
236
- state
237
- | [head, ...tail] =>
238
- tailcall go(body(state, head), tail)
239
- }
240
- }
241
- go(initial, self)
242
- }
243
-
244
- update(index: Int, value: T): List[T] {
245
- function go(list: List[T], i: Int, result: List[T]): List[T] {
246
- list.{
247
- | [] =>
248
- result.reverse()
249
- | [head, ...tail] {i == 0} =>
250
- tailcall go(tail, i - 1, [value, ...result])
251
- | [head, ...tail] =>
252
- tailcall go(tail, i - 1, [head, ...result])
253
- }
252
+ mutable result = Array.make()
253
+ self.each {x =>
254
+ body(x).each {result.push(_)}
254
255
  }
255
- go(self, index, [])
256
+ result.drain()
256
257
  }
257
258
 
258
- modify(index: Int, body: T => T): List[T] {
259
- function go(list: List[T], i: Int, result: List[T]): List[T] {
260
- list.{
261
- | [] =>
262
- result.reverse()
263
- | [head, ...tail] {i == 0} =>
264
- tailcall go(tail, i - 1, [body(head), ...result])
265
- | [head, ...tail] =>
266
- tailcall go(tail, i - 1, [head, ...result])
267
- }
268
- }
269
- go(self, index, [])
270
- }
271
-
272
- zip[S](that: List[S]): List[Pair[T, S]] {
273
- function go(list1: List[T], list2: List[S], result: List[Pair[T, S]]): List[Pair[T, S]] {
274
- Pair(list1, list2).{
275
- | Pair([x, ...xs], [y, ...ys]) =>
276
- tailcall go(xs, ys, [Pair(x, y), ...result])
277
- | _ =>
278
- result.reverse()
259
+ collectFirst[R](body: T => Option[R]): Option[R] {
260
+ mutable result = None
261
+ self.eachWhile {x =>
262
+ body(x).{
263
+ | None =>
264
+ True
265
+ | o =>
266
+ result = o
267
+ False
279
268
  }
280
269
  }
281
- go(self, that, [])
270
+ result
282
271
  }
283
272
 
284
- sortBy[O: Order](body: T => O): List[T] {
285
- if(self.size() <= 1) {self} else:
286
- let stack = self.toStack()
287
- stack.sortBy(body)
288
- stack.toList()
273
+ sortBy[S: Order](body: T => S): List[T] {
274
+ self.sortWith {Ordering.compare(body(_), body(_))}
289
275
  }
290
276
 
291
- sortWith(compare: (T, T) => Ordering): List[T] {
292
- if(self.size() <= 1) {self} else:
293
- let stack = self.toStack()
294
- stack.sortWith(compare)
295
- stack.toList()
277
+ sortWith(ordering: (T, T) => Ordering): List[T] {
278
+ let array = self.toArray()
279
+ array.sortWith(ordering)
280
+ array.drain()
296
281
  }
297
-
282
+
298
283
  reverse(): List[T] {
299
- function go(list: List[T], result: List[T]): List[T] {
300
- list.{
301
- | [] =>
302
- result
303
- | [head, ...tail] =>
304
- tailcall go(tail, [head, ...result])
305
- }
284
+ 1.to(self.size()).map {i =>
285
+ self.grab(self.size() - i)
306
286
  }
307
- go(self, [])
308
287
  }
309
-
310
- chunk(chunkSize: Int): List[List[T]] {
311
- mutable results = []
312
- mutable result = []
313
- mutable added = 0
314
- self.each {item =>
315
- if(added < chunkSize) {
316
- result = [item, ...result]
317
- added += 1
318
- } else {
319
- results = [result.reverse(), ...results]
320
- result = [item]
321
- added = 1
288
+
289
+ separate(separator: List[T]): List[T] {
290
+ let array = Array.make()
291
+ self.pairs().each {| Pair(i, x) =>
292
+ if(i != 0) {
293
+ array.pushList(separator)
322
294
  }
295
+ array.push(x)
323
296
  }
324
- if(added != 0) {
325
- results = [result.reverse(), ...results]
326
- }
327
- results.reverse()
328
- }
329
-
330
- toStream(cycle: Bool = False): Stream[T] {
331
- mutable remaining = self
332
- Stream(
333
- next = {
334
- remaining.{
335
- | [head, ...tail] =>
336
- remaining = tail
337
- Some(head)
338
- | [] {self | [head, ...tail]} {cycle} =>
339
- remaining = tail
340
- Some(head)
341
- | [] =>
342
- None
343
- }
344
- }
345
- close = {
346
- remaining = []
347
- }
348
- )
349
- }
350
-
351
- separate(separator: List[T]): List[T] {
352
- self.flatMap {e => [...separator, e]}.dropFirst(separator.size())
297
+ array.drain()
353
298
  }
354
299
 
355
300
  }
@@ -357,16 +302,13 @@ extend self[T]: List[T] {
357
302
  extend self[T: Order]: List[T] {
358
303
 
359
304
  sort(): List[T] {
360
- if(self.size() <= 1) {self} else:
361
- let stack = self.toStack()
362
- stack.sort()
363
- stack.toList()
305
+ self.sortWith(Ordering.compare)
364
306
  }
365
-
307
+
366
308
  toSet(): Set[T] {
367
- self.foldLeft(Set.empty[T]()) {set, value => set.add(value)}
309
+ self.foldLeft(Set.empty()) {_.add(_)}
368
310
  }
369
-
311
+
370
312
  distinct(): List[T] {
371
313
  mutable seen = [].toSet()
372
314
  self.filter {
@@ -380,65 +322,92 @@ extend self[T: Order]: List[T] {
380
322
 
381
323
  }
382
324
 
383
- extend self[T: Show]: List[T] {
384
-
385
- show(): String {
386
- Show.show(self)
387
- }
388
-
389
- }
390
-
391
325
  extend self[T]: List[List[T]] {
392
326
 
393
327
  flatten(): List[T] {
394
- function finish(list: List[T], result: List[T]): List[T] {
395
- | as, [] => as
396
- | as, [x, ...xs] => tailcall finish([x, ...as], xs)
397
- }
398
- function go(lists: List[List[T]], result: List[T]): List[T] {
399
- lists.{
400
- | [] => []
401
- | [as] => finish(as, result)
402
- | [[], ...aas] => tailcall go(aas, result)
403
- | [[a, ...as], ...aas] => tailcall go([as, ...aas], [a, ...result])
404
- }
328
+ let result = Array.make()
329
+ self.each {xs =>
330
+ result.pushList(xs)
405
331
  }
406
- go(self, [])
332
+ result.drain()
407
333
  }
408
334
 
409
335
  }
410
336
 
411
337
  extend self[K: Order, V]: List[Pair[K, V]] {
412
-
338
+
413
339
  toMap(): Map[K, V] {
414
- self.foldLeft(Map.empty[K, V]()) {map, pair => map.add(pair.first, pair.second)}
340
+ self.foldLeft(Map.empty()) {| map, Pair(key, value) => map.add(key, value)}
415
341
  }
416
-
342
+
417
343
  group(): Map[K, List[V]] {
418
- let initial: List[Pair[K, List[V]]] = []
419
- self.foldLeft(initial.toMap()) {map, pair => map.addToList(pair.first, pair.second)}
344
+ mutable map = Map.empty[K, Array[V]]()
345
+ self.each {| Pair(k, v) => map = map.push(k, v)}
346
+ map.mapValues {_, v => v.drain()}
420
347
  }
421
-
348
+
422
349
  }
423
350
 
424
351
  extend self[K, V]: List[Pair[K, V]] {
425
352
 
426
353
  unzip(): Pair[List[K], List[V]] {
427
- function go(pairs: List[Pair[K, V]], ks: List[K], vs: List[V]): Pair[List[K], List[V]] {
428
- pairs.{
429
- | [] =>
430
- Pair(ks.reverse(), vs.reverse())
431
- | [Pair(k, v), ...tail] =>
432
- tailcall go(tail, [k, ...ks], [v, ...vs])
433
- }
354
+ let first = Array.make()
355
+ let second = Array.make()
356
+ self.each {| Pair(x, y) =>
357
+ first.push(x)
358
+ second.push(y)
434
359
  }
435
- go(self, [], [])
360
+ Pair(first.drain(), second.drain())
436
361
  }
437
362
 
438
363
  }
439
364
 
440
365
  extend self: List[String] {
441
366
 
442
- join(separator: String = ""): String {self.toArray().join(separator)}
367
+ join(separator: String = ""): String
368
+ target js sync "return self_.join(separator_)"
443
369
 
444
370
  }
371
+
372
+ instance List[T: Show]: Show {
373
+ show(value: List[T]): String {
374
+ let array = Array.make()
375
+ array.push("[")
376
+ value.each {x =>
377
+ if(array.size() > 1) {array.push(", ")}
378
+ array.push(Show.show(x))
379
+ }
380
+ array.push("]")
381
+ array.join()
382
+ }
383
+ }
384
+
385
+ instance List[T: Equal]: Equal {
386
+ equals(x: List[T], y: List[T]): Bool {
387
+ if(internalSame(x, y)) {True} else:
388
+ if(x.size() != y.size()) {False} else:
389
+ mutable i = -1
390
+ x.all {l =>
391
+ i += 1
392
+ l == y.grab(i)
393
+ }
394
+ }
395
+ }
396
+
397
+ instance List[T: Order]: Order {
398
+ compare(x: List[T], y: List[T]): Ordering {
399
+ if(internalSame(x, y)) {OrderingSame} else:
400
+ let size = x.size().min(y.size())
401
+ mutable i = 0
402
+ mutable ordering = OrderingSame
403
+ while {ordering == OrderingSame && i < size} {
404
+ ordering = Ordering.compare(x.grab(i), y.grab(i))
405
+ i += 1
406
+ }
407
+ if(ordering != OrderingSame) {ordering} else:
408
+ Ordering.compare(x.size(), y.size())
409
+ }
410
+ }
411
+
412
+ internalSame[T](left: List[T], right: List[T]): Bool
413
+ target js sync "return left_ === right_"