firefly-compiler 0.4.46 → 0.4.49
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/bin/Release.ff +79 -24
- package/core/List.ff +71 -0
- package/lsp/CompletionHandler.ff +7 -10
- package/lsp/stdin.txt +10 -10
- package/lsp/stdout.txt +6 -6
- package/output/js/ff/core/List.mjs +146 -0
- package/package.json +1 -1
- package/s3/S3.ff +2 -2
- package/vscode/package.json +1 -1
package/bin/Release.ff
CHANGED
|
@@ -16,51 +16,103 @@ release(
|
|
|
16
16
|
accessKeyId: String
|
|
17
17
|
secretAccessKey: String
|
|
18
18
|
): Unit {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
if(!system.path("Release.ff").isFile()) {
|
|
20
|
+
system.writeErrorLine("You need to be in the directory of Release.ff")
|
|
21
|
+
system.exit(1)
|
|
22
|
+
}
|
|
23
|
+
requireNpmLoggedIn(system, system.path(".."))
|
|
24
|
+
requireVsceLoggedIn(system, system.path("../vscode"))
|
|
25
|
+
runSuccessful(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
|
|
26
|
+
runSuccessful(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
|
|
27
|
+
runSuccessful(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
|
|
28
|
+
let version = bumpMinorVersion(system, system.path("../package.json"))
|
|
23
29
|
bumpMinorVersion(system, system.path("../vscode/package.json"))
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
runSuccessful(system, "npm", ["publish"], system.path(".."))
|
|
31
|
+
runSuccessful(system, "vsce", ["publish"], system.path("../vscode"))
|
|
32
|
+
releaseFireflyPackage(system, accessKeyId, secretAccessKey, "compiler")
|
|
33
|
+
releaseFireflyPackage(system, accessKeyId, secretAccessKey, "core")
|
|
34
|
+
releaseFireflyPackage(system, accessKeyId, secretAccessKey, "lux")
|
|
35
|
+
releaseFireflyPackage(system, accessKeyId, secretAccessKey, "postgresql")
|
|
36
|
+
releaseFireflyPackage(system, accessKeyId, secretAccessKey, "rpc")
|
|
37
|
+
releaseFireflyPackage(system, accessKeyId, secretAccessKey, "s3")
|
|
38
|
+
releaseFireflyPackage(system, accessKeyId, secretAccessKey, "unsafejs")
|
|
39
|
+
releaseFireflyPackage(system, accessKeyId, secretAccessKey, "webserver")
|
|
40
|
+
runSuccessful(system, "git", ["commit", "-a", "-m", "Autorelease " + version], system.path(".."))
|
|
41
|
+
runSuccessful(system, "git", ["push"], system.path(".."))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
releaseFireflyPackage(
|
|
45
|
+
system: NodeSystem
|
|
46
|
+
accessKeyId: String
|
|
47
|
+
secretAccessKey: String
|
|
48
|
+
packageName: String
|
|
49
|
+
): Unit {
|
|
50
|
+
let temporary = system.path("../" + packageName + "/.firefly/temporary")
|
|
51
|
+
if(!temporary.exists()) {temporary.createDirectory()}
|
|
52
|
+
let tarGz = temporary.slash("ff_" + packageName + "_0_0_0.tar.gz")
|
|
53
|
+
if(tarGz.exists()) {
|
|
54
|
+
tarGz.delete()
|
|
55
|
+
system.writeLine("Deleted " + tarGz.absolute())
|
|
32
56
|
}
|
|
33
|
-
internalMakeTarGz(
|
|
34
|
-
system.writeLine("Created " +
|
|
57
|
+
internalMakeTarGz(tarGz, system.path("../" + packageName))
|
|
58
|
+
system.writeLine("Created " + tarGz.absolute())
|
|
35
59
|
S3.put(
|
|
36
60
|
system
|
|
37
61
|
accessKeyId
|
|
38
62
|
secretAccessKey
|
|
39
63
|
"eu-central-1"
|
|
40
64
|
"firefly-site"
|
|
41
|
-
"site/packages/ff/
|
|
42
|
-
|
|
65
|
+
"site/packages/ff/" + packageName + "/" + tarGz.base()
|
|
66
|
+
tarGz.readBuffer()
|
|
43
67
|
headers = [
|
|
44
68
|
Pair("Content-Type", "application/x-gzip")
|
|
45
69
|
]
|
|
46
70
|
)
|
|
47
71
|
}
|
|
48
72
|
|
|
49
|
-
|
|
73
|
+
requireNpmLoggedIn(system: NodeSystem, workingDirectory: Path) {
|
|
74
|
+
let out = run(system, "npm", ["whoami"], workingDirectory)
|
|
75
|
+
if(out.exitCode != 0) {
|
|
76
|
+
system.writeErrorLine("")
|
|
77
|
+
system.writeErrorLine("You are not logged into npm")
|
|
78
|
+
system.writeErrorLine("Run 'npm adduser'")
|
|
79
|
+
system.exit(1)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
requireVsceLoggedIn(system: NodeSystem, workingDirectory: Path) {
|
|
84
|
+
let out = runSuccessful(system, "vsce", ["ls-publishers"], workingDirectory)
|
|
85
|
+
if(!out.toString().lines().any {_ == "firefly-team"}) {
|
|
86
|
+
system.writeErrorLine("")
|
|
87
|
+
system.writeErrorLine("You are not logged into vsce")
|
|
88
|
+
system.writeErrorLine("Manage firefly-team users here https://marketplace.visualstudio.com/manage/publishers/firefly-team")
|
|
89
|
+
system.writeErrorLine("Run 'vsce login firefly-team'")
|
|
90
|
+
system.writeErrorLine("Get a new token here https://dev.azure.com/firefly-lang/_usersSettings/tokens")
|
|
91
|
+
system.exit(1)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
run(system: NodeSystem, command: String, arguments: List[String], workingDirectory: Path): ProcessResult {
|
|
50
96
|
system.writeLine("")
|
|
51
97
|
system.writeLine(command + " " + arguments.join(" "))
|
|
52
98
|
let out = system.execute(command, arguments, workingDirectory = Some(workingDirectory))
|
|
53
99
|
system.writeBuffer(out.standardOut)
|
|
54
100
|
system.writeErrorBuffer(out.standardError)
|
|
101
|
+
out
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
runSuccessful(system: NodeSystem, command: String, arguments: List[String], workingDirectory: Path): Buffer {
|
|
105
|
+
let out = run(system, command, arguments, workingDirectory)
|
|
55
106
|
if(out.exitCode != 0) {
|
|
56
107
|
system.writeErrorLine("Exit code: " + out.exitCode)
|
|
57
108
|
system.exit(1)
|
|
58
109
|
}
|
|
110
|
+
out.standardOut
|
|
59
111
|
}
|
|
60
112
|
|
|
61
|
-
bumpMinorVersion(system: NodeSystem, packageJsonPath: Path) {
|
|
113
|
+
bumpMinorVersion(system: NodeSystem, packageJsonPath: Path): String {
|
|
62
114
|
let prefix = " \"version\": \""
|
|
63
|
-
mutable
|
|
115
|
+
mutable newVersions = []
|
|
64
116
|
system.writeLine("")
|
|
65
117
|
system.writeLine("Bumping version in " + packageJsonPath.absolute())
|
|
66
118
|
let newContent = packageJsonPath.readText().lines().map {
|
|
@@ -71,18 +123,21 @@ bumpMinorVersion(system: NodeSystem, packageJsonPath: Path) {
|
|
|
71
123
|
} {
|
|
72
124
|
patch.getInt() | Some(p)
|
|
73
125
|
} =>
|
|
74
|
-
bumps += 1
|
|
75
126
|
let newVersion = major + "." + minor + "." + (p + 1)
|
|
127
|
+
newVersions = [...newVersions, newVersion]
|
|
76
128
|
system.writeLine("Will bump version: " + v + " to " + newVersion)
|
|
77
129
|
prefix + newVersion + "\","
|
|
78
130
|
| line =>
|
|
79
131
|
line
|
|
80
132
|
}.join("\n")
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
133
|
+
newVersions.{
|
|
134
|
+
| [newVersion] =>
|
|
135
|
+
packageJsonPath.writeText(newContent)
|
|
136
|
+
newVersion
|
|
137
|
+
| _ =>
|
|
138
|
+
system.writeErrorLine("Failed to bump version.")
|
|
139
|
+
system.exit(1)
|
|
84
140
|
}
|
|
85
|
-
packageJsonPath.writeText(newContent)
|
|
86
141
|
}
|
|
87
142
|
|
|
88
143
|
internalMakeTarGz(tarGzPath: Path, path: Path): Unit
|
package/core/List.ff
CHANGED
|
@@ -69,7 +69,63 @@ extend self[T]: List[T] {
|
|
|
69
69
|
|
|
70
70
|
dropLast(count: Int = 1): List[T]
|
|
71
71
|
target js sync "return self_.slice(0, self_.length - count_)"
|
|
72
|
+
|
|
73
|
+
count(body: T => Bool): Int {
|
|
74
|
+
mutable result = 0
|
|
75
|
+
mutable i = 0
|
|
76
|
+
while {i < self.size()} {
|
|
77
|
+
if(body(self.grab(i))) {result += 1}
|
|
78
|
+
i += 1
|
|
79
|
+
}
|
|
80
|
+
result
|
|
81
|
+
}
|
|
72
82
|
|
|
83
|
+
countWhile(body: T => Bool): Int {
|
|
84
|
+
mutable i = 0
|
|
85
|
+
while {i < self.size() && body(self.grab(i))} {
|
|
86
|
+
i += 1
|
|
87
|
+
}
|
|
88
|
+
i
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
takeWhile(body: T => Bool): List[T] {
|
|
92
|
+
let result = Array.new()
|
|
93
|
+
mutable i = 0
|
|
94
|
+
while {i < self.size() && body(self.grab(i))} {
|
|
95
|
+
result.push(self.grab(i))
|
|
96
|
+
i += 1
|
|
97
|
+
}
|
|
98
|
+
result.drain()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
dropWhile(body: T => Bool): List[T] {
|
|
102
|
+
let result = Array.new()
|
|
103
|
+
mutable i = 0
|
|
104
|
+
while {i < self.size() && body(self.grab(i))} {
|
|
105
|
+
i += 1
|
|
106
|
+
}
|
|
107
|
+
while {i < self.size()} {
|
|
108
|
+
result.push(self.grab(i))
|
|
109
|
+
i += 1
|
|
110
|
+
}
|
|
111
|
+
result.drain()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
partitionWhile(body: T => Bool): Pair[List[T], List[T]] {
|
|
115
|
+
let first = Array.new()
|
|
116
|
+
let second = Array.new()
|
|
117
|
+
mutable i = 0
|
|
118
|
+
while {i < self.size() && body(self.grab(i))} {
|
|
119
|
+
first.push(self.grab(i))
|
|
120
|
+
i += 1
|
|
121
|
+
}
|
|
122
|
+
while {i < self.size()} {
|
|
123
|
+
second.push(self.grab(i))
|
|
124
|
+
i += 1
|
|
125
|
+
}
|
|
126
|
+
Pair(first.drain(), second.drain())
|
|
127
|
+
}
|
|
128
|
+
|
|
73
129
|
pairs(): List[Pair[Int, T]] {
|
|
74
130
|
mutable i = 0
|
|
75
131
|
self.map {x =>
|
|
@@ -197,6 +253,21 @@ extend self[T]: List[T] {
|
|
|
197
253
|
}
|
|
198
254
|
result
|
|
199
255
|
}
|
|
256
|
+
|
|
257
|
+
indexWhere(body: T => Bool): Option[Int] {
|
|
258
|
+
mutable result = None
|
|
259
|
+
mutable i = 0
|
|
260
|
+
self.eachWhile {x =>
|
|
261
|
+
if(body(x)) {
|
|
262
|
+
result = Some(i)
|
|
263
|
+
False
|
|
264
|
+
} else {
|
|
265
|
+
i += 1
|
|
266
|
+
True
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
result
|
|
270
|
+
}
|
|
200
271
|
|
|
201
272
|
find(body: T => Bool): Option[T] {
|
|
202
273
|
mutable result = None
|
package/lsp/CompletionHandler.ff
CHANGED
|
@@ -75,7 +75,7 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
|
|
|
75
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
|
-
CompletionInfo(name, "", name, True, t2, "(
|
|
78
|
+
CompletionInfo(name, "", name, True, t2, "(...)." + name + ": " + t2.show([]), Some(h.expected))
|
|
79
79
|
}
|
|
80
80
|
[...fieldCompletions, ...completion(h.unification, h.environment, n, None, h.expected)]
|
|
81
81
|
| InferArgumentHook h {
|
|
@@ -327,7 +327,7 @@ makeCompletion(
|
|
|
327
327
|
}
|
|
328
328
|
}.toStream().takeWhile {_ != None}.collect {_}.toList().reverse()
|
|
329
329
|
let allRequired = realParameters.filter {_.default.isEmpty()}
|
|
330
|
-
let required =
|
|
330
|
+
let required = allRequired.dropLast(trailing.size()).map {_.name}
|
|
331
331
|
let optional = if(allRequired.size() != realParameters.size()) {"..."}
|
|
332
332
|
Pair(
|
|
333
333
|
if(trailing.isEmpty() || !required.isEmpty()) {
|
|
@@ -351,7 +351,7 @@ makeCompletion(
|
|
|
351
351
|
let methodGenerics = memberScheme.signature.generics
|
|
352
352
|
let generics = if(member || methodGenerics.isEmpty()) {""} else {"[" + methodGenerics.join(", ") + "]"}
|
|
353
353
|
let beforeAfter = memberScheme.signature.parameters.first().map {
|
|
354
|
-
Pair(unification.substitute(_.valueType).show([]) + "
|
|
354
|
+
Pair(unification.substitute(_.valueType).show([]) + ".", "")
|
|
355
355
|
}.else {Pair("", "")}
|
|
356
356
|
beforeAfter.first +
|
|
357
357
|
if(memberScheme.isMutable) {"mutable "} else {""} +
|
|
@@ -372,17 +372,14 @@ makeCompletion(
|
|
|
372
372
|
let methodGenerics = memberScheme.signature.generics.filter {_ != "Q$"}
|
|
373
373
|
if(methodGenerics.isEmpty()) {""} else {"[" + methodGenerics.join(", ") + "]"}
|
|
374
374
|
}
|
|
375
|
-
let selfIndent = selfType.map {_ => " "}.else {""}
|
|
376
375
|
let parameters = if(realParameters.isEmpty()) {""} else {
|
|
377
376
|
"\n" + realParameters.map {p =>
|
|
378
|
-
showCompletionParameter(
|
|
379
|
-
}.join("\n") + "\n"
|
|
377
|
+
showCompletionParameter(" ", p)
|
|
378
|
+
}.join("\n") + "\n"
|
|
380
379
|
}
|
|
381
|
-
selfType.map {_.show([])
|
|
382
|
-
selfIndent + unqualifiedName +
|
|
380
|
+
selfType.map {_.show([]) + "."}.else {""} + unqualifiedName +
|
|
383
381
|
generics + "(" + parameters + "): " +
|
|
384
|
-
returnType.show([])
|
|
385
|
-
selfType.map {_ => "\n}"}.else {""}
|
|
382
|
+
returnType.show([])
|
|
386
383
|
}
|
|
387
384
|
CompletionInfo(
|
|
388
385
|
label = shortName
|
package/lsp/stdin.txt
CHANGED
|
@@ -1,11 +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
|
-
|
|
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
11
|
{"jsonrpc":"2.0","id":2,"method":"shutdown"}
|
package/lsp/stdout.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
Content-Length: 500
|
|
2
|
-
|
|
1
|
+
Content-Length: 500
|
|
2
|
+
|
|
3
3
|
{
|
|
4
4
|
"jsonrpc": "2.0",
|
|
5
5
|
"id": 0,
|
|
@@ -20,8 +20,8 @@ Content-Length: 500
|
|
|
20
20
|
"version": "0.0.0"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
}Content-Length: 104
|
|
24
|
-
|
|
23
|
+
}Content-Length: 104
|
|
24
|
+
|
|
25
25
|
{
|
|
26
26
|
"jsonrpc": "2.0",
|
|
27
27
|
"id": 1,
|
|
@@ -29,8 +29,8 @@ Content-Length: 500
|
|
|
29
29
|
"kind": "full",
|
|
30
30
|
"items": []
|
|
31
31
|
}
|
|
32
|
-
}Content-Length: 121
|
|
33
|
-
|
|
32
|
+
}Content-Length: 121
|
|
33
|
+
|
|
34
34
|
{
|
|
35
35
|
"jsonrpc": "2.0",
|
|
36
36
|
"id": 2,
|
|
@@ -217,6 +217,64 @@ export function List_dropLast(self_, count_ = 1) {
|
|
|
217
217
|
return self_.slice(0, self_.length - count_)
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
+
export function List_count(self_, body_) {
|
|
221
|
+
let result_ = 0;
|
|
222
|
+
let i_ = 0;
|
|
223
|
+
while((i_ < ff_core_List.List_size(self_))) {
|
|
224
|
+
if(body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_)))) {
|
|
225
|
+
result_ += 1
|
|
226
|
+
};
|
|
227
|
+
i_ += 1
|
|
228
|
+
};
|
|
229
|
+
return result_
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export function List_countWhile(self_, body_) {
|
|
233
|
+
let i_ = 0;
|
|
234
|
+
while(((i_ < ff_core_List.List_size(self_)) && body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_))))) {
|
|
235
|
+
i_ += 1
|
|
236
|
+
};
|
|
237
|
+
return i_
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function List_takeWhile(self_, body_) {
|
|
241
|
+
const result_ = ff_core_Array.new_();
|
|
242
|
+
let i_ = 0;
|
|
243
|
+
while(((i_ < ff_core_List.List_size(self_)) && body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_))))) {
|
|
244
|
+
ff_core_Array.Array_push(result_, (self_[i_] ?? ff_core_List.internalGrab_(self_, i_)));
|
|
245
|
+
i_ += 1
|
|
246
|
+
};
|
|
247
|
+
return ff_core_Array.Array_drain(result_)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function List_dropWhile(self_, body_) {
|
|
251
|
+
const result_ = ff_core_Array.new_();
|
|
252
|
+
let i_ = 0;
|
|
253
|
+
while(((i_ < ff_core_List.List_size(self_)) && body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_))))) {
|
|
254
|
+
i_ += 1
|
|
255
|
+
};
|
|
256
|
+
while((i_ < ff_core_List.List_size(self_))) {
|
|
257
|
+
ff_core_Array.Array_push(result_, (self_[i_] ?? ff_core_List.internalGrab_(self_, i_)));
|
|
258
|
+
i_ += 1
|
|
259
|
+
};
|
|
260
|
+
return ff_core_Array.Array_drain(result_)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function List_partitionWhile(self_, body_) {
|
|
264
|
+
const first_ = ff_core_Array.new_();
|
|
265
|
+
const second_ = ff_core_Array.new_();
|
|
266
|
+
let i_ = 0;
|
|
267
|
+
while(((i_ < ff_core_List.List_size(self_)) && body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_))))) {
|
|
268
|
+
ff_core_Array.Array_push(first_, (self_[i_] ?? ff_core_List.internalGrab_(self_, i_)));
|
|
269
|
+
i_ += 1
|
|
270
|
+
};
|
|
271
|
+
while((i_ < ff_core_List.List_size(self_))) {
|
|
272
|
+
ff_core_Array.Array_push(second_, (self_[i_] ?? ff_core_List.internalGrab_(self_, i_)));
|
|
273
|
+
i_ += 1
|
|
274
|
+
};
|
|
275
|
+
return ff_core_Pair.Pair(ff_core_Array.Array_drain(first_), ff_core_Array.Array_drain(second_))
|
|
276
|
+
}
|
|
277
|
+
|
|
220
278
|
export function List_pairs(self_) {
|
|
221
279
|
let i_ = 0;
|
|
222
280
|
return ff_core_List.List_map(self_, ((x_) => {
|
|
@@ -343,6 +401,21 @@ return (!result_)
|
|
|
343
401
|
return result_
|
|
344
402
|
}
|
|
345
403
|
|
|
404
|
+
export function List_indexWhere(self_, body_) {
|
|
405
|
+
let result_ = ff_core_Option.None();
|
|
406
|
+
let i_ = 0;
|
|
407
|
+
ff_core_List.List_eachWhile(self_, ((x_) => {
|
|
408
|
+
if(body_(x_)) {
|
|
409
|
+
result_ = ff_core_Option.Some(i_);
|
|
410
|
+
return false
|
|
411
|
+
} else {
|
|
412
|
+
i_ += 1;
|
|
413
|
+
return true
|
|
414
|
+
}
|
|
415
|
+
}));
|
|
416
|
+
return result_
|
|
417
|
+
}
|
|
418
|
+
|
|
346
419
|
export function List_find(self_, body_) {
|
|
347
420
|
let result_ = ff_core_Option.None();
|
|
348
421
|
ff_core_List.List_eachWhile(self_, ((x_) => {
|
|
@@ -500,6 +573,64 @@ export async function List_dropLast$(self_, count_ = 1, $task) {
|
|
|
500
573
|
throw new Error('Function List_dropLast is missing on this target in async context.');
|
|
501
574
|
}
|
|
502
575
|
|
|
576
|
+
export async function List_count$(self_, body_, $task) {
|
|
577
|
+
let result_ = 0;
|
|
578
|
+
let i_ = 0;
|
|
579
|
+
while((i_ < ff_core_List.List_size(self_))) {
|
|
580
|
+
if((await body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_)), $task))) {
|
|
581
|
+
result_ += 1
|
|
582
|
+
};
|
|
583
|
+
i_ += 1
|
|
584
|
+
};
|
|
585
|
+
return result_
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
export async function List_countWhile$(self_, body_, $task) {
|
|
589
|
+
let i_ = 0;
|
|
590
|
+
while(((i_ < ff_core_List.List_size(self_)) && (await body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_)), $task)))) {
|
|
591
|
+
i_ += 1
|
|
592
|
+
};
|
|
593
|
+
return i_
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
export async function List_takeWhile$(self_, body_, $task) {
|
|
597
|
+
const result_ = ff_core_Array.new_();
|
|
598
|
+
let i_ = 0;
|
|
599
|
+
while(((i_ < ff_core_List.List_size(self_)) && (await body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_)), $task)))) {
|
|
600
|
+
ff_core_Array.Array_push(result_, (self_[i_] ?? ff_core_List.internalGrab_(self_, i_)));
|
|
601
|
+
i_ += 1
|
|
602
|
+
};
|
|
603
|
+
return ff_core_Array.Array_drain(result_)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
export async function List_dropWhile$(self_, body_, $task) {
|
|
607
|
+
const result_ = ff_core_Array.new_();
|
|
608
|
+
let i_ = 0;
|
|
609
|
+
while(((i_ < ff_core_List.List_size(self_)) && (await body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_)), $task)))) {
|
|
610
|
+
i_ += 1
|
|
611
|
+
};
|
|
612
|
+
while((i_ < ff_core_List.List_size(self_))) {
|
|
613
|
+
ff_core_Array.Array_push(result_, (self_[i_] ?? ff_core_List.internalGrab_(self_, i_)));
|
|
614
|
+
i_ += 1
|
|
615
|
+
};
|
|
616
|
+
return ff_core_Array.Array_drain(result_)
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
export async function List_partitionWhile$(self_, body_, $task) {
|
|
620
|
+
const first_ = ff_core_Array.new_();
|
|
621
|
+
const second_ = ff_core_Array.new_();
|
|
622
|
+
let i_ = 0;
|
|
623
|
+
while(((i_ < ff_core_List.List_size(self_)) && (await body_((self_[i_] ?? ff_core_List.internalGrab_(self_, i_)), $task)))) {
|
|
624
|
+
ff_core_Array.Array_push(first_, (self_[i_] ?? ff_core_List.internalGrab_(self_, i_)));
|
|
625
|
+
i_ += 1
|
|
626
|
+
};
|
|
627
|
+
while((i_ < ff_core_List.List_size(self_))) {
|
|
628
|
+
ff_core_Array.Array_push(second_, (self_[i_] ?? ff_core_List.internalGrab_(self_, i_)));
|
|
629
|
+
i_ += 1
|
|
630
|
+
};
|
|
631
|
+
return ff_core_Pair.Pair(ff_core_Array.Array_drain(first_), ff_core_Array.Array_drain(second_))
|
|
632
|
+
}
|
|
633
|
+
|
|
503
634
|
export async function List_pairs$(self_, $task) {
|
|
504
635
|
let i_ = 0;
|
|
505
636
|
return ff_core_List.List_map(self_, ((x_) => {
|
|
@@ -628,6 +759,21 @@ return (!result_)
|
|
|
628
759
|
return result_
|
|
629
760
|
}
|
|
630
761
|
|
|
762
|
+
export async function List_indexWhere$(self_, body_, $task) {
|
|
763
|
+
let result_ = ff_core_Option.None();
|
|
764
|
+
let i_ = 0;
|
|
765
|
+
(await ff_core_List.List_eachWhile$(self_, (async (x_, $task) => {
|
|
766
|
+
if((await body_(x_, $task))) {
|
|
767
|
+
result_ = ff_core_Option.Some(i_);
|
|
768
|
+
return false
|
|
769
|
+
} else {
|
|
770
|
+
i_ += 1;
|
|
771
|
+
return true
|
|
772
|
+
}
|
|
773
|
+
}), $task));
|
|
774
|
+
return result_
|
|
775
|
+
}
|
|
776
|
+
|
|
631
777
|
export async function List_find$(self_, body_, $task) {
|
|
632
778
|
let result_ = ff_core_Option.None();
|
|
633
779
|
(await ff_core_List.List_eachWhile$(self_, (async (x_, $task) => {
|
package/package.json
CHANGED
package/s3/S3.ff
CHANGED
|
@@ -26,7 +26,7 @@ put(
|
|
|
26
26
|
let response = system.httpClient().fetch(url, method = "PUT", headers = allHeaders, body = Some(HttpClient.bodyBuffer(body)), throw = False)
|
|
27
27
|
system.writeLine("" + response.status())
|
|
28
28
|
system.writeLine(response.statusText())
|
|
29
|
-
system.writeLine(response.readText())
|
|
29
|
+
//system.writeLine(response.readText())
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
makeS3AuthorizationHeader(
|
|
@@ -90,4 +90,4 @@ encodeURIComponent(text: String): String
|
|
|
90
90
|
|
|
91
91
|
encode(text: String): String {
|
|
92
92
|
text.split('/').map {encodeURIComponent(_)}.join("/")
|
|
93
|
-
}
|
|
93
|
+
}
|