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.
Files changed (115) 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 +4 -4
  7. package/compiler/Main.ff +6 -6
  8. package/compiler/Parser.ff +39 -39
  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 +19 -28
  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/Stack.ff +32 -45
  34. package/core/Stream.ff +10 -14
  35. package/core/String.ff +24 -6
  36. package/core/StringMap.ff +15 -19
  37. package/guide/Main.ff +20 -2
  38. package/lsp/CompletionHandler.ff +4 -4
  39. package/lsp/Handler.ff +44 -33
  40. package/lsp/HoverHandler.ff +2 -2
  41. package/lsp/LanguageServer.ff +2 -2
  42. package/lsp/SignatureHelpHandler.ff +1 -1
  43. package/lsp/SymbolHandler.ff +1 -1
  44. package/lux/Lux.ff +3 -3
  45. package/output/js/ff/compiler/Builder.mjs +19 -21
  46. package/output/js/ff/compiler/Compiler.mjs +18 -20
  47. package/output/js/ff/compiler/Dependencies.mjs +8 -10
  48. package/output/js/ff/compiler/Deriver.mjs +234 -236
  49. package/output/js/ff/compiler/Dictionaries.mjs +6 -8
  50. package/output/js/ff/compiler/Environment.mjs +42 -44
  51. package/output/js/ff/compiler/Inference.mjs +346 -304
  52. package/output/js/ff/compiler/JsEmitter.mjs +907 -833
  53. package/output/js/ff/compiler/JsImporter.mjs +0 -2
  54. package/output/js/ff/compiler/LspHook.mjs +10 -12
  55. package/output/js/ff/compiler/Main.mjs +109 -111
  56. package/output/js/ff/compiler/Parser.mjs +405 -407
  57. package/output/js/ff/compiler/Patterns.mjs +64 -50
  58. package/output/js/ff/compiler/Resolver.mjs +36 -38
  59. package/output/js/ff/compiler/Substitution.mjs +4 -6
  60. package/output/js/ff/compiler/Syntax.mjs +160 -162
  61. package/output/js/ff/compiler/Token.mjs +52 -54
  62. package/output/js/ff/compiler/Tokenizer.mjs +16 -18
  63. package/output/js/ff/compiler/Unification.mjs +24 -26
  64. package/output/js/ff/compiler/Wildcards.mjs +0 -2
  65. package/output/js/ff/compiler/Workspace.mjs +18 -20
  66. package/output/js/ff/core/Any.mjs +0 -2
  67. package/output/js/ff/core/Array.mjs +216 -613
  68. package/output/js/ff/core/AssetSystem.mjs +2 -4
  69. package/output/js/ff/core/Atomic.mjs +0 -2
  70. package/output/js/ff/core/Bool.mjs +0 -2
  71. package/output/js/ff/core/Box.mjs +0 -2
  72. package/output/js/ff/core/BrowserSystem.mjs +0 -2
  73. package/output/js/ff/core/Buffer.mjs +0 -2
  74. package/output/js/ff/core/BuildSystem.mjs +12 -14
  75. package/output/js/ff/core/Channel.mjs +0 -2
  76. package/output/js/ff/core/Char.mjs +0 -2
  77. package/output/js/ff/core/Core.mjs +0 -2
  78. package/output/js/ff/core/Duration.mjs +0 -2
  79. package/output/js/ff/core/Equal.mjs +0 -22
  80. package/output/js/ff/core/Error.mjs +0 -2
  81. package/output/js/ff/core/FileHandle.mjs +0 -2
  82. package/output/js/ff/core/Float.mjs +0 -2
  83. package/output/js/ff/core/HttpClient.mjs +2 -4
  84. package/output/js/ff/core/Instant.mjs +0 -2
  85. package/output/js/ff/core/Int.mjs +8 -10
  86. package/output/js/ff/core/IntMap.mjs +32 -42
  87. package/output/js/ff/core/JsSystem.mjs +1 -3
  88. package/output/js/ff/core/JsValue.mjs +5 -12
  89. package/output/js/ff/core/Json.mjs +23 -56
  90. package/output/js/ff/core/List.mjs +648 -1989
  91. package/output/js/ff/core/Lock.mjs +0 -2
  92. package/output/js/ff/core/Log.mjs +0 -2
  93. package/output/js/ff/core/Map.mjs +10 -20
  94. package/output/js/ff/core/NodeSystem.mjs +6 -8
  95. package/output/js/ff/core/Nothing.mjs +0 -2
  96. package/output/js/ff/core/Option.mjs +8 -18
  97. package/output/js/ff/core/Ordering.mjs +20 -98
  98. package/output/js/ff/core/Pair.mjs +6 -16
  99. package/output/js/ff/core/Path.mjs +12 -14
  100. package/output/js/ff/core/Random.mjs +24 -54
  101. package/output/js/ff/core/RbMap.mjs +54 -56
  102. package/output/js/ff/core/Serializable.mjs +19 -36
  103. package/output/js/ff/core/Set.mjs +0 -14
  104. package/output/js/ff/core/Show.mjs +0 -2
  105. package/output/js/ff/core/SourceLocation.mjs +0 -2
  106. package/output/js/ff/core/Stream.mjs +34 -44
  107. package/output/js/ff/core/String.mjs +31 -5
  108. package/output/js/ff/core/StringMap.mjs +32 -42
  109. package/output/js/ff/core/Task.mjs +0 -2
  110. package/output/js/ff/core/Try.mjs +0 -2
  111. package/output/js/ff/core/Unit.mjs +0 -2
  112. package/package.json +1 -1
  113. package/vscode/package.json +1 -1
  114. package/webserver/WebServer.ff +8 -8
  115. package/output/js/ff/core/Stack.mjs +0 -603
