firefly-compiler 0.5.79 → 0.5.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/compiler/Builder.ff +31 -39
  2. package/compiler/Compiler.ff +14 -4
  3. package/compiler/DevelopMode.ff +406 -0
  4. package/compiler/Main.ff +73 -53
  5. package/compiler/ModuleCache.ff +5 -5
  6. package/core/.firefly/include/package.json +1 -1
  7. package/core/BuildSystem.ff +82 -11
  8. package/core/NodeSystem.ff +47 -30
  9. package/core/Path.ff +7 -2
  10. package/experimental/proxy/Main.ff +60 -0
  11. package/experimental/proxy/Runner.ff +11 -0
  12. package/experimental/proxy/Tcp.ff +162 -0
  13. package/experimental/random/Superdigit.ff +18 -0
  14. package/experimental/terrain/Main.ff +40 -0
  15. package/experimental/terrain/Terrain.ff +97 -0
  16. package/experimental/terrain/Terrain2.ff +109 -0
  17. package/fireflysite/Main.ff +0 -1
  18. package/fireflysite/assets/markdown/reference/statements-and-expressions.md +1 -1
  19. package/lsp/CompletionHandler.ff +2 -2
  20. package/output/js/ff/compiler/Builder.mjs +24 -48
  21. package/output/js/ff/compiler/Builder.mjs.map +7 -11
  22. package/output/js/ff/compiler/Compiler.mjs +66 -12
  23. package/output/js/ff/compiler/Compiler.mjs.map +18 -14
  24. package/output/js/ff/compiler/Dependencies.mjs.map +2 -2
  25. package/output/js/ff/compiler/DependencyLock.mjs.map +1 -1
  26. package/output/js/ff/compiler/Deriver.mjs.map +1 -1
  27. package/output/js/ff/compiler/DevelopMode.mjs +1049 -0
  28. package/output/js/ff/compiler/DevelopMode.mjs.map +183 -0
  29. package/output/js/ff/compiler/Dictionaries.mjs.map +1 -1
  30. package/output/js/ff/compiler/Environment.mjs.map +1 -1
  31. package/output/js/ff/compiler/Inference.mjs.map +1 -1
  32. package/output/js/ff/compiler/JsEmitter.mjs.map +1 -1
  33. package/output/js/ff/compiler/JsImporter.mjs.map +1 -1
  34. package/output/js/ff/compiler/LspHook.mjs.map +1 -1
  35. package/output/js/ff/compiler/Main.mjs +256 -105
  36. package/output/js/ff/compiler/Main.mjs.map +43 -38
  37. package/output/js/ff/compiler/ModuleCache.mjs +12 -8
  38. package/output/js/ff/compiler/ModuleCache.mjs.map +4 -3
  39. package/output/js/ff/compiler/Parser.mjs.map +1 -1
  40. package/output/js/ff/compiler/Patterns.mjs.map +1 -1
  41. package/output/js/ff/compiler/Resolver.mjs.map +1 -1
  42. package/output/js/ff/compiler/SourceMap.mjs.map +1 -1
  43. package/output/js/ff/compiler/Substitution.mjs.map +1 -1
  44. package/output/js/ff/compiler/Syntax.mjs.map +1 -1
  45. package/output/js/ff/compiler/Token.mjs.map +1 -1
  46. package/output/js/ff/compiler/Tokenizer.mjs.map +1 -1
  47. package/output/js/ff/compiler/Unification.mjs.map +1 -1
  48. package/output/js/ff/compiler/Wildcards.mjs.map +1 -1
  49. package/output/js/ff/compiler/Workspace.mjs.map +1 -1
  50. package/output/js/ff/core/Any.mjs.map +1 -1
  51. package/output/js/ff/core/Array.mjs.map +1 -1
  52. package/output/js/ff/core/AssetSystem.mjs.map +1 -1
  53. package/output/js/ff/core/Atomic.mjs.map +1 -1
  54. package/output/js/ff/core/Bool.mjs.map +1 -1
  55. package/output/js/ff/core/BrowserSystem.mjs.map +1 -1
  56. package/output/js/ff/core/Buffer.mjs.map +1 -1
  57. package/output/js/ff/core/BuildSystem.mjs +116 -12
  58. package/output/js/ff/core/BuildSystem.mjs.map +35 -6
  59. package/output/js/ff/core/Channel.mjs.map +1 -1
  60. package/output/js/ff/core/Char.mjs.map +1 -1
  61. package/output/js/ff/core/Core.mjs.map +1 -1
  62. package/output/js/ff/core/Crypto.mjs.map +1 -1
  63. package/output/js/ff/core/Date.mjs.map +1 -1
  64. package/output/js/ff/core/Duration.mjs.map +1 -1
  65. package/output/js/ff/core/Equal.mjs.map +1 -1
  66. package/output/js/ff/core/Error.mjs.map +1 -1
  67. package/output/js/ff/core/FileHandle.mjs.map +1 -1
  68. package/output/js/ff/core/Float.mjs.map +1 -1
  69. package/output/js/ff/core/HttpClient.mjs.map +1 -1
  70. package/output/js/ff/core/Int.mjs.map +1 -1
  71. package/output/js/ff/core/IntMap.mjs.map +1 -1
  72. package/output/js/ff/core/Js.mjs.map +1 -1
  73. package/output/js/ff/core/JsSystem.mjs.map +1 -1
  74. package/output/js/ff/core/JsValue.mjs.map +1 -1
  75. package/output/js/ff/core/Json.mjs.map +1 -1
  76. package/output/js/ff/core/List.mjs.map +1 -1
  77. package/output/js/ff/core/Lock.mjs.map +1 -1
  78. package/output/js/ff/core/Log.mjs.map +1 -1
  79. package/output/js/ff/core/Map.mjs.map +1 -1
  80. package/output/js/ff/core/NodeSystem.mjs +54 -20
  81. package/output/js/ff/core/NodeSystem.mjs.map +14 -6
  82. package/output/js/ff/core/Nothing.mjs.map +1 -1
  83. package/output/js/ff/core/Option.mjs.map +1 -1
  84. package/output/js/ff/core/Ordering.mjs.map +1 -1
  85. package/output/js/ff/core/Pair.mjs.map +1 -1
  86. package/output/js/ff/core/Path.mjs +30 -4
  87. package/output/js/ff/core/Path.mjs.map +8 -6
  88. package/output/js/ff/core/Queue.mjs.map +1 -1
  89. package/output/js/ff/core/Random.mjs.map +1 -1
  90. package/output/js/ff/core/RbMap.mjs.map +1 -1
  91. package/output/js/ff/core/Serializable.mjs.map +1 -1
  92. package/output/js/ff/core/Set.mjs.map +1 -1
  93. package/output/js/ff/core/Show.mjs.map +1 -1
  94. package/output/js/ff/core/SourceLocation.mjs.map +1 -1
  95. package/output/js/ff/core/Stream.mjs.map +1 -1
  96. package/output/js/ff/core/String.mjs.map +1 -1
  97. package/output/js/ff/core/StringMap.mjs.map +1 -1
  98. package/output/js/ff/core/Task.mjs.map +1 -1
  99. package/output/js/ff/core/Try.mjs.map +1 -1
  100. package/output/js/ff/core/Unit.mjs.map +1 -1
  101. package/output/js/ff/core/node_modules +1 -0
  102. package/package.json +1 -1
  103. package/vscode/package.json +1 -1
  104. package/webserver/.firefly/include/package.json +1 -1
  105. package/webserver/WebServer.ff +6 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/RbMap.ff"
