firefly-compiler 0.4.18 → 0.4.19
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.
- package/compiler/Builder.ff +1 -1
- package/compiler/Compiler.ff +6 -5
- package/compiler/Inference.ff +31 -19
- package/compiler/JsEmitter.ff +98 -71
- package/compiler/JsImporter.ff +1 -1
- package/compiler/LspHook.ff +4 -4
- package/compiler/Main.ff +6 -6
- package/compiler/Parser.ff +39 -39
- package/compiler/Patterns.ff +2 -0
- package/compiler/Syntax.ff +1 -1
- package/compiler/Tokenizer.ff +2 -2
- package/compiler/Workspace.ff +2 -2
- package/core/Array.ff +135 -294
- package/core/Buffer.ff +3 -3
- package/core/BuildSystem.ff +1 -1
- package/core/Equal.ff +36 -52
- package/core/HttpClient.ff +1 -1
- package/core/IntMap.ff +14 -18
- package/core/JsSystem.ff +1 -1
- package/core/JsValue.ff +6 -12
- package/core/Json.ff +19 -28
- package/core/List.ff +281 -312
- package/core/Map.ff +4 -8
- package/core/NodeSystem.ff +2 -2
- package/core/Option.ff +0 -4
- package/core/Ordering.ff +10 -6
- package/core/Pair.ff +0 -4
- package/core/Random.ff +12 -26
- package/core/RbMap.ff +216 -216
- package/core/Serializable.ff +9 -18
- package/core/Set.ff +0 -1
- package/core/SourceLocation.ff +1 -1
- package/core/Stack.ff +32 -45
- package/core/Stream.ff +10 -14
- package/core/String.ff +24 -6
- package/core/StringMap.ff +15 -19
- package/guide/Main.ff +20 -2
- package/lsp/CompletionHandler.ff +4 -4
- package/lsp/Handler.ff +44 -33
- package/lsp/HoverHandler.ff +2 -2
- package/lsp/LanguageServer.ff +2 -2
- package/lsp/SignatureHelpHandler.ff +1 -1
- package/lsp/SymbolHandler.ff +1 -1
- package/lux/Lux.ff +3 -3
- package/output/js/ff/compiler/Builder.mjs +19 -21
- package/output/js/ff/compiler/Compiler.mjs +18 -20
- package/output/js/ff/compiler/Dependencies.mjs +8 -10
- package/output/js/ff/compiler/Deriver.mjs +234 -236
- package/output/js/ff/compiler/Dictionaries.mjs +6 -8
- package/output/js/ff/compiler/Environment.mjs +42 -44
- package/output/js/ff/compiler/Inference.mjs +346 -304
- package/output/js/ff/compiler/JsEmitter.mjs +907 -833
- package/output/js/ff/compiler/JsImporter.mjs +0 -2
- package/output/js/ff/compiler/LspHook.mjs +10 -12
- package/output/js/ff/compiler/Main.mjs +109 -111
- package/output/js/ff/compiler/Parser.mjs +405 -407
- package/output/js/ff/compiler/Patterns.mjs +64 -50
- package/output/js/ff/compiler/Resolver.mjs +36 -38
- package/output/js/ff/compiler/Substitution.mjs +4 -6
- package/output/js/ff/compiler/Syntax.mjs +160 -162
- package/output/js/ff/compiler/Token.mjs +52 -54
- package/output/js/ff/compiler/Tokenizer.mjs +16 -18
- package/output/js/ff/compiler/Unification.mjs +24 -26
- package/output/js/ff/compiler/Wildcards.mjs +0 -2
- package/output/js/ff/compiler/Workspace.mjs +18 -20
- package/output/js/ff/core/Any.mjs +0 -2
- package/output/js/ff/core/Array.mjs +216 -613
- package/output/js/ff/core/AssetSystem.mjs +2 -4
- package/output/js/ff/core/Atomic.mjs +0 -2
- package/output/js/ff/core/Bool.mjs +0 -2
- package/output/js/ff/core/Box.mjs +0 -2
- package/output/js/ff/core/BrowserSystem.mjs +0 -2
- package/output/js/ff/core/Buffer.mjs +0 -2
- package/output/js/ff/core/BuildSystem.mjs +12 -14
- package/output/js/ff/core/Channel.mjs +0 -2
- package/output/js/ff/core/Char.mjs +0 -2
- package/output/js/ff/core/Core.mjs +0 -2
- package/output/js/ff/core/Duration.mjs +0 -2
- package/output/js/ff/core/Equal.mjs +0 -22
- package/output/js/ff/core/Error.mjs +0 -2
- package/output/js/ff/core/FileHandle.mjs +0 -2
- package/output/js/ff/core/Float.mjs +0 -2
- package/output/js/ff/core/HttpClient.mjs +2 -4
- package/output/js/ff/core/Instant.mjs +0 -2
- package/output/js/ff/core/Int.mjs +8 -10
- package/output/js/ff/core/IntMap.mjs +32 -42
- package/output/js/ff/core/JsSystem.mjs +1 -3
- package/output/js/ff/core/JsValue.mjs +5 -12
- package/output/js/ff/core/Json.mjs +23 -56
- package/output/js/ff/core/List.mjs +648 -1989
- package/output/js/ff/core/Lock.mjs +0 -2
- package/output/js/ff/core/Log.mjs +0 -2
- package/output/js/ff/core/Map.mjs +10 -20
- package/output/js/ff/core/NodeSystem.mjs +6 -8
- package/output/js/ff/core/Nothing.mjs +0 -2
- package/output/js/ff/core/Option.mjs +8 -18
- package/output/js/ff/core/Ordering.mjs +20 -98
- package/output/js/ff/core/Pair.mjs +6 -16
- package/output/js/ff/core/Path.mjs +12 -14
- package/output/js/ff/core/Random.mjs +24 -54
- package/output/js/ff/core/RbMap.mjs +54 -56
- package/output/js/ff/core/Serializable.mjs +19 -36
- package/output/js/ff/core/Set.mjs +0 -14
- package/output/js/ff/core/Show.mjs +0 -2
- package/output/js/ff/core/SourceLocation.mjs +0 -2
- package/output/js/ff/core/Stream.mjs +34 -44
- package/output/js/ff/core/String.mjs +31 -5
- package/output/js/ff/core/StringMap.mjs +32 -42
- package/output/js/ff/core/Task.mjs +0 -2
- package/output/js/ff/core/Try.mjs +0 -2
- package/output/js/ff/core/Unit.mjs +0 -2
- package/package.json +1 -1
- package/vscode/package.json +1 -1
- package/webserver/WebServer.ff +8 -8
- package/output/js/ff/core/Stack.mjs +0 -603
package/core/Stack.ff
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
class
|
|
1
|
+
class Array[T] {}
|
|
2
2
|
|
|
3
|
-
make[T]():
|
|
3
|
+
make[T](): Array[T]
|
|
4
4
|
target js sync "return {array: []}"
|
|
5
5
|
|
|
6
|
-
fill[T](size: Int, value: T):
|
|
6
|
+
fill[T](size: Int, value: T): List[T]
|
|
7
7
|
target js sync """
|
|
8
8
|
return {array: new Array(size_).fill(value_)};
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
fillBy[T](size: Int, body: Int => T):
|
|
11
|
+
fillBy[T](size: Int, body: Int => T): List[T]
|
|
12
12
|
target js sync """
|
|
13
13
|
return {array: Array.from({length: size_}, (_, i) => body_(i))};
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
-
range(size: Int):
|
|
16
|
+
range(size: Int): List[Int]
|
|
17
17
|
target js sync """
|
|
18
18
|
return {array: Array.from({length: size_}, (_, i) => i)};
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
extend self[T]:
|
|
21
|
+
extend self[T]: Array[T] {
|
|
22
22
|
|
|
23
23
|
isEmpty(): Bool
|
|
24
24
|
target js sync "return self_.array.length === 0"
|
|
@@ -41,9 +41,9 @@ extend self[T]: Stack[T] {
|
|
|
41
41
|
return self_.array[index_]
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
|
-
grabFirst(): T {
|
|
44
|
+
grabFirst(): T {self.grab(0)}
|
|
45
45
|
|
|
46
|
-
grabLast(): T {
|
|
46
|
+
grabLast(): T {self.grab(self.size() - 1)}
|
|
47
47
|
|
|
48
48
|
first(): Option[T]
|
|
49
49
|
target js sync """
|
|
@@ -62,10 +62,10 @@ extend self[T]: Stack[T] {
|
|
|
62
62
|
push(value: T): Unit
|
|
63
63
|
target js sync "self_.array.push(value_)"
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
pushArray(value: Array[T]): Unit
|
|
66
66
|
target js sync "self_.array.push(...value_.array)"
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
pushList(value: List[T]): Unit
|
|
69
69
|
target js sync "self_.array.push(...value_)"
|
|
70
70
|
|
|
71
71
|
pop(): Option[T]
|
|
@@ -117,12 +117,12 @@ extend self[T]: Stack[T] {
|
|
|
117
117
|
self_.array.splice(start_, deleteCount_, value_);
|
|
118
118
|
"""
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
insertArray(start: Int, value: Array[T], deleteCount: Int = 0): Unit
|
|
121
121
|
target js sync """
|
|
122
122
|
self_.array.splice(start_, deleteCount_, ...value_.array);
|
|
123
123
|
"""
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
insertList(start: Int, value: List[T], deleteCount: Int = 0): Unit
|
|
126
126
|
target js sync """
|
|
127
127
|
self_.array.splice(start_, deleteCount_, ...value_);
|
|
128
128
|
"""
|
|
@@ -170,27 +170,14 @@ extend self[T]: Stack[T] {
|
|
|
170
170
|
if(result) {i}
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
drain():
|
|
173
|
+
drain(): List[T]
|
|
174
174
|
target js sync "const result = self_.array; self_.array = []; return result"
|
|
175
175
|
|
|
176
|
-
toArray(start: Int = 0, end: Int = 9007199254740991): Array[T]
|
|
177
|
-
target js sync """return self_.array.slice(start_, end_)"""
|
|
178
|
-
|
|
179
176
|
toList(start: Int = 0, end: Int = 9007199254740991): List[T]
|
|
180
|
-
target js sync """
|
|
181
|
-
if(start_ < 0) start_ = self_.array.length + start_
|
|
182
|
-
if(end_ < 0) end_ = self_.array.length + start_
|
|
183
|
-
start_ = Math.max(0, Math.min(start_, self_.array.length))
|
|
184
|
-
end_ = Math.max(0, Math.min(end_, self_.array.length))
|
|
185
|
-
let result = ff_core_List.Empty();
|
|
186
|
-
for(let i = end_ - 1; i >= start_; i--) {
|
|
187
|
-
result = ff_core_List.Link(self_.array[i], result);
|
|
188
|
-
}
|
|
189
|
-
return result;
|
|
190
|
-
"""
|
|
177
|
+
target js sync """return self_.array.slice(start_, end_)"""
|
|
191
178
|
|
|
192
179
|
toStream(start: Int = 0, end: Int = 9007199254740991): Stream[T] {
|
|
193
|
-
self.
|
|
180
|
+
self.toList(start, end).toStream()
|
|
194
181
|
}
|
|
195
182
|
|
|
196
183
|
reverse(): Unit
|
|
@@ -207,7 +194,7 @@ extend self[T]: Stack[T] {
|
|
|
207
194
|
|
|
208
195
|
}
|
|
209
196
|
|
|
210
|
-
extend self[T: Order]:
|
|
197
|
+
extend self[T: Order]: Array[T] {
|
|
211
198
|
|
|
212
199
|
sort(): Unit {
|
|
213
200
|
self.sortWith(Ordering.compare)
|
|
@@ -215,46 +202,46 @@ extend self[T: Order]: Stack[T] {
|
|
|
215
202
|
|
|
216
203
|
}
|
|
217
204
|
|
|
218
|
-
extend self:
|
|
205
|
+
extend self: Array[String] {
|
|
219
206
|
|
|
220
207
|
join(separator: String = ""): String
|
|
221
208
|
target js sync "return self_.array.join(separator_)"
|
|
222
209
|
|
|
223
210
|
}
|
|
224
211
|
|
|
225
|
-
instance
|
|
226
|
-
show(value:
|
|
227
|
-
let
|
|
228
|
-
|
|
212
|
+
instance Array[T: Show]: Show {
|
|
213
|
+
show(value: Array[T]): String {
|
|
214
|
+
let array = Array.make()
|
|
215
|
+
array.push("[")
|
|
229
216
|
value.each {x =>
|
|
230
|
-
if(
|
|
231
|
-
|
|
217
|
+
if(array.size() > 1) {array.push(", ")}
|
|
218
|
+
array.push(Show.show(x))
|
|
232
219
|
}
|
|
233
|
-
|
|
234
|
-
|
|
220
|
+
array.push("].toArray()")
|
|
221
|
+
array.join()
|
|
235
222
|
}
|
|
236
223
|
}
|
|
237
224
|
|
|
238
|
-
sortRange[T](
|
|
225
|
+
sortRange[T](array: Array[T], compare: (T, T) => Ordering, start: Int, end: Int): Unit {
|
|
239
226
|
if(end - start < 2) {} else:
|
|
240
227
|
|
|
241
228
|
mutable middle = start + ((end - start) / 2)
|
|
242
|
-
sortRange(
|
|
243
|
-
sortRange(
|
|
229
|
+
sortRange(array, compare, start, middle)
|
|
230
|
+
sortRange(array, compare, middle, end)
|
|
244
231
|
|
|
245
232
|
mutable i = start
|
|
246
233
|
mutable j = middle
|
|
247
234
|
while {i < middle && j < end} {
|
|
248
|
-
if(compare(
|
|
235
|
+
if(compare(array.grab(i), array.grab(j)) != OrderingAfter) {
|
|
249
236
|
i += 1
|
|
250
237
|
} else {
|
|
251
|
-
let value =
|
|
238
|
+
let value = array.grab(j)
|
|
252
239
|
mutable k = j
|
|
253
240
|
while {k > i} {
|
|
254
|
-
|
|
241
|
+
array.set(k, array.grab(k - 1))
|
|
255
242
|
k -= 1
|
|
256
243
|
}
|
|
257
|
-
|
|
244
|
+
array.set(i, value)
|
|
258
245
|
i += 1
|
|
259
246
|
middle += 1
|
|
260
247
|
j += 1
|
package/core/Stream.ff
CHANGED
|
@@ -337,18 +337,14 @@ extend self[T]: Stream[T] {
|
|
|
337
337
|
result
|
|
338
338
|
}
|
|
339
339
|
|
|
340
|
-
toStack(): Stack[T] {
|
|
341
|
-
let stack = Stack.make()
|
|
342
|
-
self.each {stack.push(_)}
|
|
343
|
-
stack
|
|
344
|
-
}
|
|
345
|
-
|
|
346
340
|
toArray(): Array[T] {
|
|
347
|
-
|
|
341
|
+
let array = Array.make()
|
|
342
|
+
self.each {array.push(_)}
|
|
343
|
+
array
|
|
348
344
|
}
|
|
349
345
|
|
|
350
346
|
toList(): List[T] {
|
|
351
|
-
self.
|
|
347
|
+
self.toArray().drain()
|
|
352
348
|
}
|
|
353
349
|
|
|
354
350
|
}
|
|
@@ -361,20 +357,20 @@ extend self[T]: Stream[Stream[T]] {
|
|
|
361
357
|
|
|
362
358
|
extend self[T: Order]: Stream[T] {
|
|
363
359
|
toSet(): Set[T] {
|
|
364
|
-
self.
|
|
360
|
+
self.toList().toSet()
|
|
365
361
|
}
|
|
366
362
|
}
|
|
367
363
|
|
|
368
364
|
extend self[K: Order, V]: Stream[Pair[K, V]] {
|
|
369
365
|
toMap(): Map[K, V] {
|
|
370
|
-
self.
|
|
366
|
+
self.toList().toMap()
|
|
371
367
|
}
|
|
372
368
|
}
|
|
373
369
|
|
|
374
370
|
extend self: Stream[Buffer] {
|
|
375
371
|
|
|
376
372
|
toBuffer(): Buffer {
|
|
377
|
-
let builder =
|
|
373
|
+
let builder = Array.make()
|
|
378
374
|
self.each {builder.push(_)}
|
|
379
375
|
Buffer.fromBufferArray(builder.drain())
|
|
380
376
|
}
|
|
@@ -383,9 +379,9 @@ extend self: Stream[Buffer] {
|
|
|
383
379
|
self.toBuffer().toString(encoding)
|
|
384
380
|
}
|
|
385
381
|
|
|
386
|
-
readBytes(bytes: Int): Pair[
|
|
387
|
-
if(bytes <= 0) {Pair([]
|
|
388
|
-
let buffers =
|
|
382
|
+
readBytes(bytes: Int): Pair[List[Buffer], Stream[Buffer]] {
|
|
383
|
+
if(bytes <= 0) {Pair([], self)} else:
|
|
384
|
+
let buffers = Array.make()
|
|
389
385
|
mutable buffer = self.next().grab()
|
|
390
386
|
mutable taken = 0
|
|
391
387
|
mutable remainder = None
|
package/core/String.ff
CHANGED
|
@@ -67,7 +67,7 @@ extend self: String {
|
|
|
67
67
|
slice(from: Int, until: Int): String
|
|
68
68
|
target js sync "return self_.slice(from_, until_)"
|
|
69
69
|
|
|
70
|
-
split(char: Char):
|
|
70
|
+
split(char: Char): List[String]
|
|
71
71
|
target js sync "return self_.split(String.fromCharCode(char_))"
|
|
72
72
|
|
|
73
73
|
splitFirst(char: Char): Option[Pair[String, String]]
|
|
@@ -80,9 +80,9 @@ extend self: String {
|
|
|
80
80
|
|
|
81
81
|
lines(): List[String]
|
|
82
82
|
target js sync """
|
|
83
|
-
return
|
|
83
|
+
return self_.split(
|
|
84
84
|
new RegExp("[" + String.fromCharCode(13) + "]?[" + String.fromCharCode(10) + "]", "g")
|
|
85
|
-
)
|
|
85
|
+
)
|
|
86
86
|
"""
|
|
87
87
|
|
|
88
88
|
dropFirst(count: Int = 1): String
|
|
@@ -98,10 +98,19 @@ extend self: String {
|
|
|
98
98
|
}
|
|
99
99
|
for(let i = 0; i < self_.length; i++) {
|
|
100
100
|
const c = self_.codePointAt(i)
|
|
101
|
-
if(c < 48 || c > 57) ff_core_Option.None()
|
|
101
|
+
if(c < 48 || c > 57) return ff_core_Option.None()
|
|
102
102
|
}
|
|
103
103
|
return ff_core_Option.Some(parseInt(self_, 10));
|
|
104
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
|
+
"""
|
|
105
114
|
|
|
106
115
|
grabInt(): Int
|
|
107
116
|
target js sync """
|
|
@@ -114,6 +123,15 @@ extend self: String {
|
|
|
114
123
|
}
|
|
115
124
|
return parseInt(self_, 10);
|
|
116
125
|
"""
|
|
126
|
+
|
|
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
|
+
"""
|
|
117
135
|
|
|
118
136
|
first(): Option[Char]
|
|
119
137
|
target js sync """
|
|
@@ -129,9 +147,9 @@ extend self: String {
|
|
|
129
147
|
: ff_core_Option.None()
|
|
130
148
|
"""
|
|
131
149
|
|
|
132
|
-
grabFirst(): Char {
|
|
150
|
+
grabFirst(): Char {self.first().else {Try.internalThrowGrabException()}}
|
|
133
151
|
|
|
134
|
-
grabLast(): Char {
|
|
152
|
+
grabLast(): Char {self.last().else {Try.internalThrowGrabException()}}
|
|
135
153
|
|
|
136
154
|
contains(substring: String): Bool
|
|
137
155
|
target js sync "return self_.includes(substring_)"
|
package/core/StringMap.ff
CHANGED
|
@@ -40,38 +40,34 @@ extend self[V]: StringMap[V] {
|
|
|
40
40
|
target js sync "for(const [k, v] of self_) if(!body_(k, v)) break"
|
|
41
41
|
target js async "for(const [k, v] of self_) if(!await body_(k, v)) break"
|
|
42
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
43
|
toArray(): Array[Pair[String, V]] {
|
|
50
|
-
|
|
44
|
+
let array = Array.make()
|
|
45
|
+
self.each {k, v => array.push(Pair(k, v))}
|
|
46
|
+
array
|
|
51
47
|
}
|
|
52
48
|
|
|
53
49
|
toList(): List[Pair[String, V]] {
|
|
54
|
-
self.toArray().
|
|
50
|
+
self.toArray().drain()
|
|
55
51
|
}
|
|
56
52
|
|
|
57
53
|
toStream(): Stream[Pair[String, V]] {
|
|
58
|
-
self.
|
|
54
|
+
self.toList().toStream()
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
toMap(): Map[String, V] {
|
|
62
|
-
self.
|
|
58
|
+
self.toList().toMap()
|
|
63
59
|
}
|
|
64
60
|
|
|
65
61
|
keys(): List[String] {
|
|
66
|
-
let
|
|
67
|
-
self.each {k, v =>
|
|
68
|
-
|
|
62
|
+
let array = Array.make()
|
|
63
|
+
self.each {k, v => array.push(k)}
|
|
64
|
+
array.toList()
|
|
69
65
|
}
|
|
70
66
|
|
|
71
67
|
values(): List[V] {
|
|
72
|
-
let
|
|
73
|
-
self.each {k, v =>
|
|
74
|
-
|
|
68
|
+
let array = Array.make()
|
|
69
|
+
self.each {k, v => array.push(v)}
|
|
70
|
+
array.toList()
|
|
75
71
|
}
|
|
76
72
|
|
|
77
73
|
copy(): StringMap[V]
|
|
@@ -84,12 +80,12 @@ extend self[V]: StringMap[V] {
|
|
|
84
80
|
|
|
85
81
|
}
|
|
86
82
|
|
|
87
|
-
extend self[V]: StringMap[
|
|
83
|
+
extend self[V]: StringMap[Array[V]] {
|
|
88
84
|
|
|
89
85
|
push(key: String, value: V) {
|
|
90
86
|
self.get(key).{
|
|
91
|
-
| None => self.set(key, [value].
|
|
92
|
-
| Some(
|
|
87
|
+
| None => self.set(key, [value].toArray())
|
|
88
|
+
| Some(array) => array.push(value)
|
|
93
89
|
}
|
|
94
90
|
}
|
|
95
91
|
|
package/guide/Main.ff
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
nodeMain(system: NodeSystem) {
|
|
2
|
-
|
|
3
|
-
system.
|
|
2
|
+
|
|
3
|
+
//let lines = system.path("data.txt").readText().lines()
|
|
4
|
+
let lines = [
|
|
5
|
+
"Monday: 22.5"
|
|
6
|
+
"Tuesday: 25.7"
|
|
7
|
+
"Wednesday: 23.9"
|
|
8
|
+
"Thursday: 22.4"
|
|
9
|
+
"Friday: 20.3"
|
|
10
|
+
""
|
|
11
|
+
"Saturday: 16.2"
|
|
12
|
+
"Sunday: 21.1 "
|
|
13
|
+
]
|
|
14
|
+
let pairs = lines.map {_.split(':')}.collect {
|
|
15
|
+
| [day, temp] => Some(Pair(day.trim(), temp.trim().grabFloat()))
|
|
16
|
+
| _ => None
|
|
17
|
+
}
|
|
18
|
+
let remaining = pairs.map {_.second}.sort().dropFirst().dropLast()
|
|
19
|
+
let average = remaining.foldLeft(0.0) {_ + _} / remaining.size()
|
|
20
|
+
system.writeLine("Average temperature: " + average)
|
|
21
|
+
|
|
4
22
|
}
|
package/lsp/CompletionHandler.ff
CHANGED
|
@@ -72,7 +72,7 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
|
|
|
72
72
|
completion(h.unification, h.environment, typePrefix, qualifiedByAlias, expected)
|
|
73
73
|
}
|
|
74
74
|
| InferRecordFieldHook h {h.unification.substitute(h.recordType) | TConstructor(_, n, ts)} =>
|
|
75
|
-
let fieldNames = n.split('$').
|
|
75
|
+
let fieldNames = n.split('$').dropFirst(1)
|
|
76
76
|
let fieldCompletions = fieldNames.zip(ts).map {| Pair(name, t) =>
|
|
77
77
|
let t2 = h.unification.substitute(t)
|
|
78
78
|
CompletionInfo(name, "", name, True, t2, "(\n ...\n " + name + ": " + t2.show([]) + "\n ...\n)", Some(h.expected))
|
|
@@ -162,7 +162,7 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
|
|
|
162
162
|
completionsToJson(completions: List[CompletionInfo]): Json {
|
|
163
163
|
Json.object()
|
|
164
164
|
.with("isIncomplete", False)
|
|
165
|
-
.with("items", completions.distinct().
|
|
165
|
+
.with("items", completions.distinct().map {| CompletionInfo i =>
|
|
166
166
|
let shownType = i.type.show([])
|
|
167
167
|
let isAlpha = i.label.first().any {_.isAsciiLetter()}
|
|
168
168
|
let isLower = i.label.first().any {_.isAsciiLower()}
|
|
@@ -228,7 +228,7 @@ completion(
|
|
|
228
228
|
|
|
229
229
|
let member = prefix.contains("_")
|
|
230
230
|
|
|
231
|
-
let members =
|
|
231
|
+
let members = Array.make()
|
|
232
232
|
|
|
233
233
|
let symbols = if(prefix == "") {
|
|
234
234
|
environment.symbols.toList().collect {
|
|
@@ -258,7 +258,7 @@ completion(
|
|
|
258
258
|
None
|
|
259
259
|
}.toMap()
|
|
260
260
|
} else {
|
|
261
|
-
members.
|
|
261
|
+
members.pushArray(exhaustiveMatchCompletion(environment, prefix, False).toArray())
|
|
262
262
|
let shorterPrefix = prefix.dropLast()
|
|
263
263
|
let recordFields = shorterPrefix.split('$').dropFirst().toSet()
|
|
264
264
|
environment.symbols.each {
|
package/lsp/Handler.ff
CHANGED
|
@@ -17,10 +17,16 @@ capability Handler(
|
|
|
17
17
|
mutable rootPath: Option[Path]
|
|
18
18
|
mutable virtualFiles: Map[String, String]
|
|
19
19
|
mutable cancelledRequests: Set[MessageId]
|
|
20
|
-
mutable responseCache: Map[
|
|
20
|
+
mutable responseCache: Map[TokenRequestCacheKey, ResultOrError]
|
|
21
21
|
mutable fileSymbolsCache: Map[String, List[DocumentSymbol]]
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
+
data TokenRequestCacheKey(
|
|
25
|
+
method: String
|
|
26
|
+
targetAt: Location
|
|
27
|
+
includeDeclaration: Bool
|
|
28
|
+
)
|
|
29
|
+
|
|
24
30
|
data MessageId {
|
|
25
31
|
MessageIdInt(id: Int)
|
|
26
32
|
MessageIdString(id: String)
|
|
@@ -77,21 +83,21 @@ extend self: Handler {
|
|
|
77
83
|
| "textDocument/completion" => self.handleCompletion(system, parameters)
|
|
78
84
|
| "textDocument/signatureHelp" => self.handleSignatureHelp(system, parameters)
|
|
79
85
|
| "textDocument/hover" =>
|
|
80
|
-
self.handleTokenRequestWithCache(system, method, parameters) {
|
|
81
|
-
self.handleHover(system, targetAt, goToDefinition = False)
|
|
86
|
+
self.handleTokenRequestWithCache(system, method, parameters) {key =>
|
|
87
|
+
self.handleHover(system, key.targetAt, goToDefinition = False)
|
|
82
88
|
}
|
|
83
89
|
| "textDocument/definition" =>
|
|
84
|
-
self.handleTokenRequestWithCache(system, method, parameters) {
|
|
85
|
-
self.handleHover(system, targetAt, goToDefinition = True)
|
|
90
|
+
self.handleTokenRequestWithCache(system, method, parameters) {key =>
|
|
91
|
+
self.handleHover(system, key.targetAt, goToDefinition = True)
|
|
86
92
|
}
|
|
87
93
|
| "textDocument/references" =>
|
|
88
|
-
self.handleTokenRequestWithCache(system, method, parameters) {
|
|
89
|
-
self.handleReferences(system, targetAt, local = False)
|
|
94
|
+
self.handleTokenRequestWithCache(system, method, parameters) {key =>
|
|
95
|
+
self.handleReferences(system, key.targetAt, key.includeDeclaration, local = False)
|
|
90
96
|
}
|
|
91
97
|
| "textDocument/rename" => self.handleRename(system, parameters)
|
|
92
98
|
| "textDocument/documentHighlight" =>
|
|
93
|
-
self.handleTokenRequestWithCache(system, method, parameters) {
|
|
94
|
-
self.handleReferences(system, targetAt, local = True)
|
|
99
|
+
self.handleTokenRequestWithCache(system, method, parameters) {key =>
|
|
100
|
+
self.handleReferences(system, key.targetAt, includeDeclaration = True, local = True)
|
|
95
101
|
}
|
|
96
102
|
| "workspace/symbol" =>
|
|
97
103
|
self.printTime(system.mainTask(), "handleWorkspaceSymbol") {
|
|
@@ -106,17 +112,21 @@ extend self: Handler {
|
|
|
106
112
|
system: NodeSystem
|
|
107
113
|
method: String
|
|
108
114
|
parameters: Map[String, Json]
|
|
109
|
-
handle:
|
|
115
|
+
handle: TokenRequestCacheKey => ResultOrError
|
|
110
116
|
): ResultOrError {
|
|
111
117
|
let targetAt = self.findTokenFromParameters(system, parameters)
|
|
112
|
-
let
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
let includeDeclaration = parameters.get("context").{
|
|
119
|
+
| Some(context) {context.field("includeDeclaration") | includeDeclaration} {includeDeclaration.getBool() | Some(b)} => b
|
|
120
|
+
| _ => True
|
|
121
|
+
}
|
|
122
|
+
let cacheKey = TokenRequestCacheKey(method, targetAt, includeDeclaration)
|
|
123
|
+
self.responseCache.get(cacheKey).{
|
|
124
|
+
| Some(hit) => hit
|
|
125
|
+
| None =>
|
|
126
|
+
let result = handle(cacheKey)
|
|
127
|
+
self.responseCache = self.responseCache.add(cacheKey, result)
|
|
128
|
+
result
|
|
129
|
+
}
|
|
120
130
|
}
|
|
121
131
|
|
|
122
132
|
handleUnsupported(): ResultOrError {
|
|
@@ -230,7 +240,7 @@ extend self: Handler {
|
|
|
230
240
|
let path = system.pathFromUrl(uri)
|
|
231
241
|
let symbols = self.getDocumentSymbolsWithCache(system, path)
|
|
232
242
|
let lspSymbols = symbols.map {SymbolHandler.documentSymbolToLsp(_)}
|
|
233
|
-
Result(Json.
|
|
243
|
+
Result(Json.array(lspSymbols).write())
|
|
234
244
|
}
|
|
235
245
|
|
|
236
246
|
getDocumentSymbols(system: NodeSystem, path: Path): List[DocumentSymbol] {
|
|
@@ -277,7 +287,7 @@ extend self: Handler {
|
|
|
277
287
|
}
|
|
278
288
|
let limitedSymbols = symbols.sortBy {_.name.size()}.takeFirst(100)
|
|
279
289
|
let jsSymbols = limitedSymbols.map {SymbolHandler.workspaceSymbolToLsp(self.rootPath.grab(), _)}
|
|
280
|
-
Result(Json.
|
|
290
|
+
Result(Json.array(jsSymbols).write())
|
|
281
291
|
}
|
|
282
292
|
|
|
283
293
|
handleDidChange(system: NodeSystem, parameters: Map[String, Json]): Unit {
|
|
@@ -322,7 +332,7 @@ extend self: Handler {
|
|
|
322
332
|
line = token.startLine
|
|
323
333
|
column = token.startColumn
|
|
324
334
|
)
|
|
325
|
-
Log.show(token.followedByLeftBracket)
|
|
335
|
+
//Log.show(token.followedByLeftBracket)
|
|
326
336
|
let lspHook = LspHook.make(at = Some(completionAt), definedAt = None, insertIdentifier = True, trackSymbols = False)
|
|
327
337
|
try {
|
|
328
338
|
Builder.check(system, self.fireflyPath, system.path(completionAt.file), self.virtualFiles, lspHook, True)
|
|
@@ -373,13 +383,13 @@ extend self: Handler {
|
|
|
373
383
|
Result((o.else {Json.null()}).write())
|
|
374
384
|
}
|
|
375
385
|
|
|
376
|
-
handleReferences(system: NodeSystem, targetAt: Location, local: Bool): ResultOrError {
|
|
377
|
-
let tokens = self.findReferences(system, targetAt, local)
|
|
386
|
+
handleReferences(system: NodeSystem, targetAt: Location, includeDeclaration: Bool, local: Bool): ResultOrError {
|
|
387
|
+
let tokens = self.findReferences(system, targetAt, local, includeDeclaration)
|
|
378
388
|
let o = tokens.{
|
|
379
389
|
| None => Json.null()
|
|
380
390
|
| Some(tokens) =>
|
|
381
391
|
let lspTokens = tokens.map {self.tokenLocationToLspLocation(system, _)}
|
|
382
|
-
Json.
|
|
392
|
+
Json.array(lspTokens)
|
|
383
393
|
}
|
|
384
394
|
Result(o.write())
|
|
385
395
|
}
|
|
@@ -387,11 +397,11 @@ extend self: Handler {
|
|
|
387
397
|
handleRename(system: NodeSystem, parameters: Map[String, Json]): ResultOrError {
|
|
388
398
|
let newName = parameters.grab("newName").grabString()
|
|
389
399
|
let targetAt = self.findTokenFromParameters(system, parameters)
|
|
390
|
-
let tokens = self.findReferences(system, targetAt, False)
|
|
400
|
+
let tokens = self.findReferences(system, targetAt, local = False, includeDeclaration = True)
|
|
391
401
|
tokens.{
|
|
392
402
|
| None => Error(-32602, "Token definition not found") // InvalidParams
|
|
393
403
|
| Some([]) => Result(Json.null().write())
|
|
394
|
-
| Some([first, ...
|
|
404
|
+
| Some([first, ...] @ tokens) =>
|
|
395
405
|
let oldName = first.raw
|
|
396
406
|
Log.trace("Rename '" + oldName + "' to '" + newName + "'")
|
|
397
407
|
|
|
@@ -415,7 +425,7 @@ extend self: Handler {
|
|
|
415
425
|
}
|
|
416
426
|
}
|
|
417
427
|
|
|
418
|
-
findReferences(system: NodeSystem, targetAt: Location, local: Bool): Option[List[TokenLocation]] {
|
|
428
|
+
findReferences(system: NodeSystem, targetAt: Location, local: Bool, includeDeclaration: Bool): Option[List[TokenLocation]] {
|
|
419
429
|
let temporaryLspHook = LspHook.make(at = Some(targetAt), definedAt = None, insertIdentifier = False, trackSymbols = False)
|
|
420
430
|
try {
|
|
421
431
|
Builder.check(system, self.fireflyPath, system.path(targetAt.file), self.virtualFiles, temporaryLspHook, True)
|
|
@@ -440,8 +450,6 @@ extend self: Handler {
|
|
|
440
450
|
| _ => None
|
|
441
451
|
}.filter {at => !at.file.endsWith(">")}
|
|
442
452
|
|
|
443
|
-
//Log.trace("definedAtList: " + Show.show(definedAtList))
|
|
444
|
-
|
|
445
453
|
definedAtList.first().{
|
|
446
454
|
| Some(definedAt) =>
|
|
447
455
|
//Log.trace("handleReferences definedAt: " + Show.show(definedAt))
|
|
@@ -465,11 +473,14 @@ extend self: Handler {
|
|
|
465
473
|
h.parameters.find {_.name == n}.map {_ => a.at}
|
|
466
474
|
| InferLookupHook h => Some(h.symbol.value.usageAt)
|
|
467
475
|
| _ => None
|
|
468
|
-
}.filter {at =>
|
|
469
|
-
|
|
470
|
-
|
|
476
|
+
}.filter {at =>
|
|
477
|
+
!at.file.endsWith(">") &&
|
|
478
|
+
(includeDeclaration || at != definedAt)
|
|
479
|
+
}
|
|
471
480
|
|
|
472
|
-
let clientLocations = referencesResult.addAll(
|
|
481
|
+
let clientLocations = referencesResult.addAll(
|
|
482
|
+
if(includeDeclaration) {[definedAt]} else {[]}
|
|
483
|
+
).distinct().filter {
|
|
473
484
|
!local || _.file == targetAt.file
|
|
474
485
|
}.map {at =>
|
|
475
486
|
self.findToken(system, at)
|
package/lsp/HoverHandler.ff
CHANGED
|
@@ -18,7 +18,7 @@ handleGoToDefinition(system: NodeSystem, handler: Handler, lspHook: LspHook): Js
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
| InferRecordFieldHook h {h.unification.substitute(h.recordType) | TConstructor(_, n, ts)} =>
|
|
21
|
-
let fieldNames = n.split('$').
|
|
21
|
+
let fieldNames = n.split('$').dropFirst(1)
|
|
22
22
|
fieldNames.zip(ts).collectFirst {| Pair(name, t) =>
|
|
23
23
|
if(h.fieldName == name) {
|
|
24
24
|
h.unification.substitute(t).at // TODO: This points to the field type rather than the field name
|
|
@@ -55,7 +55,7 @@ handleHover(system: NodeSystem, handler: Handler, lspHook: LspHook): Json {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
| InferRecordFieldHook h {h.unification.substitute(h.recordType) | TConstructor(_, n, ts)} =>
|
|
58
|
-
let fieldNames = n.split('$').
|
|
58
|
+
let fieldNames = n.split('$').dropFirst(1)
|
|
59
59
|
fieldNames.zip(ts).collectFirst {| Pair(name, t) =>
|
|
60
60
|
if(h.fieldName == name) {
|
|
61
61
|
let noEffect = TConstructor(t.at, "ff:core/Nothing.Nothing", [])
|
package/lsp/LanguageServer.ff
CHANGED
|
@@ -105,13 +105,13 @@ parseRequest(system: NodeSystem, input: Stream[Buffer]): Pair[Request, Stream[Bu
|
|
|
105
105
|
let headers = headersPair.first
|
|
106
106
|
let contentLength = headers
|
|
107
107
|
.get("content-length").else {throw(BadRequestException("'content-length' header is missing"))}
|
|
108
|
-
.getInt().else {throw(BadRequestException("Value for 'content-length' is not an integer"))}
|
|
108
|
+
.trim().getInt().else {throw(BadRequestException("Value for 'content-length' is not an integer"))}
|
|
109
109
|
let bodyPair = parseRequestBody(contentLength, headersPair.second)
|
|
110
110
|
bodyPair.mapFirst {body => Request(headers, body)}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
parseRequestHeaders(input: Stream[Buffer]): Pair[Map[String, String], Stream[Buffer]] {
|
|
114
|
-
let buffers =
|
|
114
|
+
let buffers = Array.make()
|
|
115
115
|
mutable buffer = input.next().else {
|
|
116
116
|
throw(BadRequestException("End of input while parsing request headers"))
|
|
117
117
|
}
|
|
@@ -44,7 +44,7 @@ handleSignatureHelp(system: NodeSystem, lspHook: LspHook): Json {
|
|
|
44
44
|
|
|
45
45
|
pickActiveParameter(help: Json, argumentIndex: Int, parameterName: Option[String]): Json {
|
|
46
46
|
parameterName.flatMap {name =>
|
|
47
|
-
let parameters = help.field("signatures").index(0).field("parameters").grabArray()
|
|
47
|
+
let parameters = help.field("signatures").index(0).field("parameters").grabArray()
|
|
48
48
|
parameters.pairs().collectFirst {| Pair(i, p) =>
|
|
49
49
|
if(name == p.field("label").grabString().takeWhile {_.isAsciiLetterOrDigit()}) {
|
|
50
50
|
help.with("activeParameter", i)
|
package/lsp/SymbolHandler.ff
CHANGED
|
@@ -96,7 +96,7 @@ documentSymbolToLsp(symbol: DocumentSymbol): Json {
|
|
|
96
96
|
.with("kind", symbol.kind)
|
|
97
97
|
.with("range", locationsToLspRange(symbol.start, symbol.end))
|
|
98
98
|
.with("selectionRange", locationsToLspRange(symbol.selectionStart, symbol.selectionEnd))
|
|
99
|
-
.with("children", symbol.children.
|
|
99
|
+
.with("children", symbol.children.map {documentSymbolToLsp(_)})
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
workspaceSymbolToLsp(rootPath: Path, symbol: WorkspaceSymbol): Json {
|