package/core/Stack.ff CHANGED
@@ -1,24 +1,24 @@
1
- class Stack[T] {}
1
+ class Array[T] {}
2
2
 
3
- make[T](): Stack[T]
3
+ make[T](): Array[T]
4
4
  target js sync "return {array: []}"
5
5
 
6
- fill[T](size: Int, value: T): Array[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): Array[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): Array[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]: Stack[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 { self.grab(0) }
44
+ grabFirst(): T {self.grab(0)}
45
45
 
46
- grabLast(): T { self.grab(self.size() - 1) }
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
- pushAll(value: Stack[T]): Unit
65
+ pushArray(value: Array[T]): Unit
66
66
  target js sync "self_.array.push(...value_.array)"
67
67
 
68
- pushArray(value: Array[T]): Unit
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
- insertAll(start: Int, value: Stack[T], deleteCount: Int = 0): Unit
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
- insertArray(start: Int, value: Array[T], deleteCount: Int = 0): Unit
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(): Array[T]
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.toArray(start, end).toStream()
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]: Stack[T] {
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: Stack[String] {
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 Stack[T: Show]: Show {
226
- show(value: Stack[T]): String {
227
- let stack = Stack.make()
228
- stack.push("[")
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(stack.size() > 1) {stack.push(", ")}
231
- stack.push(Show.show(x))
217
+ if(array.size() > 1) {array.push(", ")}
218
+ array.push(Show.show(x))
232
219
  }
233
- stack.push("].toStack()")
234
- stack.join()
220
+ array.push("].toArray()")
221
+ array.join()
235
222
  }
236
223
  }
237
224
 
238
- sortRange[T](stack: Stack[T], compare: (T, T) => Ordering, start: Int, end: Int): Unit {
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(stack, compare, start, middle)
243
- sortRange(stack, compare, middle, end)
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(stack.grab(i), stack.grab(j)) != OrderingAfter) {
235
+ if(compare(array.grab(i), array.grab(j)) != OrderingAfter) {
249
236
  i += 1
250
237
  } else {
251
- let value = stack.grab(j)
238
+ let value = array.grab(j)
252
239
  mutable k = j
253
240
  while {k > i} {
254
- stack.set(k, stack.grab(k - 1))
241
+ array.set(k, array.grab(k - 1))
255
242
  k -= 1
256
243
  }
257
- stack.set(i, value)
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
- self.toStack().drain()
341
+ let array = Array.make()
342
+ self.each {array.push(_)}
343
+ array
348
344
  }
349
345
 
350
346
  toList(): List[T] {
351
- self.toStack().toList()
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.toArray().toSet()
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.toArray().toMap()
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 = Stack.make()
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[Array[Buffer], Stream[Buffer]] {
387
- if(bytes <= 0) {Pair([].toArray(), self)} else:
388
- let buffers = Stack.make()
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): Array[String]
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 ff_core_Array.Array_toList(self_.split(
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 { self.first().else {Try.internalThrowGrabException()} }
150
+ grabFirst(): Char {self.first().else {Try.internalThrowGrabException()}}
133
151
 
134
- grabLast(): Char { self.last().else {Try.internalThrowGrabException()} }
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
- self.toStack().drain()
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().toList()
50
+ self.toArray().drain()
55
51
  }
56
52
 
57
53
  toStream(): Stream[Pair[String, V]] {
58
- self.toArray().toStream()
54
+ self.toList().toStream()
59
55
  }
60
56
 
61
57
  toMap(): Map[String, V] {
62
- self.toArray().toMap()
58
+ self.toList().toMap()
63
59
  }
64
60
 
65
61
  keys(): List[String] {
66
- let stack = Stack.make()
67
- self.each {k, v => stack.push(k)}
68
- stack.toList()
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 stack = Stack.make()
73
- self.each {k, v => stack.push(v)}
74
- stack.toList()
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[Stack[V]] {
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].toStack())
92
- | Some(stack) => stack.push(value)
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
- let text = system.httpClient().fetch("https://www.example.com/").readText()
3
- system.writeLine(text)
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
  }
@@ -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('$').toList().dropFirst(1)
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().toArray().map {| CompletionInfo i =>
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 = Stack.make()
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.pushAll(exhaustiveMatchCompletion(environment, prefix, False).toStack())
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[Pair[String, Location], ResultOrError]
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) {targetAt =>
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) {targetAt =>
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) {targetAt =>
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) {targetAt =>
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: Location => ResultOrError
115
+ handle: TokenRequestCacheKey => ResultOrError
110
116
  ): ResultOrError {
111
117
  let targetAt = self.findTokenFromParameters(system, parameters)
112
- let cacheKey = Pair(method, targetAt)
113
- self.responseCache.get(cacheKey).{
114
- | Some(hit) => hit
115
- | None =>
116
- let result = handle(targetAt)
117
- self.responseCache = self.responseCache.add(cacheKey, result)
118
- result
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.list(lspSymbols).write())
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.list(jsSymbols).write())
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.list(lspTokens)
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, ..._] @ tokens) =>
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 => !at.file.endsWith(">")}
469
-
470
- //Log.trace("referencesResult: " + Show.show(referencesResult))
476
+ }.filter {at =>
477
+ !at.file.endsWith(">") &&
478
+ (includeDeclaration || at != definedAt)
479
+ }
471
480
 
472
- let clientLocations = referencesResult.addAll([definedAt]).distinct().filter {
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)
@@ -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('$').toList().dropFirst(1)
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('$').toList().dropFirst(1)
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", [])
@@ -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 = Stack.make()
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().toList()
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)
@@ -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.toArray().map {documentSymbolToLsp(_)})
99
+ .with("children", symbol.children.map {documentSymbolToLsp(_)})
100
100
  }
101
101
 
102
102
  workspaceSymbolToLsp(rootPath: Path, symbol: WorkspaceSymbol): Json {