firefly-compiler 0.4.46 → 0.4.48

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 CHANGED
@@ -16,13 +16,19 @@ release(
16
16
  accessKeyId: String
17
17
  secretAccessKey: String
18
18
  ): Unit {
19
- run(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
20
- run(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
21
- run(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
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(".."))
22
28
  bumpMinorVersion(system, system.path("../package.json"))
23
29
  bumpMinorVersion(system, system.path("../vscode/package.json"))
24
- run(system, "npm", ["publish"], system.path(".."))
25
- run(system, "vsce", ["publish"], system.path("../vscode"))
30
+ runSuccessful(system, "npm", ["publish"], system.path(".."))
31
+ runSuccessful(system, "vsce", ["publish"], system.path("../vscode"))
26
32
  let coreTemporary = system.path("../core/.firefly/temporary")
27
33
  if(!coreTemporary.exists()) {coreTemporary.createDirectory()}
28
34
  let coreTarGz = coreTemporary.slash("ff_core_0_0_0.tar.gz")
@@ -44,18 +50,49 @@ release(
44
50
  Pair("Content-Type", "application/x-gzip")
45
51
  ]
46
52
  )
53
+
54
+ // git commit
55
+ // git push
56
+ }
57
+
58
+ requireNpmLoggedIn(system: NodeSystem, workingDirectory: Path) {
59
+ let out = run(system, "npm", ["whoami"], workingDirectory)
60
+ if(out.exitCode != 0) {
61
+ system.writeErrorLine("")
62
+ system.writeErrorLine("You are not logged into npm")
63
+ system.writeErrorLine("Run 'npm adduser'")
64
+ system.exit(1)
65
+ }
47
66
  }
48
67
 
49
- run(system: NodeSystem, command: String, arguments: List[String], workingDirectory: Path) {
68
+ requireVsceLoggedIn(system: NodeSystem, workingDirectory: Path) {
69
+ let out = runSuccessful(system, "vsce", ["ls-publishers"], workingDirectory)
70
+ if(!out.toString().lines().any {_ == "firefly-team"}) {
71
+ system.writeErrorLine("")
72
+ system.writeErrorLine("You are not logged into vsce")
73
+ system.writeErrorLine("Manage firefly-team users here https://marketplace.visualstudio.com/manage/publishers/firefly-team")
74
+ system.writeErrorLine("Run 'vsce login firefly-team'")
75
+ system.writeErrorLine("Get a new token here https://dev.azure.com/firefly-lang/_usersSettings/tokens")
76
+ system.exit(1)
77
+ }
78
+ }
79
+
80
+ run(system: NodeSystem, command: String, arguments: List[String], workingDirectory: Path): ProcessResult {
50
81
  system.writeLine("")
51
82
  system.writeLine(command + " " + arguments.join(" "))
52
83
  let out = system.execute(command, arguments, workingDirectory = Some(workingDirectory))
53
84
  system.writeBuffer(out.standardOut)
54
85
  system.writeErrorBuffer(out.standardError)
86
+ out
87
+ }
88
+
89
+ runSuccessful(system: NodeSystem, command: String, arguments: List[String], workingDirectory: Path): Buffer {
90
+ let out = run(system, command, arguments, workingDirectory)
55
91
  if(out.exitCode != 0) {
56
92
  system.writeErrorLine("Exit code: " + out.exitCode)
57
93
  system.exit(1)
58
94
  }
95
+ out.standardOut
59
96
  }
60
97
 
61
98
  bumpMinorVersion(system: NodeSystem, packageJsonPath: Path) {
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
@@ -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, "(\n ...\n " + name + ": " + t2.show([]) + "\n ...\n)", Some(h.expected))
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 = allRequired.dropLast(trailing.size()).map {_.name}
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([]) + "(\n ...\n ", "\n ...\n)")
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(selfIndent + " ", p)
379
- }.join("\n") + "\n" + selfIndent
377
+ showCompletionParameter(" ", p)
378
+ }.join("\n") + "\n"
380
379
  }
381
- selfType.map {_.show([])}.map {"extend " + _ + " {\n"}.else {""} +
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
@@ -4,7 +4,7 @@
4
4
  "description": "Firefly compiler",
5
5
  "author": "Firefly team",
6
6
  "license": "MIT",
7
- "version": "0.4.46",
7
+ "version": "0.4.48",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"
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
+ }
@@ -4,7 +4,7 @@
4
4
  "description": "Firefly language support",
5
5
  "author": "Firefly team",
6
6
  "license": "MIT",
7
- "version": "0.4.46",
7
+ "version": "0.4.48",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"