firefly-compiler 0.4.4 → 0.4.6

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 (98) hide show
  1. package/.hintrc +5 -0
  2. package/README.md +42 -61
  3. package/compiler/Compiler.ff +6 -2
  4. package/compiler/Deriver.ff +10 -0
  5. package/compiler/Environment.ff +2 -1
  6. package/compiler/JsEmitter.ff +29 -17
  7. package/compiler/Resolver.ff +1 -1
  8. package/core/.firefly/package.ff +1 -2
  9. package/core/Box.ff +7 -0
  10. package/core/BuildSystem.ff +5 -4
  11. package/core/Core.ff +4 -0
  12. package/core/HttpClient.ff +1 -1
  13. package/core/JsValue.ff +22 -1
  14. package/core/Lock.ff +4 -4
  15. package/core/NodeSystem.ff +12 -3
  16. package/core/Path.ff +1 -1
  17. package/core/SourceLocation.ff +41 -0
  18. package/core/Stack.ff +6 -6
  19. package/core/StringMap.ff +3 -3
  20. package/lsp/LanguageServer.ff +32 -7
  21. package/lsp/stderr.txt +1 -0
  22. package/lsp/stdin.txt +11 -0
  23. package/lsp/stdout.txt +41 -0
  24. package/lux/.firefly/package.ff +2 -0
  25. package/lux/Lux.ff +473 -0
  26. package/lux/LuxEvent.ff +116 -0
  27. package/lux/Main.ff +126 -0
  28. package/lux/Main2.ff +144 -0
  29. package/meetup/AutoCompletion.ff +6 -0
  30. package/output/js/ff/compiler/Builder.mjs +444 -440
  31. package/output/js/ff/compiler/Compiler.mjs +416 -410
  32. package/output/js/ff/compiler/Dependencies.mjs +389 -385
  33. package/output/js/ff/compiler/Deriver.mjs +1170 -1166
  34. package/output/js/ff/compiler/Dictionaries.mjs +1309 -1305
  35. package/output/js/ff/compiler/Environment.mjs +1015 -1005
  36. package/output/js/ff/compiler/Inference.mjs +4268 -4264
  37. package/output/js/ff/compiler/JsEmitter.mjs +5391 -5353
  38. package/output/js/ff/compiler/JsImporter.mjs +266 -262
  39. package/output/js/ff/compiler/LspHook.mjs +793 -789
  40. package/output/js/ff/compiler/Main.mjs +1699 -1695
  41. package/output/js/ff/compiler/Parser.mjs +4008 -4004
  42. package/output/js/ff/compiler/Patterns.mjs +927 -923
  43. package/output/js/ff/compiler/Resolver.mjs +2307 -2303
  44. package/output/js/ff/compiler/Substitution.mjs +1150 -1146
  45. package/output/js/ff/compiler/Syntax.mjs +12434 -12430
  46. package/output/js/ff/compiler/Token.mjs +3096 -3092
  47. package/output/js/ff/compiler/Tokenizer.mjs +593 -589
  48. package/output/js/ff/compiler/Unification.mjs +1752 -1748
  49. package/output/js/ff/compiler/Wildcards.mjs +608 -604
  50. package/output/js/ff/compiler/Workspace.mjs +687 -683
  51. package/output/js/ff/core/Any.mjs +143 -139
  52. package/output/js/ff/core/Array.mjs +547 -543
  53. package/output/js/ff/core/AssetSystem.mjs +274 -270
  54. package/output/js/ff/core/Atomic.mjs +154 -150
  55. package/output/js/ff/core/Bool.mjs +152 -141
  56. package/output/js/ff/core/Box.mjs +112 -0
  57. package/output/js/ff/core/BrowserSystem.mjs +126 -122
  58. package/output/js/ff/core/Buffer.mjs +395 -391
  59. package/output/js/ff/core/BuildSystem.mjs +296 -290
  60. package/output/js/ff/core/Channel.mjs +189 -185
  61. package/output/js/ff/core/Char.mjs +149 -145
  62. package/output/js/ff/core/Core.mjs +300 -288
  63. package/output/js/ff/core/Duration.mjs +116 -112
  64. package/output/js/ff/core/Equal.mjs +179 -175
  65. package/output/js/ff/core/Error.mjs +142 -138
  66. package/output/js/ff/core/FileHandle.mjs +150 -146
  67. package/output/js/ff/core/Float.mjs +225 -214
  68. package/output/js/ff/core/HttpClient.mjs +190 -186
  69. package/output/js/ff/core/Instant.mjs +109 -105
  70. package/output/js/ff/core/Int.mjs +265 -254
  71. package/output/js/ff/core/IntMap.mjs +280 -276
  72. package/output/js/ff/core/JsSystem.mjs +238 -234
  73. package/output/js/ff/core/JsValue.mjs +714 -664
  74. package/output/js/ff/core/List.mjs +2334 -2321
  75. package/output/js/ff/core/Lock.mjs +230 -226
  76. package/output/js/ff/core/Log.mjs +163 -159
  77. package/output/js/ff/core/Map.mjs +362 -358
  78. package/output/js/ff/core/NodeSystem.mjs +302 -283
  79. package/output/js/ff/core/Nothing.mjs +104 -100
  80. package/output/js/ff/core/Option.mjs +1015 -1002
  81. package/output/js/ff/core/Ordering.mjs +730 -726
  82. package/output/js/ff/core/Pair.mjs +331 -318
  83. package/output/js/ff/core/Path.mjs +546 -542
  84. package/output/js/ff/core/RbMap.mjs +1940 -1936
  85. package/output/js/ff/core/Serializable.mjs +428 -424
  86. package/output/js/ff/core/Set.mjs +254 -250
  87. package/output/js/ff/core/Show.mjs +205 -201
  88. package/output/js/ff/core/SourceLocation.mjs +229 -0
  89. package/output/js/ff/core/Stack.mjs +541 -537
  90. package/output/js/ff/core/Stream.mjs +1304 -1300
  91. package/output/js/ff/core/String.mjs +365 -354
  92. package/output/js/ff/core/StringMap.mjs +280 -276
  93. package/output/js/ff/core/Task.mjs +320 -316
  94. package/output/js/ff/core/Try.mjs +507 -503
  95. package/output/js/ff/core/Unit.mjs +151 -103
  96. package/package.json +29 -29
  97. package/vscode/package-lock.json +5 -5
  98. package/vscode/package.json +1 -1