4
+ "../../../../core/RbMap.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "// Based on https://www.cs.kent.ac.uk/people/staff/smk/redblack/Untyped.hs\r\n\r\ndata Color {\r\n R\r\n B\r\n}\r\n\r\ndata RB[K, V] {\r\n E\r\n T(color: Color, left: RB[K, V], key: K, value: V, right: RB[K, V])\r\n}\r\n\r\ninsert[K: Order, V](x: K, xv: V, s: RB[K, V]): RB[K, V] {\r\n function ins(s: RB[K, V]): RB[K, V] {\r\n | E => T(R, E, x, xv, E)\r\n | T(B, a, y, yv, b) => Ordering.compare(x, y).{\r\n | OrderingBefore => balance(ins(a), y, yv, b)\r\n | OrderingAfter => balance(a, y, yv, ins(b))\r\n | OrderingSame => T(B, a, x, xv, b)\r\n }\r\n | T(R, a, y, yv, b) => Ordering.compare(x, y).{\r\n | OrderingBefore => T(R, ins(a), y, yv, b)\r\n | OrderingAfter => T(R, a, y, yv, ins(b))\r\n | OrderingSame => T(R, a, x, xv, b)\r\n }\r\n }\r\n\r\n ins(s).{\r\n | E => panic(\"Unexpected empty tree\")\r\n | T(_, a, z, zv, b) => T(B, a, z, zv, b)\r\n }\r\n}\r\n\r\nmember[K: Order, V](key: K, tree: RB[K, V]): Bool {\r\n | x, E => False\r\n | x, T(_, a, y, _, b,) => Ordering.compare(x, y).{\r\n | OrderingBefore => member(x, a)\r\n | OrderingAfter => member(x, b)\r\n | OrderingSame => True\r\n }\r\n}\r\n\r\nbalance[K: Order, V](tree1: RB[K, V], key: K, value: V, tree2: RB[K, V]): RB[K, V] {\r\n | T(R, a, x, xv, b), y, yv, T(R, c, z, zv, d) => T(R, T(B, a, x, xv, b), y, yv, T(B, c, z, zv, d))\r\n | T(R, T(R, a, x, xv, b), y, yv, c), z, zv, d => T(R, T(B, a, x, xv, b), y, yv, T(B, c, z, zv, d))\r\n | T(R, a, x, xv, T(R, b, y, yv, c)), z, zv, d => T(R, T(B, a, x, xv, b), y, yv, T(B, c, z, zv, d))\r\n | a, x, xv, T(R, b, y, yv, T(R, c, z, zv, d)) => T(R, T(B, a, x, xv, b), y, yv, T(B, c, z, zv, d))\r\n | a, x, xv, T(R, T(R, b, y, yv, c), z, zv, d) => T(R, T(B, a, x, xv, b), y, yv, T(B, c, z, zv, d))\r\n | a, x, xv, b => T(B, a, x, xv, b)\r\n}\r\n\r\ndelete[K: Order, V](x: K, t: RB[K, V]): RB[K, V] {\r\n function del(ss: RB[K, V]): RB[K, V] {\r\n | E => E\r\n | T(_, a, y, yv, b) => Ordering.compare(x, y).{\r\n | OrderingBefore => delformLeft(a, y, yv, b)\r\n | OrderingAfter => delformRight(a, y, yv, b)\r\n | OrderingSame => app(a, b)\r\n }\r\n }\r\n\r\n function delformLeft(left: RB[K, V], key: K, value: V, right: RB[K, V]): RB[K, V] {\r\n | T(B, _, _, _, _), y, yv, b => balleft(del(left), y, yv, b)\r\n | a, y, yv, b => T(R, del(a), y, yv, b)\r\n }\r\n\r\n function delformRight(left: RB[K, V], key: K, value: V, right: RB[K, V]): RB[K, V] {\r\n | a, y, yv, T(B, _, _, _, _) => balright(a, y, yv, del(right))\r\n | a, y, yv, b => T(R, a, y, yv, del(b))\r\n }\r\n\r\n del(t).{\r\n | T(_, a, y, yv, b) => T(B, a, y, yv, b)\r\n | _ => E\r\n }\r\n}\r\n\r\nballeft[K: Order, V](tree1: RB[K, V], key: K, value: V, tree2: RB[K, V]): RB[K, V] {\r\n | T(R, a, x, xv, b), y, yv, c => T(R, T(B, a, x, xv, b), y, yv, c)\r\n | bl, x, xv, T(B, a, y, yv, b) => balance(bl, x, xv, T(R, a, y, yv, b))\r\n | bl, x, xv, T(R, T(B, a, y, yv, b), z, zv, c) => T(R, T(B, bl, x, xv, a), y, yv, (balance(b, z, zv, sub1(c))))\r\n | _, _, _, _ => panic(\"Unexhaustive match in balleft\")\r\n}\r\n\r\nbalright[K: Order, V](tree1: RB[K, V], key: K, value: V, tree2: RB[K, V]): RB[K, V] {\r\n | a, x, xv, T(R, b, y, yv, c) => T(R, a, x, xv, T(B, b, y, yv, c))\r\n | T(B, a, x, xv, b), y, yv, bl => balance(T(R, a, x, xv, b), y, yv, bl)\r\n | T(R, a, x, xv, T(B, b, y, yv, c)), z, zv, bl => T(R, balance(sub1(a), x, xv, b), y, yv, T(B, c, z, zv, bl))\r\n | _, _, _, _ => panic(\"Unexhaustive match in balright\")\r\n}\r\n\r\nsub1[K: Order, V](tree: RB[K, V]): RB[K, V] {\r\n | T(B, a, x, xv, b) => T(R, a, x, xv, b)\r\n | _ => panic(\"invariance violation\")\r\n}\r\n\r\napp[K: Order, V](tree1: RB[K, V], tree2: RB[K, V]): RB[K, V] {\r\n | E, b => b\r\n | a, E => a\r\n | T(R, a, x, xv, b), T(R, c, y, yv, d) =>\r\n app(b, c).{\r\n | T(R, b2, z, zv, c2) => T(R, T(R, a, x, xv, b2), z, zv, T(R, c2, y, yv, d))\r\n | bc => T(R, a, x, xv, T(R, bc, y, yv, d))\r\n }\r\n | T(B, a, x, xv, b), T(B, c, y, yv, d) =>\r\n app(b, c).{\r\n | T(R, b2, z, zv, c2) => T(R, T(B, a, x, xv, b2), z, zv, T(B, c2, y, yv, d))\r\n | bc => balleft(a, x, xv, T(B, bc, y, yv, d))\r\n }\r\n | a, T(R, b, x, xv, c) => T(R, app(a, b), x, xv, c)\r\n | T(R, a, x, xv, b), c => T(R, a, x, xv, app(b, c))\r\n}\r\n\r\nextend self[K: Order, V]: RB[K, V] {\r\n\r\n get(key: K): Option[V] {\r\n self.{\r\n | E_ => None\r\n | T(_, a, y, yv, b) => Ordering.compare(key, y).{\r\n | OrderingBefore => a.get(key)\r\n | OrderingAfter => b.get(key)\r\n | OrderingSame => Some(yv)\r\n }\r\n }\r\n }\r\n \r\n first(): Option[Pair[K, V]] {\r\n self.{\r\n | E => None\r\n | T(_, E, k, v, _) => Some(Pair(k, v))\r\n | T(_, l, _, _, _) => l.first()\r\n }\r\n }\r\n \r\n last(): Option[Pair[K, V]] {\r\n self.{\r\n | E => None\r\n | T(_, _, k, v, E) => Some(Pair(k, v))\r\n | T(_, _, _, _, r) => r.last()\r\n }\r\n }\r\n\r\n lastBefore(key: K): Option[Pair[K, V]] {\r\n self.{\r\n | E => None\r\n | T(_, l, k, v, r) {k >= key} => l.lastBefore(key)\r\n | T(_, l, k, v, r) => r.lastBefore(key).orElse {Some(Pair(k, v))}\r\n }\r\n }\r\n \r\n firstAfter(key: K): Option[Pair[K, V]] {\r\n self.{\r\n | E => None\r\n | T(_, l, k, v, r) {k <= key} => r.firstAfter(key)\r\n | T(_, l, k, v, r) => l.firstAfter(key).orElse {Some(Pair(k, v))}\r\n }\r\n }\r\n\r\n size(): Int {\r\n self.{\r\n | E => 0\r\n | T(_, l, _, _, r) => l.size() + 1 + r.size()\r\n }\r\n }\r\n\r\n pairs(): List[Pair[K, V]] {\r\n let result = [].toArray()\r\n self.each {k, v =>\r\n result.push(Pair(k, v))\r\n }\r\n result.drain()\r\n }\r\n\r\n toStream(cycle: Bool): Stream[Pair[K, V]] {\r\n mutable array = [self]\r\n function next(): Option[Pair[K, V]] {\r\n array.{\r\n | [] =>\r\n if(cycle && self.{| E => False | _ => True}) {\r\n array = [self]\r\n tailcall next()\r\n } else {\r\n None\r\n }\r\n | [E, ...tail] =>\r\n array = tail\r\n tailcall next()\r\n | [T(_, E, k, v, E), ...tail] =>\r\n array = tail\r\n Some(Pair(k, v))\r\n | [T(_, l, k, v, r), ...tail] =>\r\n array = [l, T(B, E, k, v, E), r, ...tail]\r\n tailcall next()\r\n }\r\n }\r\n Stream.new(next)\r\n }\r\n\r\n each(body: (K, V) => Unit): Unit {\r\n self.{\r\n | E =>\r\n | T(_, l, k, v, r) =>\r\n l.each(body)\r\n body(k, v)\r\n r.each(body)\r\n }\r\n }\r\n\r\n eachWhile(body: (K, V) => Bool): Bool {\r\n self.{\r\n | E =>\r\n True\r\n | T(_, l, k, v, r) =>\r\n l.eachWhile(body) &&\r\n body(k, v) &&\r\n r.eachWhile(body)\r\n }\r\n }\r\n\r\n map[K2: Order, V2](body: (K, V) => Pair[K2, V2]): RB[K2, V2] {\r\n mutable result = E\r\n self.each {k, v =>\r\n let pair = body(k, v)\r\n result = insert(pair.first, pair.second, result)\r\n }\r\n result\r\n }\r\n\r\n mapValues[V2](body: (K, V) => V2): RB[K, V2] {\r\n self.{\r\n | E => E\r\n | T(c, l, k, v, r) =>\r\n T(c, l.mapValues(body), k, body(k, v), r.mapValues(body))\r\n }\r\n }\r\n\r\n find(body: (K, V) => Bool): Option[Pair[K, V]] {\r\n mutable result = None\r\n self.eachWhile {k, v => \r\n if(body(k, v)) {\r\n result = Some(Pair(k, v))\r\n False\r\n } else {True}\r\n }\r\n result\r\n }\r\n\r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/Serializable.ff"
4
+ "../../../../core/Serializable.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "data DeserializationChecksumException()\r\n\r\nserialize[T: Serializable](value: T, initialBufferSize: Int = 1024): Buffer {\r\n let serialization = Serialization(Buffer.new(initialBufferSize), 0, 0)\r\n serializeUsing(serialization, value)\r\n serialization.autoResize(4)\r\n serialization.buffer.setInt32(serialization.offset, serialization.checksum)\r\n serialization.offset += 4\r\n serialization.buffer.view(0, serialization.offset)\r\n}\r\n\r\ndeserialize[T: Serializable](buffer: Buffer): T {\r\n let serialization = Serialization(buffer, 0, 0)\r\n let result = deserializeUsing(serialization)\r\n let checksum = serialization.buffer.grabInt32(serialization.offset)\r\n if(checksum != serialization.checksum) {\r\n throw(DeserializationChecksumException)\r\n }\r\n result\r\n}\r\n\r\ntrait T: Serializable {\r\n serializeUsing(serialization: Serialization, value: T): Unit\r\n deserializeUsing(serialization: Serialization): T\r\n}\r\n\r\nclass Serialization(\r\n mutable buffer: Buffer\r\n mutable offset: Int\r\n mutable checksum: Int\r\n)\r\n\r\nextend self: Serialization {\r\n autoResize(minSpareCapacity: Int) {\r\n if(self.offset + minSpareCapacity > self.buffer.size()) {\r\n let minSize = self.buffer.size() + minSpareCapacity\r\n let newBuffer = Buffer.new((self.buffer.size() * 2).max(minSize))\r\n newBuffer.setAll(0, self.buffer)\r\n self.buffer = newBuffer\r\n }\r\n }\r\n}\r\n\r\ninstance Int: Serializable {\r\n serializeUsing(serialization: Serialization, value: Int): Unit {\r\n serialization.autoResize(8)\r\n serialization.buffer.setInt64(serialization.offset, value)\r\n serialization.offset += 8\r\n }\r\n deserializeUsing(serialization: Serialization): Int {\r\n let result = serialization.buffer.grabInt64(serialization.offset)\r\n serialization.offset += 8\r\n result\r\n }\r\n}\r\n\r\ninstance Bool: Serializable {\r\n serializeUsing(serialization: Serialization, value: Bool): Unit {\r\n serialization.autoResize(1)\r\n serialization.buffer.setUint8(serialization.offset, if(value) {1} else {0})\r\n serialization.offset += 1\r\n }\r\n deserializeUsing(serialization: Serialization): Bool {\r\n let result = serialization.buffer.grabUint8(serialization.offset)\r\n serialization.offset += 1\r\n result == 1\r\n }\r\n}\r\n\r\ninstance List[T: Serializable]: Serializable {\r\n serializeUsing(serialization: Serialization, value: List[T]): Unit {\r\n if(value.size() < 255) {\r\n serialization.autoResize(1)\r\n serialization.buffer.setUint8(serialization.offset, value.size())\r\n serialization.offset += 1\r\n } elseIf {value.size() < 1073741824} {\r\n serialization.autoResize(1 + 4)\r\n serialization.buffer.setUint8(serialization.offset, 255)\r\n serialization.buffer.setUint32(1 + serialization.offset, value.size())\r\n serialization.offset += 1 + 4\r\n } else {\r\n panic(\"Can't serialize arrays where size() >= 1073741824\")\r\n }\r\n value.each {serializeUsing(serialization, _)}\r\n }\r\n deserializeUsing(serialization: Serialization): List[T] {\r\n let smallSize = serialization.buffer.grabUint8(serialization.offset)\r\n if(smallSize != 255) {\r\n serialization.offset += 1\r\n List.fillBy(smallSize) {_ => deserializeUsing(serialization)}\r\n } else {\r\n let size = serialization.buffer.grabUint32(serialization.offset + 1)\r\n serialization.offset += 1 + 4\r\n List.fillBy(size) {_ => deserializeUsing(serialization)}\r\n }\r\n }\r\n}\r\n\r\ninstance Set[T: Serializable: Order]: Serializable {\r\n serializeUsing(serialization: Serialization, value: Set[T]): Unit {\r\n serializeUsing(serialization, value.toList())\r\n }\r\n deserializeUsing(serialization: Serialization): Set[T] {\r\n deserializeUsing[List[T]](serialization).toSet()\r\n }\r\n}\r\n\r\ninstance Map[K: Serializable: Order, V: Serializable]: Serializable {\r\n serializeUsing(serialization: Serialization, value: Map[K, V]): Unit {\r\n serializeUsing(serialization, value.toList())\r\n }\r\n deserializeUsing(serialization: Serialization): Map[K, V] {\r\n deserializeUsing[List[Pair[K, V]]](serialization).toMap()\r\n }\r\n}\r\n\r\ninstance String: Serializable {\r\n serializeUsing(serialization: Serialization, value: String): Unit {\r\n serialization.autoResize(1 + value.size())\r\n serialization.buffer.setUint8(serialization.offset, value.size())\r\n if(value.size() < 255 && internalSetLatin1(serialization.buffer, serialization.offset + 1, value)) {\r\n serialization.offset += 1 + value.size()\r\n } elseIf {value.size() < 1073741824} {\r\n let stringBuffer = value.toBuffer()\r\n serialization.autoResize(5 + stringBuffer.size())\r\n serialization.buffer.setUint8(serialization.offset, 255)\r\n serialization.buffer.setUint32(serialization.offset + 1, stringBuffer.size())\r\n serialization.buffer.setAll(serialization.offset + 5, stringBuffer)\r\n serialization.offset += 5 + stringBuffer.size()\r\n } else {\r\n panic(\"Can't serialize strings where size() >= 1073741824\")\r\n }\r\n }\r\n deserializeUsing(serialization: Serialization): String {\r\n let smallSize = serialization.buffer.grabUint8(serialization.offset)\r\n if(smallSize != 255) {\r\n let result = internalGrabLatin1(serialization.buffer, serialization.offset + 1, smallSize)\r\n serialization.offset += 1 + smallSize\r\n result\r\n } else {\r\n let size = serialization.buffer.grabUint32(serialization.offset + 1)\r\n let stringBuffer = serialization.buffer.view(serialization.offset + 5, serialization.offset + 5 + size)\r\n serialization.offset += 5 + size\r\n stringBuffer.toString()\r\n }\r\n }\r\n}\r\n\r\n\r\ninternalSetLatin1(self: Buffer, byteOffset: Int, value: String): Bool {\r\n mutable result = True\r\n 0.until(value.size()).eachWhile {i =>\r\n let charCode: Int = value!->charCodeAt(i)?\r\n if(charCode >= 256) {\r\n result = False\r\n } else {\r\n self!->setUint8(byteOffset + i, charCode)\r\n }\r\n result\r\n }\r\n result\r\n}\r\n\r\ninternalGrabLatin1(self: Buffer, byteOffset: Int, size: Int): String {\r\n let codeUnits = Js->Uint8Array->(self!->buffer, self!->byteOffset + byteOffset!, size)\r\n Js->String->fromCharCode->apply(Js.null(), codeUnits)?\r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/Set.ff"
4
+ "../../../../core/Set.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "newtype Set[T](map: Map[T, Unit])\r\n\r\nnew[T](): Set[T] {\r\n Set(Map.new())\r\n}\r\n\r\nextend self[T: Order]: Set[T] {\r\n add(value: T): Set[T] {Set(self.map.add(value, Unit))}\r\n addAll(that: Set[T]): Set[T] {Set(self.map.addAll(that.map))}\r\n addList(that: List[T]): Set[T] {\r\n mutable result = self.map\r\n that.each {k =>\r\n result = result.add(k, Unit)\r\n }\r\n Set(result) \r\n }\r\n remove(value: T): Set[T] {Set(self.map.remove(value))}\r\n removeAll(that: Set[T]): Set[T] {Set(self.map.removeAll(that.map))}\r\n contains(value: T): Bool {self.map.contains(value)}\r\n first(): Option[T] {self.map.first().map {_.first}}\r\n last(): Option[T] {self.map.last().map {_.first}}\r\n lastBefore(key: T): Option[T] {self.map.lastBefore(key).map {_.first}}\r\n firstAfter(key: T): Option[T] {self.map.firstAfter(key).map {_.first}}\r\n size(): Int {self.map.size()}\r\n toList(): List[T] {self.map.toList().map {_.first}}\r\n toStream(cycle: Bool = False): Stream[T] {self.map.toStream(cycle).map {_.first }}\r\n each(body: T => Unit): Unit {self.map.each {| k, _ => body(k)}}\r\n eachWhile(body: T => Bool): Bool {self.map.eachWhile {| k, _ => body(k)}}\r\n find(body: T => Bool): Option[T] {self.map.find {| k, _ => body(k)}.map {_.first}}\r\n}\r\n\r\ninstance Set[A: Equal: Order]: Equal {\r\n equals(x: Set[A], y: Set[A]): Bool {\r\n Equal.equals(x.toList(), y.toList())\r\n }\r\n}\r\n\r\ninstance Set[A: Order]: Order {\r\n compare(x: Set[A], y: Set[A]): Ordering {\r\n Ordering.compare(x.toList(), y.toList())\r\n }\r\n}\r\n\r\ninstance Set[A: Show: Order]: Show {\r\n show(value: Set[A]): String {\r\n Show.show(value.toList()) + \".toSet()\"\r\n }\r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/Show.ff"
4
+ "../../../../core/Show.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "trait T: Show {\r\n show(value: T): String\r\n}\r\n\r\ninstance Bool: Show {\r\n show(value: Bool): String {\r\n | False => \"False\"\r\n | True => \"True\"\r\n }\r\n}\r\n\r\ninstance Nothing: Show {\r\n show(value: Nothing): String {\"\"}\r\n}\r\n\r\ninstance Char: Show {\r\n show(value: Char): String {value.toString()}\r\n}\r\n\r\ninstance Int: Show {\r\n show(value: Int): String {\"\" + value}\r\n}\r\n\r\ninstance Float: Show {\r\n show(value: Float): String {\"\" + value}\r\n}\r\n\r\ninstance String: Show {\r\n show(value: String): String {\r\n Js->JSON->stringify(value)?\r\n }\r\n}\r\n\r\ninstance List[T: Show]: Show {\r\n show(value: List[T]): String {\r\n \"[\" + value.map(show).join(\", \") + \"]\"\r\n }\r\n}\r\n\r\ninstance Pair[A: Show, B: Show]: Show {\r\n show(value: Pair[A, B]): String {\r\n \"Pair(\" + show(value.first) + \", \" + show(value.second) + \")\"\r\n }\r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/SourceLocation.ff"
4
+ "../../../../core/SourceLocation.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "newtype SourceLocation(location: String) // E.g. \"directory/Module:line:column,group,package>Type>function\"\r\n\r\nhere(location: SourceLocation = SourceLocation.callSite()): SourceLocation {\r\n location\r\n}\r\n\r\ncallSite(): SourceLocation {\r\n panic(\"SourceLocation.callSite() can only occur as the default value of an argument\")\r\n}\r\n\r\nextend self: SourceLocation {\r\n\r\n group(): String {\r\n self.location.dropWhile {_ != ','}.dropFirst().takeWhile {_ != ','}\r\n }\r\n \r\n package(): String {\r\n self.location.dropWhile {_ != ','}.dropFirst().dropWhile {_ != ','}.dropFirst().takeWhile {_ != '>'}\r\n }\r\n \r\n directory(): String {\r\n self.location.takeWhile {_ != ':'}.reverse().dropWhile {_ != '/'}.dropFirst().reverse()\r\n }\r\n\r\n module(): String {\r\n self.location.takeWhile {_ != ':'}.reverse().takeWhile {_ != '/'}.reverse()\r\n }\r\n \r\n directoryAndModule(): String {\r\n self.location.takeWhile {_ != ':'}.reverse().reverse()\r\n }\r\n\r\n line(): Int {\r\n self.location.dropWhile {_ != ':'}.dropFirst().takeWhile {_ != ':'}.grabInt()\r\n }\r\n\r\n column(): Int {\r\n self.location.dropWhile {_ != ':'}.dropFirst().dropWhile {_ != ':'}.dropFirst().takeWhile {_ != ','}.grabInt()\r\n }\r\n \r\n breadcrumbs(): List[String] {\r\n self.location.dropWhile {_ != '>'}.dropFirst().split('>')\r\n }\r\n\r\n}\r\n\r\ninstance SourceLocation: Show {\r\n show(self: SourceLocation): String {\r\n self.location\r\n }\r\n}\r\n\r\ninstance SourceLocation: Equal {\r\n equals(a: SourceLocation, b: SourceLocation): Bool {\r\n a.location == b.location\r\n }\r\n}\r\n\r\ninstance SourceLocation: Order {\r\n compare(a: SourceLocation, b: SourceLocation): Ordering {\r\n Ordering.compare(a.location, b.location)\r\n }\r\n}\r\n\r\ninstance SourceLocation: Serializable {\r\n serializeUsing(serialization: Serialization, self: SourceLocation) {\r\n Serializable.serializeUsing(serialization, self.location)\r\n }\r\n deserializeUsing(serialization: Serialization): SourceLocation {\r\n SourceLocation(Serializable.deserializeUsing(serialization))\r\n }\r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/Stream.ff"
4
+ "../../../../core/Stream.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "capability Stream[T](\r\n next: () => Option[T]\r\n close: () => Unit\r\n)\r\n\r\nnew[T](next: () => Option[T], close: () => Unit = {}): Stream[T] {\r\n Stream(next, close)\r\n}\r\n\r\ndo[T](body: () => Stream[T]): Stream[T] {\r\n mutable initialized = False\r\n mutable stream = Stream {None} {}\r\n Stream({\r\n if(initialized) {\r\n stream.next()\r\n } else {\r\n initialized = True\r\n stream = body()\r\n stream.next()\r\n }\r\n }, {\r\n initialized = True\r\n stream.close()\r\n })\r\n}\r\n\r\nextend self[T]: Stream[T] {\r\n\r\n addAll(that: Stream[T]): Stream[T] {\r\n mutable firstDone = False\r\n Stream {\r\n if(firstDone) {\r\n that.next()\r\n } else {\r\n self.next().orElse {\r\n firstDone = True\r\n that.next()\r\n }\r\n }\r\n } {\r\n try {\r\n self.close()\r\n } finally {\r\n that.close()\r\n }\r\n }\r\n }\r\n\r\n map[S](body: T => S): Stream[S] {\r\n Stream {\r\n self.next().map(body)\r\n } {\r\n self.close()\r\n }\r\n }\r\n\r\n flatMap[S](body: T => Stream[S]): Stream[S] {\r\n mutable inner = Stream {None} {}\r\n Stream {\r\n mutable result = None\r\n while {result.isEmpty()} {\r\n inner.next().{\r\n | Some(_)@i => result = Some(i)\r\n | None =>\r\n self.next().{\r\n | None => result = Some(None)\r\n | Some(o) => \r\n inner.close()\r\n inner = body(o)\r\n }\r\n }\r\n }\r\n result.grab()\r\n } {\r\n try {\r\n inner.close()\r\n } finally {\r\n self.close()\r\n }\r\n }\r\n }\r\n\r\n collect[S](body: T => Option[S]): Stream[S] {\r\n self.flatMap {body(_).toStream()}\r\n }\r\n\r\n filter(body: T => Bool): Stream[T] {\r\n Stream {\r\n mutable result = None\r\n while {result.isEmpty()} {\r\n self.next().{\r\n | Some(x) {body(x)} => result = Some(Some(x))\r\n | Some(_) =>\r\n | None => result = Some(None)\r\n }\r\n }\r\n result.grab()\r\n } {\r\n self.close()\r\n }\r\n }\r\n\r\n zip[S](that: Stream[S]): Stream[Pair[T, S]] {\r\n Stream {\r\n Pair(self.next(), that.next()).{\r\n | Pair(Some(x), Some(y)) => Some(Pair(x, y))\r\n | _ => None\r\n }\r\n } {\r\n try {\r\n self.close()\r\n } finally {\r\n that.close()\r\n }\r\n }\r\n }\r\n\r\n takeFirst(count: Int = 1): Stream[T] {\r\n mutable remaining = count\r\n Stream {\r\n self.next().filter {_ =>\r\n remaining -= 1\r\n remaining >= 0\r\n }\r\n } {\r\n self.close()\r\n }\r\n }\r\n\r\n dropFirst(count: Int = 1): Stream[T] {\r\n mutable remaining = count\r\n Stream {\r\n while {remaining >= 1} {\r\n self.next().{\r\n | None => remaining = 0\r\n | Some(_) => remaining -= 1\r\n }\r\n }\r\n self.next()\r\n } {\r\n self.close()\r\n }\r\n }\r\n\r\n takeWhile(body: T => Bool): Stream[T] {\r\n mutable done = False\r\n Stream {\r\n if(done) {None} else:\r\n self.next().{\r\n | None =>\r\n done = True\r\n None\r\n | Some(x)@o =>\r\n done = !body(x)\r\n if(done) {None} else {o}\r\n }\r\n } {\r\n self.close()\r\n }\r\n }\r\n\r\n dropWhile(body: T => Bool): Stream[T] {\r\n mutable done = False\r\n Stream {\r\n if(!done) {\r\n mutable result = None\r\n while {!done} {\r\n self.next().{\r\n | None => done = True\r\n | Some(x) {body(x)} =>\r\n | Some(x)@o =>\r\n result = o\r\n done = True\r\n }\r\n }\r\n result\r\n } else {\r\n self.next()\r\n }\r\n } {\r\n self.close()\r\n }\r\n }\r\n\r\n pairs(): Stream[Pair[Int, T]] {\r\n mutable i = 0\r\n self.map {x =>\r\n let r = Pair(i, x)\r\n i += 1\r\n r\r\n }\r\n }\r\n\r\n chunked(size: Int): Stream[List[T]] {\r\n mutable remaining = size\r\n Stream {\r\n if(remaining <= 0) {None} else:\r\n self.next().{\r\n | None =>\r\n remaining = -1\r\n None\r\n | Some(x) =>\r\n mutable list = [x]\r\n remaining -= 1\r\n while {remaining > 0} {\r\n remaining -= 1\r\n self.next().{\r\n | None => remaining = -1\r\n | Some(x) => list = [x, ...list]\r\n }\r\n }\r\n if(remaining != -1) {remaining = size}\r\n Some(list.reverse())\r\n }\r\n } {\r\n self.close()\r\n }\r\n }\r\n\r\n // Consuming methods\r\n\r\n use[R](body: Stream[T] => R): R {\r\n try {\r\n body(self)\r\n } finally {\r\n self.close()\r\n }\r\n }\r\n\r\n each(body: T => Unit): Unit {\r\n try {\r\n mutable done = False\r\n while {!done} {\r\n self.next().{\r\n | None => done = True\r\n | Some(x) => body(x)\r\n }\r\n }\r\n } finally {\r\n self.close()\r\n }\r\n }\r\n\r\n eachWhile(body: T => Bool): Unit {\r\n try {\r\n mutable done = False\r\n while {!done} {\r\n self.next().{\r\n | None => done = True\r\n | Some(x) => done = !body(x)\r\n }\r\n }\r\n } finally {\r\n self.close()\r\n }\r\n }\r\n\r\n all(body: T => Bool): Bool {\r\n mutable result = True\r\n self.eachWhile {x =>\r\n result = result && body(x)\r\n result\r\n }\r\n result\r\n }\r\n\r\n any(body: T => Bool): Bool {\r\n mutable result = False\r\n self.eachWhile {x =>\r\n result = result || body(x)\r\n (!result)\r\n }\r\n result\r\n }\r\n\r\n first(): Option[T] {\r\n try {\r\n self.next()\r\n } finally {\r\n self.close()\r\n }\r\n }\r\n\r\n last(): Option[T] {\r\n try {\r\n mutable done = False\r\n mutable result = None\r\n while {!done} {\r\n self.next().{\r\n | None => done = True\r\n | Some(x)@o => result = o\r\n }\r\n }\r\n result\r\n } finally {\r\n self.close()\r\n }\r\n }\r\n\r\n grabFirst(): T {\r\n self.first().else {panic(\"grabFirst() on empty iterator\")}\r\n }\r\n\r\n grabLast(): T {\r\n self.last().else {panic(\"grabLast() on empty iterator\")}\r\n }\r\n\r\n collectFirst[R](body: T => Option[R]): Option[R] {\r\n try {\r\n mutable done = False\r\n mutable result = None\r\n while {!done} {\r\n self.next().{\r\n | None => done = True\r\n | Some(x) =>\r\n body(x).{\r\n | None =>\r\n | o =>\r\n done = True\r\n result = o\r\n }\r\n }\r\n }\r\n result\r\n } finally {\r\n self.close()\r\n }\r\n }\r\n\r\n find(body: T => Bool): Option[T] {\r\n self.filter(body).first()\r\n }\r\n\r\n foldLeft[R](initial: R, body: (R, T) => R): R {\r\n mutable result = initial\r\n self.each {result = body(result, _)}\r\n result\r\n }\r\n\r\n toArray(): Array[T] {\r\n let array = Array.new()\r\n self.each {array.push(_)}\r\n array\r\n }\r\n\r\n toList(): List[T] {\r\n self.toArray().drain()\r\n }\r\n\r\n}\r\n\r\nextend self[T]: Stream[Stream[T]] {\r\n flatten(): Stream[T] {\r\n self.flatMap {_}\r\n }\r\n}\r\n\r\nextend self[T: Order]: Stream[T] {\r\n toSet(): Set[T] {\r\n self.toList().toSet()\r\n }\r\n}\r\n\r\nextend self[K: Order, V]: Stream[Pair[K, V]] {\r\n toMap(): Map[K, V] {\r\n self.toList().toMap()\r\n }\r\n}\r\n\r\nextend self: Stream[Buffer] {\r\n\r\n toBuffer(): Buffer {\r\n let builder = Array.new()\r\n self.each {builder.push(_)}\r\n Buffer.fromBufferList(builder.drain())\r\n }\r\n\r\n toString(encoding: String = \"utf8\"): String {\r\n self.toBuffer().toString(encoding)\r\n }\r\n\r\n readBytes(bytes: Int): Pair[List[Buffer], Stream[Buffer]] {\r\n if(bytes <= 0) {Pair([], self)} else:\r\n let buffers = Array.new()\r\n mutable buffer = self.next().grab()\r\n mutable taken = 0\r\n mutable remainder = None\r\n while {remainder == None} {\r\n let needed = bytes - taken\r\n if(needed > buffer.size()) {\r\n buffers.push(buffer)\r\n taken += buffer.size()\r\n buffer = self.next().grab()\r\n } else {\r\n buffers.push(buffer.view(0, needed))\r\n remainder = Some(buffer.view(needed, buffer.size()))\r\n }\r\n }\r\n Pair(buffers.drain(), remainder.toStream().addAll(self))\r\n }\r\n\r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/String.ff"
4
+ "../../../../core/String.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "data String {}\r\n\r\nextend self: String {\r\n\r\n size(): Int {\r\n self!->length?\r\n }\r\n\r\n grab(index: Int): Char {\r\n if(index < 0 || index >= self.size()) {\r\n throw(GrabException())\r\n }\r\n self!->charCodeAt(index)?\r\n }\r\n \r\n replace(needle: String, replacement: String): String {\r\n self!->replaceAll(needle, replacement)?\r\n }\r\n\r\n replaceFirst(needle: String, replacement: String): String {\r\n self!->replace(needle, replacement)?\r\n }\r\n\r\n reverse(): String {\r\n self!->split(\"\")->reverse()->join(\"\")?\r\n }\r\n\r\n repeat(count: Int): String {\r\n self!->repeat(count)?\r\n }\r\n\r\n trim(): String {\r\n self!->trim()?\r\n }\r\n\r\n trimStart(): String {\r\n self!->trimStart()?\r\n }\r\n\r\n trimEnd(): String {\r\n self!->trimEnd()?\r\n }\r\n\r\n lower(): String {\r\n self!->toLowerCase()?\r\n }\r\n\r\n upper(): String {\r\n self!->toUpperCase()?\r\n }\r\n\r\n dropWhile(p: Char => Bool): String {\r\n mutable i = 0\r\n while {i < self.size() && p(self!->charCodeAt(i)?)} {\r\n i += 1\r\n }\r\n self!->slice(i)?\r\n }\r\n\r\n takeWhile(p: Char => Bool): String {\r\n mutable i = 0\r\n while {i < self.size() && p(self!->charCodeAt(i)?)} {\r\n i += 1\r\n }\r\n self!->slice(0, i)?\r\n }\r\n\r\n slice(from: Int, until: Int): String {\r\n self!->slice(from, until)?\r\n }\r\n\r\n split(char: Char): List[String] {\r\n self!->split(Js->String->fromCharCode(char))?\r\n }\r\n \r\n splitFirst(char: Char): Option[Pair[String, String]] {\r\n let array: List[String] = self!->split(Js->String->fromCharCode(char), 2)?\r\n if(array.size() == 2) {\r\n Pair(array!.get(0)?, array!.get(1)?)\r\n }\r\n } \r\n\r\n lines(): List[String] {\r\n self!->split(\r\n Js->RegExp->(\"[\" + Js->String->fromCharCode(13)? + \"]?[\" + Js->String->fromCharCode(10)? + \"]\", \"g\")\r\n )?\r\n }\r\n\r\n dropFirst(count: Int = 1): String {\r\n self!->slice(count)?\r\n }\r\n\r\n dropLast(count: Int = 1): String {\r\n self!->slice(0, self.size() - count)?\r\n }\r\n \r\n getInt(): Option[Int] {\r\n if(self.size() > 0 && self.all {c => 48 <= c.codeUnit && c.codeUnit <= 57}) {\r\n Js->parseInt(self!, 10)?\r\n }\r\n }\r\n \r\n getFloat(): Option[Float] {\r\n // TODO return None for invalid input\r\n let result = Js->parseFloat(self!, 10)\r\n if(Js->isFinite(result)?) {result?}\r\n }\r\n\r\n grabInt(): Int {\r\n self.getInt().else {\r\n throw(GrabException())\r\n }\r\n }\r\n \r\n grabFloat(): Float {\r\n self.getFloat().else {\r\n throw(GrabException())\r\n }\r\n }\r\n\r\n first(): Option[Char] {\r\n if(self.size() > 0) {\r\n Char(self!->charCodeAt(0)?)\r\n }\r\n }\r\n\r\n last(): Option[Char] {\r\n if(self.size() > 0) {\r\n Char(self!->charCodeAt(self.size() - 1)?)\r\n }\r\n }\r\n\r\n grabFirst(): Char {\r\n self.first().else {\r\n throw(GrabException())\r\n }\r\n }\r\n\r\n grabLast(): Char {\r\n self.last().else {\r\n throw(GrabException())\r\n }\r\n }\r\n\r\n contains(substring: String): Bool {\r\n self!->includes(substring)?\r\n }\r\n\r\n startsWith(prefix: String, offset: Int = 0): Bool {\r\n self!->startsWith(prefix, offset)?\r\n }\r\n\r\n endsWith(suffix: String): Bool {\r\n self!->endsWith(suffix)?\r\n }\r\n\r\n removeFirst(prefix: String): Option[String] {\r\n if(self.startsWith(prefix)) {Some(self.dropFirst(prefix.size()))} else {None}\r\n }\r\n\r\n removeLast(suffix: String): Option[String] {\r\n if(self.endsWith(suffix)) {Some(self.dropLast(suffix.size()))} else {None}\r\n }\r\n \r\n padStart(length: Int, padding: String = \" \"): String {\r\n self!->padStart(length, padding)?\r\n }\r\n\r\n padEnd(length: Int, padding: String = \" \"): String {\r\n self!->padEnd(length, padding)?\r\n }\r\n \r\n each(body: Char => Unit): Unit {\r\n mutable i = 0\r\n while {i < self.size()} {\r\n body(Char(self!->charCodeAt(i)?))\r\n i += 1\r\n }\r\n }\r\n\r\n eachWhile(body: Char => Bool): Unit {\r\n mutable i = 0\r\n while {i < self.size()} {\r\n if(body(Char(self!->charCodeAt(i)?))) {\r\n i += 1\r\n } else {\r\n i = self.size()\r\n }\r\n }\r\n } \r\n \r\n all(body: Char => Bool): Bool {\r\n mutable result = True\r\n self.eachWhile {x =>\r\n result = body(x)\r\n result\r\n }\r\n result\r\n }\r\n\r\n any(body: Char => Bool): Bool {\r\n mutable result = False\r\n self.eachWhile {x =>\r\n result = body(x)\r\n (!result)\r\n }\r\n result\r\n }\r\n \r\n find(body: Char => Bool): Option[Char] {\r\n mutable result = None\r\n self.eachWhile {x =>\r\n if(body(x)) {\r\n result = Some(x)\r\n False\r\n } else {\r\n True\r\n }\r\n }\r\n result\r\n }\r\n\r\n indexOf(needle: String, position: Int = 0): Option[Int] {\r\n let index = self!->indexOf(needle, position)?\r\n if(index != -1) {index}\r\n }\r\n \r\n indexWhere(body: Char => Bool): Option[Int] {\r\n mutable i = -1\r\n mutable result = False\r\n self.eachWhile {x =>\r\n i += 1\r\n result = body(x)\r\n (!result)\r\n }\r\n if(result) {i}\r\n } \r\n \r\n filter(body: Char => Bool): String {\r\n let result = Array.new()\r\n self.each {x =>\r\n if(body(x)) {\r\n result.push(x.toString())\r\n }\r\n }\r\n result.join()\r\n } \r\n\r\n toBuffer(): Buffer {\r\n let encoded = Js->TextEncoder->()->encode(self)\r\n Js->DataView->(encoded->buffer, encoded->byteOffset, encoded->byteLength)?\r\n }\r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/StringMap.ff"
4
+ "../../../../core/StringMap.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "class StringMap[V] {}\r\n\r\nnew[V](): StringMap[V] {\r\n Js->Map->()?\r\n}\r\n \r\nextend self[V]: StringMap[V] {\r\n\r\n get(key: String): Option[V] {\r\n let result = self!->get(key)\r\n if(!result.isUndefined() || self!->has(key)?) {result?}\r\n }\r\n\r\n grab(key: String): V {\r\n let result = self!->get(key)\r\n if(result.isUndefined() && !self.has(key)) {throw(GrabException())}\r\n result?\r\n }\r\n \r\n set(key: String, value: V): Unit {\r\n self!->set(key, value!)\r\n }\r\n\r\n has(key: String): Bool {\r\n self!->has(key)?\r\n }\r\n\r\n remove(key: String): Bool {\r\n self!->delete(key)?\r\n }\r\n\r\n clear(): Unit {\r\n self!->clear()\r\n }\r\n\r\n size(): Int {\r\n self!->size?\r\n }\r\n \r\n isEmpty(): Bool {\r\n self.size() == 0\r\n }\r\n\r\n each(body: (String, V) => Unit): Unit {\r\n if(Js.inAsync()) {\r\n let iterator = self!->entries()\r\n mutable result = iterator->next()\r\n while {!result->done?} {\r\n let value = result->value\r\n body(value.get(0)?, value.get(1)?)\r\n result = iterator->next()\r\n }\r\n } else {\r\n self!->forEach(Js->{v, k => body(k?, v?)})\r\n }\r\n }\r\n \r\n eachWhile(body: (String, V) => Bool): Unit {\r\n self!.eachWhile {value =>\r\n body(value.get(0)?, value.get(1)?)\r\n }\r\n }\r\n \r\n toArray(): Array[Pair[String, V]] {\r\n let array = Array.new()\r\n self.each {k, v => array.push(Pair(k, v))}\r\n array\r\n }\r\n\r\n toList(): List[Pair[String, V]] {\r\n self.toArray().drain()\r\n }\r\n\r\n toStream(): Stream[Pair[String, V]] {\r\n self.toList().toStream()\r\n }\r\n\r\n toMap(): Map[String, V] {\r\n self.toList().toMap()\r\n }\r\n\r\n keys(): List[String] {\r\n let array = Array.new()\r\n self.each {k, v => array.push(k)}\r\n array.drain()\r\n }\r\n\r\n values(): List[V] {\r\n let array = Array.new()\r\n self.each {k, v => array.push(v)}\r\n array.drain()\r\n }\r\n\r\n copy(): StringMap[V] {\r\n Js->Map->(self!)?\r\n }\r\n\r\n getOrSet(key: String, body: () => V): V {\r\n if(!self.has(key)) {self.set(key, body())}\r\n self.grab(key)\r\n }\r\n \r\n}\r\n\r\nextend self[V]: StringMap[Array[V]] {\r\n\r\n push(key: String, value: V) {\r\n self.get(key).{\r\n | None => self.set(key, [value].toArray())\r\n | Some(array) => array.push(value)\r\n }\r\n }\r\n\r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/Task.ff"
4
+ "../../../../core/Task.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "capability Task(\r\n mutable controller: JsValue\r\n subtasks: JsValue\r\n mutable promise: JsValue\r\n started: Duration\r\n)\r\n\r\nextend self: Task {\r\n\r\n // Spawns a task running body. The return value as well as the argument to body is the task handle.\r\n // Automatically aborts and then joins subtasks when body returns or throws an unhandled exception.\r\n // If body throws, the parent task is also aborted with the dueToSubtask flag set to true.\r\n spawn(body: Task => Unit): Task {\r\n self.throwIfAborted()\r\n let task = Task(\r\n controller = Js->AbortController->()\r\n subtasks = Js->Set->()\r\n promise = Js.undefined()\r\n started = Duration(Js->performance->now()? * 0.001)\r\n )\r\n self.subtasks->add(task!)\r\n task.promise = Js->Promise->resolve(task!)->then(Js.async0 {\r\n try {\r\n Js.await(body!.callValue2(task!, task!))\r\n } tryCatchAny {e => \r\n Js.await(self.controller->abort())\r\n e.rethrow()\r\n } finally {\r\n task.subtasks.each {subtask => \r\n Js.fromValue[Task](subtask).controller->abort()\r\n }\r\n Js.await(Js->Promise->allSettled(\r\n task.subtasks.spreadToArray().map {subtask => \r\n Js.fromValue[Task](subtask).promise\r\n } \r\n ))\r\n self.subtasks->delete(task!)\r\n }\r\n })\r\n task\r\n }\r\n\r\n // If the aborted flag is set for the current task, clears it and throws TaskAbortedException.\r\n // You don't normally need to call this, but you might want to before doing an expensive computation.\r\n throwIfAborted(): Unit {\r\n let signal = self.controller->signal\r\n if(signal->aborted?) {\r\n self.controller = Js->AbortController->()\r\n signal->throwIfAborted()\r\n }\r\n }\r\n\r\n // Sets the tasks aborted flag, which causes the ongoing/next async call to throw TaskAbortedException.\r\n abort(): Unit {\r\n self.controller->abort()\r\n }\r\n \r\n // Create a blocking channel with the specified capacity. The channel is not tied to the task.\r\n channel[T](capacity: Int = 0): Channel[T] {\r\n Channel(\r\n capacity = capacity\r\n buffer = Array.new()\r\n readers = Js->Set->()\r\n writers = Js->Set->()\r\n )\r\n }\r\n\r\n // Create a mutex. The mutex is not tied to the task.\r\n lock(): Lock {\r\n Lock(\r\n owner = Js.undefined()\r\n level = 0\r\n queue = Queue.new()\r\n )\r\n }\r\n \r\n elapsed(): Duration {\r\n let now = Js->performance->now()? * 0.001\r\n Duration(now - self.started.seconds)\r\n }\r\n\r\n time[R](body: () => R): Pair[R, Duration] {\r\n let start = self.elapsed()\r\n let result = body()\r\n let stop = self.elapsed()\r\n let duration = Duration(stop.seconds - start.seconds)\r\n Pair(result, duration)\r\n }\r\n\r\n}\r\n\r\n// Convenience methods\r\nextend self: Task {\r\n\r\n sleep(duration: Duration): Unit {\r\n Channel.\r\n readOr(self.channel()) {_ => }.\r\n timeout(duration) {}\r\n }\r\n \r\n mapList[T, R](list: List[T], body: T => R): List[R] {\r\n self.all(list.map {x => {body(x)}})\r\n }\r\n \r\n raceList[T, R](list: List[T], body: T => R): R {\r\n self.race(list.map {x => {body(x)}})\r\n }\r\n\r\n all[T](tasks: List[() => T]): List[T] {\r\n let successChannel = self.channel()\r\n let failureChannel = self.channel()\r\n self.spawn {t =>\r\n let channel = t.channel()\r\n try {\r\n tasks.pairs().each {| Pair(i, task) =>\r\n t.spawn {_ =>\r\n channel.write(Pair(i, task()))\r\n }\r\n }\r\n let result = tasks.map {_ =>\r\n channel.read()\r\n }.sortBy {_.first}.map {_.second}\r\n successChannel.write(result)\r\n } catchAny {error =>\r\n failureChannel.write(error)\r\n t.abort()\r\n }\r\n }\r\n Channel.\r\n readOr(successChannel, {_}).\r\n readOr(failureChannel, {_.rethrow()}).\r\n wait()\r\n }\r\n\r\n race[T](tasks: List[() => T]): T {\r\n let successChannel = self.channel()\r\n let failureChannel = self.channel()\r\n mutable live = tasks.size()\r\n let started = tasks.map {task =>\r\n self.spawn {_ =>\r\n try {\r\n successChannel.write(task())\r\n } catchAny {e =>\r\n live -= 1 // Not thread safe (but OK in JS)\r\n if(live == 0) {\r\n failureChannel.write(e)\r\n }\r\n }\r\n }\r\n }\r\n try {\r\n Channel.\r\n readOr(successChannel, {_}).\r\n readOr(failureChannel, {_.rethrow()}).\r\n wait()\r\n } finally {\r\n started.each {_.abort()}\r\n }\r\n }\r\n \r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/Try.ff"
4
+ "../../../../core/Try.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "data Try[T] {\r\n Success(value: T)\r\n Failure(error: Error)\r\n}\r\n\r\nextend self[T]: Try[T] {\r\n\r\n map[S](body: T => S): Try[S] {\r\n self.{\r\n | Success(value) => try {body(value)}\r\n | Failure(error) => Failure(error)\r\n }\r\n }\r\n\r\n flatMap[S](body: T => Try[S]): Try[S] {\r\n self.map(body).flatten()\r\n }\r\n\r\n catch[E: HasAnyTag](body: (E, Error) => T): T {\r\n self.{\r\n | Failure(error) {error.exception().flatMap(Any.fromAny) | Some(e)} => body(e, error)\r\n | _ => self.grab()\r\n }\r\n }\r\n\r\n catchAny(body: Error => T): T {\r\n self.{\r\n | Failure(error) => body(error)\r\n | _ => self.grab()\r\n }\r\n }\r\n\r\n finally(body: () => Unit): T {\r\n self.{\r\n | Success(value) => body(); value\r\n | Failure(_) => body(); self.grab()\r\n }\r\n }\r\n\r\n tryCatch[E: HasAnyTag](body: (E, Error) => T): Try[T] {\r\n self.{\r\n | Failure(error) {error.exception().flatMap(Any.fromAny) | Some(e)} => try {body(e, error)}\r\n | _ => self\r\n }\r\n }\r\n\r\n tryCatchAny(body: Error => T): Try[T] {\r\n self.{\r\n | Failure(error) => try {body(error)}\r\n | _ => self\r\n }\r\n }\r\n\r\n tryFinally(body: () => Unit): Try[T] {\r\n self.{\r\n | Success(value) => try {body(); value}\r\n | Failure(_) =>\r\n try {body()}.{\r\n | Success(_) => self\r\n | Failure(error) => Failure(error)\r\n }\r\n }\r\n }\r\n \r\n else(body: () => T): T {\r\n self.{\r\n | Success(value) => value\r\n | Failure(_) => body()\r\n }\r\n }\r\n\r\n grab(): T {\r\n self.{\r\n | Success(value) => value\r\n | Failure(error) => error.rethrow()\r\n }\r\n }\r\n\r\n toOption(): Option[T] {\r\n self.{\r\n | Success(value) => Some(value)\r\n | Failure(_) => None\r\n }\r\n }\r\n\r\n}\r\n\r\nextend self[T]: Try[Try[T]] {\r\n\r\n flatten(): Try[T] {\r\n self.{\r\n | Success(Success(_)@t) => t\r\n | Success(Failure(_)@t) => t\r\n | Failure(error) => Failure(error)\r\n }\r\n }\r\n\r\n}\r\n\r\ninternalThrowGrabException[T](): T {\r\n throw(GrabException())\r\n}\r\n"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": [
4
- "../../../../../core/Unit.ff"
4
+ "../../../../core/Unit.ff"
5
5
  ],
6
6
  "sourcesContent": [
7
7
  "data Unit {\r\n Unit\r\n}\r\n"
@@ -0,0 +1 @@
1
+ /Users/ahnfelt/Downloads/firefly-boot/core/.firefly/include/node_modules
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.5.79",
7
+ "version": "0.5.80",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"
@@ -4,7 +4,7 @@
4
4
  "description": "Firefly language support",
5
5
  "author": "Firefly team",
6
6
  "license": "MIT",
7
- "version": "0.5.79",
7
+ "version": "0.5.80",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "dependencies": {
3
- "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.51.0"
3
+ "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.52.0"
4
4
  }
5
5
  }
@@ -142,14 +142,17 @@ extend self: WebServer {
142
142
  internalResolveFlush = Js.null()
143
143
  internalContentSize = -1
144
144
  internalResponded = False
145
- );
145
+ )
146
146
  handler(webRequest)
147
147
  task.throwIfAborted()
148
- if(context.nullish() && !webRequest.internalResponded && webRequest.internalContentSize >= 0) {
148
+ if(
149
+ context.nullish() &&
150
+ !webRequest.internalResponded && webRequest.internalContentSize >= 0 && !abortedByUws
151
+ ) {
149
152
  webRequest.flush()
150
153
  task.throwIfAborted()
151
154
  }
152
- if(context.nullish() && !webRequest.internalResponded) {
155
+ if(context.nullish() && !webRequest.internalResponded && !abortedByUws) {
153
156
  Js.awaitCancellablePromise {resolve, reject, onSettle =>
154
157
  res->cork(Js->{
155
158
  try {