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/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 {
@@ -748,8 +748,8 @@ toplevelCompletion(lspHook: LspHook): List[CompletionInfo] {
748
748
  label = "webapp",
749
749
  extra = " with frontend and backend",
750
750
  snippet = [
751
- "dependency ff:httpserver:0.0.0"
752
- "import HttpServer from ff:httpserver"
751
+ "dependency ff:webserver:0.0.0"
752
+ "import WebServer from ff:webserver"
753
753
  ""
754
754
  "browserMain(system: BrowserSystem): Unit {"
755
755
  " let response = system.httpClient().fetch(\"http://localhost:8080/hello\")"
@@ -758,19 +758,19 @@ toplevelCompletion(lspHook: LspHook): List[CompletionInfo] {
758
758
  "}"
759
759
  ""
760
760
  "nodeMain(system: NodeSystem): Unit {"
761
- " HttpServer.listen(system, \"localhost\", 8080) {request, response =>"
762
- " if(request.path() == \"/\") {"
763
- " response.setHeader(\"Content-Type\", [\"text/html; charset=UTF-8\"])"
764
- " response.writeText(\"<!doctype html>\")"
765
- " response.writeText(\"<script type='module' src='/js/script/script/WebApp.mjs'></script>\")"
766
- " } elseIf {request.path() == \"/hello\"} {"
767
- " response.setHeader(\"Content-Type\", [\"text/plain; charset=UTF-8\"])"
768
- " response.writeText(\"Hello from server!\")"
769
- " } elseIf {request.path().startsWith(\"/js/\") && !request.path().contains(\"..\")} {"
770
- " response.setHeader(\"Content-Type\", [\"text/javascript; charset=UTF-8\"])"
771
- " response.writeText(system.assets().readText(request.path()))"
761
+ " WebServer.make(system, \"localhost\", 8080).listen {request =>"
762
+ " if(request.readPath() == \"/\") {"
763
+ " request.writeHeader(\"Content-Type\", \"text/html; charset=UTF-8\")"
764
+ " request.writeText(\"<!doctype html>\")"
765
+ " request.writeText(\"<script type='module' src='/js/script/script/WebApp.mjs'></script>\")"
766
+ " } elseIf {request.readPath() == \"/hello\"} {"
767
+ " request.writeHeader(\"Content-Type\", \"text/plain; charset=UTF-8\")"
768
+ " request.writeText(\"Hello from server!\")"
769
+ " } elseIf {request.readPath().startsWith(\"/js/\") && !request.readPath().contains(\"..\")} {"
770
+ " request.writeHeader(\"Content-Type\", \"text/javascript; charset=UTF-8\")"
771
+ " request.writeText(system.assets().readText(request.readPath()))"
772
772
  " } else {"
773
- " response.writeStatus(404, Some(\"Not found\"))"
773
+ " request.writeStatus(\"404 Not found\")"
774
774
  " }"
775
775
  " }"
776
776
  "}"
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] {
@@ -270,14 +280,14 @@ extend self: Handler {
270
280
  let documentSymbols = self.getDocumentSymbolsWithCache(system, file)
271
281
  let workspaceSymbols = documentSymbols.flatMap {SymbolHandler.documentToWorkspaceSymbols(_, None)}
272
282
  if(query == "") {
273
- workspaceSymbols.filter {_.kind == 5} // Class
283
+ workspaceSymbols.filter {_.kind == SType}
274
284
  } else {
275
285
  workspaceSymbols.filter {SymbolHandler.symbolFilter(_, query)}
276
286
  }
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)
@@ -3,7 +3,7 @@ import Syntax from ff:compiler
3
3
 
4
4
  data DocumentSymbol(
5
5
  name: String
6
- kind: Int
6
+ kind: DocumentSymbolKind
7
7
  selectionStart: Location
8
8
  selectionEnd: Location
9
9
  start: Location
@@ -13,7 +13,7 @@ data DocumentSymbol(
13
13
 
14
14
  data WorkspaceSymbol(
15
15
  name: String
16
- kind: Int
16
+ kind: DocumentSymbolKind
17
17
  containerName: Option[String]
18
18
  selectionStart: Location
19
19
  selectionEnd: Location
@@ -93,16 +93,30 @@ showPosition(at: Location): String {
93
93
  documentSymbolToLsp(symbol: DocumentSymbol): Json {
94
94
  Json.object()
95
95
  .with("name", symbol.name)
96
- .with("kind", symbol.kind)
96
+ .with("kind", documentSymbolNumber(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
+ }
101
+
102
+ documentSymbolNumber(kind: DocumentSymbolKind): Int {
103
+ | SExtend => 3 // Namespace
104
+ | SFunction(True) => 6
105
+ | SFunction(False) => 12
106
+ | SInstance => 19 // Object
107
+ | SLet(True) => 13
108
+ | SLet(False) => 14
109
+ | SParameter => 7 // Property
110
+ | STrait => 11 // Interface
111
+ | STraitFunction => 12 // Function
112
+ | SType => 5
113
+ | SVariant => 10 // Enum
100
114
  }
101
115
 
102
116
  workspaceSymbolToLsp(rootPath: Path, symbol: WorkspaceSymbol): Json {
103
117
  let o = Json.object()
104
118
  .with("name", symbol.name)
105
- .with("kind", symbol.kind)
119
+ .with("kind", documentSymbolNumber(symbol.kind))
106
120
  .with("location", Json.object()
107
121
  .with("uri", rootPath.path(symbol.selectionStart.file).url())
108
122
  .with("range", locationsToLspRange(symbol.selectionStart, symbol.selectionEnd))
package/lux/Lux.ff CHANGED
@@ -8,7 +8,7 @@ capability Lux(
8
8
  mutable cssClasses: StringMap[CssClass]
9
9
  mutable renderLock: Lock
10
10
  mutable task: Task
11
- mutable renderQueue: Stack[RenderQueueItem]
11
+ mutable renderQueue: Array[RenderQueueItem]
12
12
  mutable element: LuxElement
13
13
  mutable depth: Int
14
14
  mutable keys: Option[StringMap[JsValue]]
@@ -294,7 +294,7 @@ extend self: Lux {
294
294
  let lux = luxCopy.Lux(
295
295
  task = task
296
296
  renderLock = task.lock()
297
- renderQueue = Stack.make()
297
+ renderQueue = Array.make()
298
298
  element = luxCopy.element.LuxElement(element = fragment)
299
299
  )
300
300
  try {
@@ -475,7 +475,7 @@ render(browserSystem: BrowserSystem, element: JsValue, body: Lux => Unit) {
475
475
  keys = None
476
476
  key = ""
477
477
  attributes = None
478
- renderQueue = Stack.make()
478
+ renderQueue = Array.make()
479
479
  )
480
480
  lux.renderLock.do(reentrant = False) {
481
481
  body(lux)