package/core/Stack.ff CHANGED
@@ -99,32 +99,32 @@ extend self[T]: Stack[T] {
99
99
 
100
100
  fill(value: T, start: Int = 0, end: Int = 9007199254740991): Unit
101
101
  target js sync """
102
- self.array.fill(value_, start, end);
102
+ self_.array.fill(value_, start_, end_);
103
103
  """
104
104
 
105
105
  copy(target: Int, start: Int, end: Int): Unit
106
106
  target js sync """
107
- self.array.copyWithin(target, start, end);
107
+ self_.array.copyWithin(target_, start_, end_);
108
108
  """
109
109
 
110
110
  delete(start: Int, deleteCount: Int): Unit
111
111
  target js sync """
112
- self.array.splice(start, deleteCount_);
112
+ self_.array.splice(start_, deleteCount_);
113
113
  """
114
114
 
115
115
  insert(start: Int, value: T, deleteCount: Int = 0): Unit
116
116
  target js sync """
117
- self.array.splice(start, deleteCount_, value_);
117
+ self_.array.splice(start_, deleteCount_, value_);
118
118
  """
119
119
 
120
120
  insertAll(start: Int, value: Stack[T], deleteCount: Int = 0): Unit
121
121
  target js sync """
122
- self.array.splice(start, deleteCount_, ...value_.array);
122
+ self_.array.splice(start_, deleteCount_, ...value_.array);
123
123
  """
124
124
 
125
125
  insertArray(start: Int, value: Array[T], deleteCount: Int = 0): Unit
126
126
  target js sync """
127
- self.array.splice(start, deleteCount_, ...value_);
127
+ self_.array.splice(start_, deleteCount_, ...value_);
128
128
  """
129
129
 
130
130
  each(body: T => Unit): Unit
package/core/StringMap.ff CHANGED
@@ -32,11 +32,11 @@ extend self[V]: StringMap[V] {
32
32
  size(): Int
33
33
  target js sync "return self_.size"
34
34
 
35
- each(body: (String, V) => Unit): Bool
36
- target js sync "return self_.forEach((v, k) => body_(k, v))"
35
+ each(body: (String, V) => Unit): Unit
36
+ target js sync "self_.forEach((v, k) => body_(k, v))"
37
37
  target js async "for(const [k, v] of self_) await body_(k, v)"
38
38
 
39
- eachWhile(body: (String, V) => Bool): Bool
39
+ eachWhile(body: (String, V) => Bool): Unit
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
 
@@ -17,17 +17,26 @@ capability RequestMessage(
17
17
  parameters: Map[String, JsValue]
18
18
  )
19
19
 
20
+ logMessages = False
20
21
 
21
22
  main(system: NodeSystem) {
23
+ let logDirectory = if(logMessages) {
24
+ let directory = system.path(".").slash("messages")
25
+ if(directory.isDirectory()) {directory.delete()}
26
+ directory.createDirectory()
27
+ directory
28
+ }
29
+
22
30
  let fireflyPath = system.path(".")
23
31
  let handler = Handler(fireflyPath, None, Map.empty(), [].toSet(), Map.empty(), Map.empty())
24
32
  try {
25
33
  mutable input = system.readStream()
26
- let responseChannel: Channel[JsValue] = system.mainTask().channel()
34
+ let responseChannel: Channel[Pair[JsValue, String]] = system.mainTask().channel()
27
35
  system.mainTask().spawn {_ =>
28
36
  while {True} {
29
37
  let body = responseChannel.read()
30
- let json = body.toJson(Some(" ")).toBuffer()
38
+ let json = body.first.toJson(Some(" ")).toBuffer()
39
+ logDirectory.each {logMessage(_, "response", body.first, body.second)}
31
40
  system.writeText("Content-Length: " + json.size() + "\r\n\r\n")
32
41
  system.writeBuffer(json)
33
42
  }
@@ -38,13 +47,14 @@ main(system: NodeSystem) {
38
47
  input = requestPair.second
39
48
  let request = requestPair.first
40
49
  let message = parseRequestMessage(request.object)
50
+ logDirectory.each {logMessage(_, "request", request.object, message.method)}
41
51
  spawn(message.id) {_ =>
42
52
  if(message.method == "$/cancelRequest") {
43
53
  abort(Some(parseMessageId(message.parameters.grab("id"))))
44
54
  }
45
55
  try {
46
56
  handleRequestMessage(system, handler, message).each {body =>
47
- responseChannel.write(body)
57
+ responseChannel.write(Pair(body, message.method))
48
58
  }
49
59
  } catchAny {error =>
50
60
  let problem = if(error.name() == "AbortError") {
@@ -55,7 +65,8 @@ main(system: NodeSystem) {
55
65
  Error(-32603, "Internal error")
56
66
  }
57
67
  message.id.each {id =>
58
- responseChannel.write(makeResponseMessage(system.js(), id, problem))
68
+ let body = makeResponseMessage(system.js(), id, problem)
69
+ responseChannel.write(Pair(body, message.method))
59
70
  }
60
71
  } grab()
61
72
  }
@@ -74,17 +85,17 @@ taskGroup[K: Order, R](
74
85
  mutable tasks = [].toMap()
75
86
  function spawn(key: K, body: Task => Unit): Task {
76
87
  let body2 = {task =>
77
- lock.do {tasks = tasks.add(key, task)}
88
+ lock.do(reentrant = True) {tasks = tasks.add(key, task)}
78
89
  try {
79
90
  body(task)
80
91
  } finally {
81
- lock.do {tasks = tasks.remove(key)}
92
+ lock.do(reentrant = True) {tasks = tasks.remove(key)}
82
93
  } grab()
83
94
  }
84
95
  parentTask.spawn(body2)
85
96
  }
86
97
  function abort(key: K): Unit {
87
- lock.do {tasks.get(key).each {_.abort()}}
98
+ lock.do(reentrant = True) {tasks.get(key).each {_.abort()}}
88
99
  }
89
100
  groupBody(spawn, abort)
90
101
  }
@@ -227,3 +238,17 @@ makeResponseMessage(js: JsSystem, id: MessageId, result: ResultOrError): JsValue
227
238
  }
228
239
  o
229
240
  }
241
+
242
+ logMessage(directory: Path, messageType: String, body: JsValue, method: String) {
243
+ let id = if(method == "$/cancelRequest") {
244
+ Some(body.get("params").get("id").grabInt())
245
+ } else {
246
+ body.getOwn("id").map {_.grabInt()}
247
+ }
248
+ let number = directory.entries().toList().size()
249
+ let idName = id.map {_ + ""}.else {"_"}
250
+ let methodName = method.replace("$", "notification").replace("/", "_")
251
+ let fileName = number + "-id-" + idName + "-" + messageType + "-" + methodName + ".json"
252
+ let path = directory.slash(fileName)
253
+ path.writeText(body.toJson(Some(" ")))
254
+ }
package/lsp/stderr.txt ADDED
@@ -0,0 +1 @@
1
+ End of input while parsing request headers
package/lsp/stdin.txt ADDED
@@ -0,0 +1,11 @@
1
+ Content-Length: 5836
2
+
3
+ {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":43727,"clientInfo":{"name":"Visual Studio Code","version":"1.76.2"},"locale":"en","rootPath":"/Users/ahnfelt/Downloads/firefly-boot","rootUri":"file:///Users/ahnfelt/Downloads/firefly-boot","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"],"failureHandling":"textOnlyTransactional","normalizesLineEndings":true,"changeAnnotationSupport":{"groupsOnLabel":true}},"configuration":true,"didChangeWatchedFiles":{"dynamicRegistration":true,"relativePatternSupport":true},"symbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"tagSupport":{"valueSet":[1]},"resolveSupport":{"properties":["location.range"]}},"codeLens":{"refreshSupport":true},"executeCommand":{"dynamicRegistration":true},"didChangeConfiguration":{"dynamicRegistration":true},"workspaceFolders":true,"semanticTokens":{"refreshSupport":true},"fileOperations":{"dynamicRegistration":true,"didCreate":true,"didRename":true,"didDelete":true,"willCreate":true,"willRename":true,"willDelete":true},"inlineValue":{"refreshSupport":true},"inlayHint":{"refreshSupport":true},"diagnostics":{"refreshSupport":true}},"textDocument":{"publishDiagnostics":{"relatedInformation":true,"versionSupport":false,"tagSupport":{"valueSet":[1,2]},"codeDescriptionSupport":true,"dataSupport":true},"synchronization":{"dynamicRegistration":true,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":true,"contextSupport":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":true,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":true,"preselectSupport":true,"tagSupport":{"valueSet":[1]},"insertReplaceSupport":true,"resolveSupport":{"properties":["documentation","detail","additionalTextEdits"]},"insertTextModeSupport":{"valueSet":[1,2]},"labelDetailsSupport":true},"insertTextMode":2,"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]},"completionList":{"itemDefaults":["commitCharacters","editRange","insertTextFormat","insertTextMode"]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"],"parameterInformation":{"labelOffsetSupport":true},"activeParameterSupport":true},"contextSupport":true},"definition":{"dynamicRegistration":true,"linkSupport":true},"references":{"dynamicRegistration":true},"documentHighlight":{"dynamicRegistration":true},"documentSymbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"hierarchicalDocumentSymbolSupport":true,"tagSupport":{"valueSet":[1]},"labelSupport":true},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"disabledSupport":true,"dataSupport":true,"resolveSupport":{"properties":["edit"]},"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"honorsChangeAnnotations":false},"codeLens":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"onTypeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true,"prepareSupportDefaultBehavior":1,"honorsChangeAnnotations":true},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"typeDefinition":{"dynamicRegistration":true,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"colorProvider":{"dynamicRegistration":true},"foldingRange":{"dynamicRegistration":true,"rangeLimit":5000,"lineFoldingOnly":true,"foldingRangeKind":{"valueSet":["comment","imports","region"]},"foldingRange":{"collapsedText":false}},"declaration":{"dynamicRegistration":true,"linkSupport":true},"selectionRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":true},"semanticTokens":{"dynamicRegistration":true,"tokenTypes":["namespace","type","class","enum","interface","struct","typeParameter","parameter","variable","property","enumMember","event","function","method","macro","keyword","modifier","comment","string","number","regexp","operator","decorator"],"tokenModifiers":["declaration","definition","readonly","static","deprecated","abstract","async","modification","documentation","defaultLibrary"],"formats":["relative"],"requests":{"range":true,"full":{"delta":true}},"multilineTokenSupport":false,"overlappingTokenSupport":false,"serverCancelSupport":true,"augmentsSyntaxTokens":true},"linkedEditingRange":{"dynamicRegistration":true},"typeHierarchy":{"dynamicRegistration":true},"inlineValue":{"dynamicRegistration":true},"inlayHint":{"dynamicRegistration":true,"resolveSupport":{"properties":["tooltip","textEdits","label.tooltip","label.location","label.command"]}},"diagnostic":{"dynamicRegistration":true,"relatedDocumentSupport":false}},"window":{"showMessage":{"messageActionItem":{"additionalPropertiesSupport":true}},"showDocument":{"support":true},"workDoneProgress":true},"general":{"staleRequestSupport":{"cancel":true,"retryOnContentModified":["textDocument/semanticTokens/full","textDocument/semanticTokens/range","textDocument/semanticTokens/full/delta"]},"regularExpressions":{"engine":"ECMAScript","version":"ES2020"},"markdown":{"parser":"marked","version":"1.1.0"},"positionEncodings":["utf-16"]},"notebookDocument":{"synchronization":{"dynamicRegistration":true,"executionSummarySupport":true}}},"trace":"off","workspaceFolders":[{"uri":"file:///Users/ahnfelt/Downloads/firefly-boot","name":"firefly-boot"}]}}Content-Length: 52
4
+
5
+ {"jsonrpc":"2.0","method":"initialized","params":{}}Content-Length: 9421
6
+
7
+ {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///Users/ahnfelt/Downloads/firefly-boot/lsp/LanguageServer.ff","languageId":"firefly","version":1,"text":"class LanguageServer(\n mutable openFiles: Map[String, String]\n)\n\ndata BadRequestException(reason: String)\n\ncapability Request(\n headers: Map[String, String]\n object: JsValue\n)\n\ncapability RequestMessage(\n id: Option[MessageId] // None when the request is a Notification Message\n method: String\n parameters: Map[String, JsValue]\n)\n\ndata MessageId {\n MessageIdInt(id: Int)\n MessageIdString(id: String)\n}\n\ncapability ResultOrError {\n Result(result: JsValue)\n Error(code: Int, message: String)\n}\n\n\nmain(system: NodeSystem) {\n try {\n mutable input = system.readStream()\n while {True} {\n let requestPair = parseRequest(system, input)\n input = requestPair.second\n let request = requestPair.first\n let message = parseRequestMessage(request.object)\n handleRequestMessage(system.js(), message).each {body =>\n system.writeText(makeResponse(body))\n }\n //system.writeText(makeResponse(makeDiagnoseNotification(system.js())))\n }\n } catch {| BadRequestException(reason), error =>\n system.writeErrorText(reason + \"\\n\")\n } grab()\n}\n \nparseRequest(system: NodeSystem, input: Stream[Buffer]): Pair[Request, Stream[Buffer]] {\n let headersPair = parseRequestHeaders(input)\n let headers = headersPair.first\n let contentLength = headers\n .get(\"content-length\").else {throw(BadRequestException(\"'content-length' header is missing\"))}\n .getInt().else {throw(BadRequestException(\"Value for 'content-length' is not an integer\"))}\n let bodyPair = parseRequestBody(system.js(), contentLength, headersPair.second)\n bodyPair.mapFirst {body => Request(headers, body)}\n}\n\nparseRequestHeaders(input: Stream[Buffer]): Pair[Map[String, String], Stream[Buffer]] {\n let buffers = Stack.make()\n mutable buffer = input.next().else {\n throw(BadRequestException(\"End of input while parsing request headers\"))\n }\n mutable offset = 0\n mutable droppingInitialNewlines = True\n mutable lastWasNewline = False\n mutable done = False\n while {!done} {\n if(offset == buffer.size()) {\n offset = 0\n buffers.push(buffer)\n buffer = input.next().else {\n throw(BadRequestException(\"End of input while parsing request headers\"))\n }\n }\n let byte = buffer.grabUint8(offset)\n if(droppingInitialNewlines && (byte == '\\n'.codeUnit || byte == '\\r'.codeUnit)) {\n // Skip\n } elseIf {byte == '\\n'.codeUnit} {\n if(lastWasNewline) {\n done = True\n } else {\n lastWasNewline = True\n }\n } elseIf {byte != '\\r'.codeUnit && lastWasNewline} {\n lastWasNewline = False\n } else {\n droppingInitialNewlines = False\n }\n offset += 1\n }\n buffers.push(buffer.view(0, offset))\n let headers = Buffer.fromBufferArray(buffers.drain()).toString()\n let map = headers.lines().pairs().filter {_.second.size() != 0}.map {| Pair(i, line) =>\n line.splitFirst(':').else {\n throw(BadRequestException(\"Invalid header at line \" + i + \" '\" + line + \"'\"))\n }.mapFirst {_.lower()} //.mapSecond {_.trim()}\n }.toMap()\n Pair(map, [buffer.view(offset, buffer.size())].toStream().addAll(input))\n}\n\nparseRequestBody(js: JsSystem, contentLength: Int, input: Stream[Buffer]): Pair[JsValue, Stream[Buffer]] {\n let bodyPair = try {\n input.readBytes(contentLength) // Should Stream.readBytes return an option?\n } catchAny {error =>\n throw(BadRequestException(\"End of input while parsing request body\"))\n } grab()\n let body = Buffer.fromBufferArray(bodyPair.first).toString()\n let json = try {\n js.parseJson(body)\n } catchAny {error =>\n throw(BadRequestException(\"Invalid JSON in request body: \" + body))\n } grab()\n Pair(json, bodyPair.second)\n}\n\nparseRequestMessage(object: JsValue): RequestMessage {\n let id = object.getOwn(\"id\").map {id =>\n if(id.isInt()) {\n MessageIdInt(id.grabInt())\n } elseIf {id.isString()} {\n MessageIdString(id.grabString())\n } else {\n throw(BadRequestException(\"Bad JSON-RPC id, int or string expected\"))\n }\n }\n\n let method = object.getOwn(\"method\").{\n | None => throw(BadRequestException(\"Bad JSON-RPC, missing method\"))\n | Some(m) {!m.isString()} => throw(BadRequestException(\"Bad JSON-RPC method, string expected\"))\n | Some(m) => m.grabString()\n }\n\n let parameters = object.getOwn(\"params\").{\n | None => [].toMap()\n | Some(o) {!o.isObject()} => throw(BadRequestException(\"Bad JSON-RPC params, object expected\"))\n | Some(o) => o.grabMap()\n }\n\n RequestMessage(id, method, parameters)\n}\n\nhandleRequestMessage(js: JsSystem, message: RequestMessage): Option[JsValue] {\n message.id.{\n // Notification Message\n | None =>\n message.method.{\n | \"initialized\" =>\n | _ =>\n }\n None\n // Request Message\n | Some(id) =>\n let result = message.method.{\n | \"initialize\" => handleInitialize(js, message.parameters)\n | \"textDocument/diagnostic\" => handleDiagnostic(js, message.parameters)\n | \"hover\" => handleHover(js, message.parameters)\n | _ => handleUnsupported(js)\n }\n Some(makeResponseMessage(js, id, result))\n }\n}\n\nmakeResponse(body: JsValue): String {\n let json = body.toJson(Some(\" \"))\n let length = json.size()\n \"Content-Length: \" + length + \"\\r\\n\" +\n \"\\r\\n\" +\n json\n}\n\nmakeResponseMessage(js: JsSystem, id: MessageId, result: ResultOrError): JsValue {\n let o = js.object()\n o.set(\"jsonrpc\", \"2.0\")\n id.{\n | MessageIdInt(id) => o.set(\"id\", id)\n | MessageIdString(id) => o.set(\"id\", id)\n }\n result.{\n | Result(result) =>\n o.set(\"result\", result)\n | Error(code, message) =>\n let e = js.object()\n e.set(\"code\", code)\n e.set(\"message\", message)\n o.set(\"error\", e)\n }\n o\n}\n\nhandleUnsupported(js: JsSystem): ResultOrError {\n Error(1234, \"Unsupported method\")\n}\n\nhandleInitialize(js: JsSystem, parameters: Map[String, JsValue]): ResultOrError {\n let anyFireflyFile = js.object()\n .with(\"filters\", [\n js.object()\n .with(\"pattern\", js.object()\n .with(\"glob\", \"**/*.ff\")\n .with(\"matches\", \"file\")\n )\n ].toArray())\n\n let o = js.object()\n .with(\"capabilities\", js.object()\n .with(\"textDocumentSync\", js.object()\n .with(\"openClose\", True)\n .with(\"change\", 1 /* TextDocumentSyncKind.Full */)\n )\n .with(\"hoverProvider\", False)\n //.with(\"definitionProvider\", True)\n //.with(\"typeDefinitionProvider\", True)\n .with(\"diagnosticProvider\", js.object()\n .with(\"interFileDependencies\", True)\n .with(\"workspaceDiagnostics\", False)\n )\n /*.with(\"workspace\", js.object()\n .with(\"workspaceFolders\", js.object()\n .with(\"supported\", True)\n .with(\"changeNotifications\", True)\n )\n .with(\"fileOperations\", js.object()\n .with(\"didCreate\", anyFireflyFile)\n .with(\"didRename\", anyFireflyFile)\n .with(\"didDelete\", anyFireflyFile)\n )\n )*/\n )\n .with(\"serverInfo\", js.object()\n .with(\"name\", \"Firefly Language Server\")\n .with(\"version\", \"0.0.0\")\n )\n Result(o)\n}\n\nhandleDiagnostic(js: JsSystem, parameters: Map[String, JsValue]): ResultOrError {\n let diagnostic = js.object()\n .with(\"range\", js.object()\n .with(\"start\", js.object()\n .with(\"line\", 0).with(\"character\", 6)\n )\n .with(\"end\", js.object()\n .with(\"line\", 0).with(\"character\", 20)\n )\n )\n .with(\"severity\", 1 /* Error */)\n .with(\"message\", \"Hurray!\")\n\n let o = js.object()\n .with(\"kind\", \"full\")\n .with(\"items\", [/*diagnostic*/].toArray())\n\n Result(o)\n}\n\nhandleHover(js: JsSystem, parameters: Map[String, JsValue]): ResultOrError {\n let o = js.object().with(\"contents\", \"TODO\")\n Result(o)\n}\n\nmakeNotificationMessage(js: JsSystem, method: String, params: JsValue): JsValue {\n js.object()\n .with(\"jsonrpc\", \"2.0\")\n .with(\"method\", method)\n .with(\"params\", params)\n}\n"}}}Content-Length: 162
8
+
9
+ {"jsonrpc":"2.0","id":1,"method":"textDocument/diagnostic","params":{"textDocument":{"uri":"file:///Users/ahnfelt/Downloads/firefly-boot/lsp/LanguageServer.ff"}}}Content-Length: 44
10
+
11
+ {"jsonrpc":"2.0","id":2,"method":"shutdown"}
package/lsp/stdout.txt ADDED
@@ -0,0 +1,41 @@
1
+ Content-Length: 500
2
+
3
+ {
4
+ "jsonrpc": "2.0",
5
+ "id": 0,
6
+ "result": {
7
+ "capabilities": {
8
+ "textDocumentSync": {
9
+ "openClose": true,
10
+ "change": 1
11
+ },
12
+ "hoverProvider": false,
13
+ "diagnosticProvider": {
14
+ "interFileDependencies": true,
15
+ "workspaceDiagnostics": false
16
+ }
17
+ },
18
+ "serverInfo": {
19
+ "name": "Firefly Language Server",
20
+ "version": "0.0.0"
21
+ }
22
+ }
23
+ }Content-Length: 104
24
+
25
+ {
26
+ "jsonrpc": "2.0",
27
+ "id": 1,
28
+ "result": {
29
+ "kind": "full",
30
+ "items": []
31
+ }
32
+ }Content-Length: 121
33
+
34
+ {
35
+ "jsonrpc": "2.0",
36
+ "id": 2,
37
+ "error": {
38
+ "code": 1234,
39
+ "message": "Unsupported method"
40
+ }
41
+ }
@@ -0,0 +1,2 @@
1
+ dependency ff:httpserver:0.0.0
2
+ package ff:lux:0.0.0