firefly-compiler 0.4.4

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 (221) hide show
  1. package/.firefly-workspace +1 -0
  2. package/.vscode/settings.json +5 -0
  3. package/LICENSE.txt +21 -0
  4. package/README.md +96 -0
  5. package/bin/firefly.mjs +2 -0
  6. package/compiler/.firefly/package.ff +1 -0
  7. package/compiler/Builder.ff +218 -0
  8. package/compiler/Compiler.ff +241 -0
  9. package/compiler/Dependencies.ff +179 -0
  10. package/compiler/Deriver.ff +647 -0
  11. package/compiler/Dictionaries.ff +205 -0
  12. package/compiler/Environment.ff +166 -0
  13. package/compiler/Inference.ff +1117 -0
  14. package/compiler/JsEmitter.ff +861 -0
  15. package/compiler/JsImporter.ff +56 -0
  16. package/compiler/LspHook.ff +188 -0
  17. package/compiler/Main.ff +237 -0
  18. package/compiler/Parser.ff +1383 -0
  19. package/compiler/Patterns.ff +111 -0
  20. package/compiler/Resolver.ff +620 -0
  21. package/compiler/Substitution.ff +178 -0
  22. package/compiler/Syntax.ff +299 -0
  23. package/compiler/Token.ff +180 -0
  24. package/compiler/Tokenizer.ff +278 -0
  25. package/compiler/Unification.ff +220 -0
  26. package/compiler/Wildcards.ff +50 -0
  27. package/compiler/Workspace.ff +88 -0
  28. package/core/.firefly/package.ff +2 -0
  29. package/core/Any.ff +30 -0
  30. package/core/Array.ff +249 -0
  31. package/core/AssetSystem.ff +61 -0
  32. package/core/Atomic.ff +64 -0
  33. package/core/Bool.ff +13 -0
  34. package/core/BrowserSystem.ff +14 -0
  35. package/core/Buffer.ff +211 -0
  36. package/core/BuildSystem.ff +144 -0
  37. package/core/Channel.ff +131 -0
  38. package/core/Char.ff +18 -0
  39. package/core/Core.ff +58 -0
  40. package/core/Duration.ff +15 -0
  41. package/core/Equal.ff +52 -0
  42. package/core/Error.ff +20 -0
  43. package/core/FileHandle.ff +41 -0
  44. package/core/Float.ff +41 -0
  45. package/core/HttpClient.ff +84 -0
  46. package/core/Instant.ff +9 -0
  47. package/core/Int.ff +61 -0
  48. package/core/IntMap.ff +85 -0
  49. package/core/JsSystem.ff +66 -0
  50. package/core/JsValue.ff +240 -0
  51. package/core/List.ff +440 -0
  52. package/core/Lock.ff +144 -0
  53. package/core/Log.ff +24 -0
  54. package/core/Map.ff +126 -0
  55. package/core/NodeSystem.ff +88 -0
  56. package/core/Nothing.ff +1 -0
  57. package/core/Option.ff +133 -0
  58. package/core/Ordering.ff +157 -0
  59. package/core/Pair.ff +55 -0
  60. package/core/Path.ff +393 -0
  61. package/core/RbMap.ff +216 -0
  62. package/core/Serializable.ff +173 -0
  63. package/core/Set.ff +38 -0
  64. package/core/Show.ff +43 -0
  65. package/core/Stack.ff +263 -0
  66. package/core/Stream.ff +406 -0
  67. package/core/String.ff +175 -0
  68. package/core/StringMap.ff +85 -0
  69. package/core/Task.ff +138 -0
  70. package/core/Try.ff +81 -0
  71. package/core/Unit.ff +3 -0
  72. package/experimental/random/AltGeneric.ff +44 -0
  73. package/experimental/random/Async.ff +68 -0
  74. package/experimental/random/Buffer2.ff +77 -0
  75. package/experimental/random/Cat.ff +12 -0
  76. package/experimental/random/Dictionary.ff +52 -0
  77. package/experimental/random/Example.ff +46 -0
  78. package/experimental/random/Generic.ff +102 -0
  79. package/experimental/random/HappyEyeballs.ff +40 -0
  80. package/experimental/random/HashMap.ff +72 -0
  81. package/experimental/random/IfElseUnit.ff +9 -0
  82. package/experimental/random/InputOutput.ff +23 -0
  83. package/experimental/random/ListVsArray.ff +45 -0
  84. package/experimental/random/Main.ff +44 -0
  85. package/experimental/random/MapTest.ff +67 -0
  86. package/experimental/random/OldTaskSystem.ff +210 -0
  87. package/experimental/random/PatternTest.ff +39 -0
  88. package/experimental/random/Patterns.ff +226 -0
  89. package/experimental/random/ReadBytesTest.ff +10 -0
  90. package/experimental/random/RunLength.ff +65 -0
  91. package/experimental/random/Scrape.ff +51 -0
  92. package/experimental/random/Serialization.ff +217 -0
  93. package/experimental/random/SerializationTest.ff +46 -0
  94. package/experimental/random/Serializer.ff +36 -0
  95. package/experimental/random/StdInOutErr.ff +4 -0
  96. package/experimental/random/Symbols.ff +74 -0
  97. package/experimental/random/Tag.ff +49 -0
  98. package/experimental/random/Tensor.ff +52 -0
  99. package/experimental/random/Try.ff +56 -0
  100. package/experimental/random/Tsv.ff +9 -0
  101. package/experimental/random/TypesAreModules.ff +87 -0
  102. package/experimental/random/blueprints/Blueprint.ff +52 -0
  103. package/experimental/random/blueprints/Main.ff +11 -0
  104. package/experimental/random/blueprints/Pretty.ff +58 -0
  105. package/experimental/random/blueprints/User.ff +64 -0
  106. package/experimental/random/blueprintsystem/BlueprintSystem.ff +48 -0
  107. package/experimental/random/blueprintsystem/Deserialize.ff +53 -0
  108. package/experimental/random/blueprintsystem/ReadJs.ff +13 -0
  109. package/experimental/random/blueprintsystem/User.ff +2 -0
  110. package/experimental/random/kahrs/Kahrs.ff +112 -0
  111. package/experimental/random/kahrs/TestKahrs.ff +22 -0
  112. package/experimental/random/kahrs/TestMap.ff +18 -0
  113. package/experimental/random/streaming/Gzip.ff +3 -0
  114. package/experimental/random/streaming/Main.ff +34 -0
  115. package/experimental/random/streaming/S3Bucket.ff +11 -0
  116. package/experimental/random/streaming/Tar.ff +5 -0
  117. package/experimental/rhymeapp/Main.ff +81 -0
  118. package/experimental/rhymeapp/index.html +14 -0
  119. package/firefly.sh +5 -0
  120. package/fireflysite/Main.ff +13 -0
  121. package/httpserver/.firefly/package.ff +1 -0
  122. package/httpserver/HttpServer.ff +184 -0
  123. package/lsp/.firefly/package.ff +1 -0
  124. package/lsp/CompletionHandler.ff +814 -0
  125. package/lsp/Handler.ff +551 -0
  126. package/lsp/HoverHandler.ff +82 -0
  127. package/lsp/LanguageServer.ff +229 -0
  128. package/lsp/SignatureHelpHandler.ff +55 -0
  129. package/lsp/SymbolHandler.ff +167 -0
  130. package/output/js/ff/compiler/Builder.mjs +483 -0
  131. package/output/js/ff/compiler/Compiler.mjs +410 -0
  132. package/output/js/ff/compiler/Dependencies.mjs +388 -0
  133. package/output/js/ff/compiler/Deriver.mjs +1166 -0
  134. package/output/js/ff/compiler/Dictionaries.mjs +1305 -0
  135. package/output/js/ff/compiler/Environment.mjs +1005 -0
  136. package/output/js/ff/compiler/Inference.mjs +4264 -0
  137. package/output/js/ff/compiler/JsEmitter.mjs +5353 -0
  138. package/output/js/ff/compiler/JsImporter.mjs +262 -0
  139. package/output/js/ff/compiler/LspHook.mjs +789 -0
  140. package/output/js/ff/compiler/Main.mjs +1695 -0
  141. package/output/js/ff/compiler/Parser.mjs +4004 -0
  142. package/output/js/ff/compiler/Patterns.mjs +923 -0
  143. package/output/js/ff/compiler/Resolver.mjs +2303 -0
  144. package/output/js/ff/compiler/Substitution.mjs +1146 -0
  145. package/output/js/ff/compiler/Syntax.mjs +12430 -0
  146. package/output/js/ff/compiler/Token.mjs +3092 -0
  147. package/output/js/ff/compiler/Tokenizer.mjs +589 -0
  148. package/output/js/ff/compiler/Unification.mjs +1748 -0
  149. package/output/js/ff/compiler/Wildcards.mjs +604 -0
  150. package/output/js/ff/compiler/Workspace.mjs +683 -0
  151. package/output/js/ff/core/Any.mjs +139 -0
  152. package/output/js/ff/core/Array.mjs +594 -0
  153. package/output/js/ff/core/AssetSystem.mjs +270 -0
  154. package/output/js/ff/core/Atomic.mjs +186 -0
  155. package/output/js/ff/core/Bool.mjs +141 -0
  156. package/output/js/ff/core/BrowserSystem.mjs +122 -0
  157. package/output/js/ff/core/Buffer.mjs +467 -0
  158. package/output/js/ff/core/BuildSystem.mjs +320 -0
  159. package/output/js/ff/core/Channel.mjs +268 -0
  160. package/output/js/ff/core/Char.mjs +145 -0
  161. package/output/js/ff/core/Core.mjs +300 -0
  162. package/output/js/ff/core/Duration.mjs +112 -0
  163. package/output/js/ff/core/Equal.mjs +175 -0
  164. package/output/js/ff/core/Error.mjs +138 -0
  165. package/output/js/ff/core/FileHandle.mjs +164 -0
  166. package/output/js/ff/core/Float.mjs +214 -0
  167. package/output/js/ff/core/HttpClient.mjs +210 -0
  168. package/output/js/ff/core/Instant.mjs +105 -0
  169. package/output/js/ff/core/Int.mjs +254 -0
  170. package/output/js/ff/core/IntMap.mjs +282 -0
  171. package/output/js/ff/core/JsSystem.mjs +234 -0
  172. package/output/js/ff/core/JsValue.mjs +678 -0
  173. package/output/js/ff/core/List.mjs +2335 -0
  174. package/output/js/ff/core/Lock.mjs +322 -0
  175. package/output/js/ff/core/Log.mjs +159 -0
  176. package/output/js/ff/core/Map.mjs +358 -0
  177. package/output/js/ff/core/NodeSystem.mjs +288 -0
  178. package/output/js/ff/core/Nothing.mjs +100 -0
  179. package/output/js/ff/core/Option.mjs +1002 -0
  180. package/output/js/ff/core/Ordering.mjs +734 -0
  181. package/output/js/ff/core/Pair.mjs +318 -0
  182. package/output/js/ff/core/Path.mjs +768 -0
  183. package/output/js/ff/core/RbMap.mjs +1936 -0
  184. package/output/js/ff/core/Serializable.mjs +434 -0
  185. package/output/js/ff/core/Set.mjs +250 -0
  186. package/output/js/ff/core/Show.mjs +201 -0
  187. package/output/js/ff/core/Stack.mjs +595 -0
  188. package/output/js/ff/core/Stream.mjs +1300 -0
  189. package/output/js/ff/core/String.mjs +433 -0
  190. package/output/js/ff/core/StringMap.mjs +282 -0
  191. package/output/js/ff/core/Task.mjs +345 -0
  192. package/output/js/ff/core/Try.mjs +503 -0
  193. package/output/js/ff/core/Unit.mjs +103 -0
  194. package/package.json +29 -0
  195. package/postgresql/.firefly/include/package-lock.json +250 -0
  196. package/postgresql/.firefly/include/package.json +5 -0
  197. package/postgresql/.firefly/include/prepare.sh +2 -0
  198. package/postgresql/.firefly/package.ff +3 -0
  199. package/postgresql/Pg.ff +530 -0
  200. package/unsafejs/.firefly/package.ff +1 -0
  201. package/unsafejs/UnsafeJs.ff +19 -0
  202. package/vscode/.vscode/launch.json +18 -0
  203. package/vscode/.vscode/tasks.json +33 -0
  204. package/vscode/LICENSE.txt +21 -0
  205. package/vscode/Prepublish.ff +15 -0
  206. package/vscode/README.md +17 -0
  207. package/vscode/client/package-lock.json +544 -0
  208. package/vscode/client/package.json +22 -0
  209. package/vscode/client/src/extension.ts +64 -0
  210. package/vscode/client/tsconfig.json +12 -0
  211. package/vscode/icons/firefly-icon.png +0 -0
  212. package/vscode/icons/firefly-icon.svg +10 -0
  213. package/vscode/icons/firefly-logo-notext.png +0 -0
  214. package/vscode/icons/firefly-logo.png +0 -0
  215. package/vscode/language-configuration.json +39 -0
  216. package/vscode/package-lock.json +3623 -0
  217. package/vscode/package.json +144 -0
  218. package/vscode/snippets-none.json +1 -0
  219. package/vscode/snippets.json +241 -0
  220. package/vscode/syntaxes/firefly.tmLanguage.json +294 -0
  221. package/vscode/tsconfig.json +20 -0
package/core/Map.ff ADDED
@@ -0,0 +1,126 @@
1
+ import RbMap
2
+
3
+ newtype Map[K, V](redBlack: RB[K, V])
4
+
5
+ empty[K, V](): Map[K, V] {Map(E)}
6
+
7
+ extend self[K: Order, V]: Map[K, V] {
8
+
9
+ add(key: K, value: V): Map[K, V] {
10
+ Map(RbMap.insert(key, value, self.redBlack))
11
+ }
12
+
13
+ addAll(that: Map[K, V]): Map[K, V] {
14
+ mutable result = self.redBlack
15
+ that.redBlack.each {k, v =>
16
+ result = RbMap.insert(k, v, result)
17
+ }
18
+ Map(result)
19
+ }
20
+
21
+ get(key: K): Option[V] {
22
+ self.redBlack.get(key)
23
+ }
24
+
25
+ remove(key: K): Map[K, V] {
26
+ Map(RbMap.delete(key, self.redBlack))
27
+ }
28
+
29
+ removeAll(that: Map[K, V]): Map[K, V] {
30
+ mutable result = self.redBlack
31
+ that.redBlack.each {| k, _ =>
32
+ result = RbMap.delete(k, result)
33
+ }
34
+ Map(result)
35
+ }
36
+
37
+ pairs(): List[Pair[K, V]] { // TODO: Remove this method (use toList)
38
+ self.toList()
39
+ }
40
+
41
+ toList(): List[Pair[K, V]] {
42
+ self.redBlack.pairs()
43
+ }
44
+
45
+ toArray(): Array[Pair[K, V]] {
46
+ self.redBlack.pairs().toArray() // TODO: Avoid going through List
47
+ }
48
+
49
+ toStream(cycle: Bool = False): Stream[Pair[K, V]] {
50
+ self.redBlack.toStream(cycle)
51
+ }
52
+
53
+ keys(): Set[K] {
54
+ self.pairs().map {_.first}.toSet()
55
+ }
56
+
57
+ values(): List[V] {
58
+ self.pairs().map {_.second}
59
+ }
60
+
61
+ size(): Int {
62
+ self.redBlack.size()
63
+ }
64
+
65
+ map[K1: Order, V1](body: (K, V) => Pair[K1, V1]): Map[K1, V1] {
66
+ Map(self.redBlack.map(body))
67
+ }
68
+
69
+ mapValues[V1](body: (K, V) => V1): Map[K, V1] {
70
+ Map(self.redBlack.mapValues(body))
71
+ }
72
+
73
+ contains(key: K): Bool {
74
+ !self.get(key).isEmpty()
75
+ }
76
+
77
+ grab(key: K): V {
78
+ self.get(key).grab()
79
+ }
80
+
81
+ updateOrInsert(key: K, update: V => V, default: () => V): Map[K, V] {
82
+ self.get(key).{
83
+ | None => self.add(key, default())
84
+ | Some(v) => self.add(key, update(v))
85
+ }
86
+ }
87
+
88
+ each(body: (K, V) => Unit): Unit {
89
+ self.redBlack.each(body)
90
+ }
91
+
92
+ eachWhile(body: (K, V) => Bool): Bool {
93
+ self.redBlack.eachWhile(body)
94
+ }
95
+
96
+ find(body: (K, V) => Bool): Option[Pair[K, V]] {
97
+ self.redBlack.find(body)
98
+ }
99
+
100
+ }
101
+
102
+ extend self[K: Order, V]: Map[K, List[V]] {
103
+
104
+ addToList(key: K, value: V): Map[K, List[V]] {
105
+ self.updateOrInsert(key, {[value, ..._]}, {[value]})
106
+ }
107
+
108
+ }
109
+
110
+ instance Map[K: Equal: Order, V: Equal]: Equal {
111
+ equals(x: Map[K, V], y: Map[K, V]): Bool {
112
+ Equal.equals(x.pairs(), y.pairs())
113
+ }
114
+ }
115
+
116
+ instance Map[K: Order, V: Order]: Order {
117
+ compare(x: Map[K, V], y: Map[K, V]): Ordering {
118
+ Ordering.compare(x.pairs(), y.pairs())
119
+ }
120
+ }
121
+
122
+ instance Map[K: Show: Order, V: Show]: Show {
123
+ show(value: Map[K, V]): String {
124
+ Show.show(value.pairs()) + ".toMap()"
125
+ }
126
+ }
@@ -0,0 +1,88 @@
1
+ capability NodeSystem {}
2
+
3
+ extend self: NodeSystem {
4
+
5
+ arguments(): Array[String]
6
+ target node async "return self_.array_"
7
+
8
+ assets(): AssetSystem {
9
+ let assetPkgSnapshotPath = self.path("/snapshot/output/assets")
10
+ if(assetPkgSnapshotPath.isDirectory()) {
11
+ function streams(path: Path): Stream[Pair[String, () => Stream[Buffer]]] {
12
+ path.entries().flatMap {file =>
13
+ if(file.isDirectory()) {
14
+ streams(file.path())
15
+ } else {
16
+ [Pair(file.path().relativeTo(assetPkgSnapshotPath), {file.path().readStream()})].toStream()
17
+ }
18
+ }
19
+ }
20
+ AssetSystem(streams(assetPkgSnapshotPath).toMap())
21
+ } else {
22
+ internalAssets(self)
23
+ }
24
+ }
25
+
26
+ path(relativePath: String): Path
27
+ target node async """
28
+ import * as path from 'path'
29
+ return path.resolve(relativePath_)
30
+ """
31
+
32
+ pathFromUrl(url: String): Path
33
+ target node async """
34
+ import * as url from 'url';
35
+ return url.fileURLToPath(new URL(url_));
36
+ """
37
+
38
+ httpClient(): HttpClient
39
+ target js async "return null"
40
+
41
+ mainTask(): Task
42
+ target js async "return self_.task_"
43
+
44
+ js(): JsSystem
45
+ target js async "return typeof globalThis !== 'undefined' ? globalThis : window"
46
+
47
+ exit[T](exitCode: Int = 0): T
48
+ target js async "process.exit(exitCode_)"
49
+
50
+ readStream(): Stream[Buffer]
51
+ target js async """
52
+ return ff_core_Path.internalReadStream_$(() => process.stdin)
53
+ """
54
+
55
+ writeBuffer(buffer: Buffer): Unit
56
+ target js async "process.stdout.write(new Uint8Array(buffer_.buffer, buffer_.byteOffset, buffer_.byteLength))"
57
+
58
+ writeStream(stream: Stream[Buffer]): Unit {
59
+ stream.each {self.writeBuffer(_)}
60
+ }
61
+
62
+ writeText(text: String): Unit {
63
+ self.writeBuffer(text.toBuffer())
64
+ }
65
+
66
+ writeLine(text: String): Unit {
67
+ self.writeText(text + "\n")
68
+ }
69
+
70
+ writeErrorBuffer(buffer: Buffer): Unit
71
+ target js async "process.stderr.write(new Uint8Array(buffer_.buffer, buffer_.byteOffset, buffer_.byteLength))"
72
+
73
+ writeErrorStream(stream: Stream[Buffer]): Unit {
74
+ stream.each {self.writeErrorBuffer(_)}
75
+ }
76
+
77
+ writeErrorText(text: String): Unit {
78
+ self.writeErrorBuffer(text.toBuffer())
79
+ }
80
+
81
+ writeErrorLine(text: String): Unit {
82
+ self.writeErrorText(text + "\n")
83
+ }
84
+
85
+ }
86
+
87
+ internalAssets(system: NodeSystem): AssetSystem
88
+ target node async "return system_.assets_"
@@ -0,0 +1 @@
1
+ data Nothing {}
package/core/Option.ff ADDED
@@ -0,0 +1,133 @@
1
+ data Option[T] {
2
+ None
3
+ Some(value: T)
4
+ }
5
+
6
+ extend self[T]: Option[T] {
7
+
8
+ else(body: () => T): T {
9
+ self.{
10
+ | None => body()
11
+ | Some(value) => value
12
+ }
13
+ }
14
+
15
+ elseIf(condition: () => Bool, body: () => T): Option[T] {
16
+ self.{
17
+ | None =>
18
+ condition().{
19
+ | True => Some(body())
20
+ | False => None
21
+ }
22
+ | Some(_) => self
23
+ }
24
+ }
25
+
26
+ orElse(body: () => Option[T]): Option[T] {
27
+ self.{
28
+ | None => body()
29
+ | Some(_) => self
30
+ }
31
+ }
32
+
33
+ isEmpty(): Bool {
34
+ self.{
35
+ | None => True
36
+ | Some(_) => False
37
+ }
38
+ }
39
+
40
+ toList(): List[T] {
41
+ self.{
42
+ | None => []
43
+ | Some(v) => [v]
44
+ }
45
+ }
46
+
47
+ toStack(): Stack[T] {
48
+ self.toList().toStack()
49
+ }
50
+
51
+ toArray(): Array[T] {
52
+ self.toList().toArray()
53
+ }
54
+
55
+ toStream(cycle: Bool = False): Stream[T] {
56
+ mutable next = self
57
+ Stream.make {
58
+ let result = next
59
+ if(!cycle) {next = None}
60
+ result
61
+ }
62
+ }
63
+
64
+ filter(body: T => Bool): Option[T] {
65
+ self.{
66
+ | Some(v) {body(v)} => Some(v)
67
+ | _ => None
68
+ }
69
+ }
70
+
71
+ map[R](body: T => R): Option[R] {
72
+ self.{
73
+ | None => None
74
+ | Some(v) => Some(body(v))
75
+ }
76
+ }
77
+
78
+ flatMap[R](body: T => Option[R]): Option[R] {
79
+ self.{
80
+ | None => None
81
+ | Some(v) => body(v)
82
+ }
83
+ }
84
+
85
+ each(body: T => Unit): Unit {
86
+ self.{
87
+ | None =>
88
+ | Some(v) => body(v)
89
+ }
90
+ }
91
+
92
+ all(body: T => Bool): Bool {
93
+ self.{
94
+ | None => True
95
+ | Some(v) => body(v)
96
+ }
97
+ }
98
+
99
+ any(body: T => Bool): Bool {
100
+ self.{
101
+ | None => False
102
+ | Some(v) => body(v)
103
+ }
104
+ }
105
+
106
+ grab(): T {
107
+ self.{
108
+ | None => Try.internalThrowGrabException()
109
+ | Some(v) => v
110
+ }
111
+ }
112
+
113
+ }
114
+
115
+ extend self[T: Equal]: Option[T] {
116
+ contains(value: T): Bool {
117
+ self.{
118
+ | None => False
119
+ | Some(v) => v == value
120
+ }
121
+ }
122
+ }
123
+
124
+ extend self[T]: Option[Option[T]] {
125
+
126
+ flatten(): Option[T] {
127
+ self.{
128
+ | None => None
129
+ | Some(v) => v
130
+ }
131
+ }
132
+
133
+ }
@@ -0,0 +1,157 @@
1
+ trait T: Order {
2
+ compare(x: T, y: T): Ordering
3
+ }
4
+
5
+ before[T: Order](x: T, y: T): Bool {
6
+ compare(x, y) == OrderingBefore
7
+ }
8
+
9
+ notBefore[T: Order](x: T, y: T): Bool {
10
+ compare(x, y) != OrderingBefore
11
+ }
12
+
13
+ after[T: Order](x: T, y: T): Bool {
14
+ compare(x, y) == OrderingAfter
15
+ }
16
+
17
+ notAfter[T: Order](x: T, y: T): Bool {
18
+ compare(x, y) != OrderingAfter
19
+ }
20
+
21
+ reverse[T](compare: (T, T) => Ordering): (T, T) => Ordering {
22
+ {x, y => compare(x, y).{
23
+ | OrderingBefore => OrderingAfter
24
+ | OrderingSame => OrderingSame
25
+ | OrderingAfter => OrderingBefore
26
+ }}
27
+ }
28
+
29
+ pair[A, B](
30
+ compareFirst: (A, A) => Ordering
31
+ compareSecond: (B, B) => Ordering
32
+ ): (Pair[A, B], Pair[A, B]) => Ordering {
33
+ {x, y => compareFirst(x.first, y.first).{
34
+ | OrderingSame => compareSecond(x.second, y.second)
35
+ | ordering => ordering
36
+ }}
37
+ }
38
+
39
+ instance Nothing: Order {
40
+ compare(x: Nothing, y: Nothing): Ordering {OrderingSame}
41
+ }
42
+
43
+ instance Bool: Order {
44
+ compare(x: Bool, y: Bool): Ordering {
45
+ | False, True => OrderingBefore
46
+ | True, False => OrderingAfter
47
+ | _, _ => OrderingSame
48
+ }
49
+ }
50
+
51
+ instance Char: Order {
52
+ compare(x: Char, y: Char): Ordering {
53
+ fromInt(x.codeUnit - y.codeUnit)
54
+ }
55
+ }
56
+
57
+ instance Int: Order {
58
+ compare(x: Int, y: Int): Ordering {fromInt(x - y)}
59
+ }
60
+
61
+ instance Float: Order {
62
+ compare(x: Float, y: Float): Ordering {fromFloat(x - y)}
63
+ }
64
+
65
+ instance String: Order {
66
+ compare(x: String, y: String): Ordering
67
+ target js sync """
68
+ if(x_ < y_) {
69
+ return ff_core_Ordering.OrderingBefore()
70
+ } else if(x_ > y_) {
71
+ return ff_core_Ordering.OrderingAfter()
72
+ } else {
73
+ return ff_core_Ordering.OrderingSame()
74
+ }
75
+ """
76
+ }
77
+
78
+ instance Pair[A: Order, B: Order]: Order {
79
+ compare(x: Pair[A, B], y: Pair[A, B]): Ordering {
80
+ compare(x.first, y.first).{
81
+ | OrderingSame => compare(x.second, y.second)
82
+ | o => o
83
+ }
84
+ }
85
+ }
86
+
87
+ instance List[T: Order]: Order {
88
+ compare(x: List[T], y: List[T]): Ordering {
89
+ | [], [] => OrderingSame
90
+ | [], _ => OrderingBefore
91
+ | _, [] => OrderingAfter
92
+ | [a, ...as], [b, ...bs] => compare(a, b).{
93
+ | OrderingSame => compare(as, bs)
94
+ | o => o
95
+ }
96
+ }
97
+ }
98
+
99
+ data Ordering {
100
+ OrderingBefore
101
+ OrderingSame
102
+ OrderingAfter
103
+ }
104
+
105
+ instance Ordering: Equal {
106
+ equals(x: Ordering, y: Ordering): Bool {
107
+ | OrderingBefore, OrderingBefore => True
108
+ | OrderingSame, OrderingSame => True
109
+ | OrderingAfter, OrderingAfter => True
110
+ | _, _ => False
111
+ }
112
+ }
113
+
114
+ fromInt(order: Int): Ordering {
115
+ if(order < 0) {
116
+ OrderingBefore
117
+ } elseIf {order == 0} {
118
+ OrderingSame
119
+ } else {
120
+ OrderingAfter
121
+ }
122
+ }
123
+
124
+ fromFloat(order: Float): Ordering {
125
+ if(order < 0.0) {
126
+ OrderingBefore
127
+ } elseIf {order == 0.0} {
128
+ OrderingSame
129
+ } else {
130
+ OrderingAfter
131
+ }
132
+ }
133
+
134
+ fromLessThan[T](lessThan: (T, T) => Bool): (T, T) => Ordering {
135
+ {
136
+ | x, y {lessThan(x, y)} => OrderingBefore
137
+ | x, y {lessThan(y, x)} => OrderingAfter
138
+ | _, _ => OrderingSame
139
+ }
140
+ }
141
+
142
+ extend self: Ordering {
143
+ toInt(): Int {
144
+ self.{
145
+ | OrderingBefore => -1
146
+ | OrderingSame => 0
147
+ | OrderingAfter => 1
148
+ }
149
+ }
150
+ reverse(): Ordering {
151
+ self.{
152
+ | OrderingBefore => OrderingAfter
153
+ | OrderingSame => OrderingSame
154
+ | OrderingAfter => OrderingBefore
155
+ }
156
+ }
157
+ }
package/core/Pair.ff ADDED
@@ -0,0 +1,55 @@
1
+ data Pair[A, B](first: A, second: B) {
2
+ Pair()
3
+ }
4
+
5
+ extend self[A, B]: Pair[A, B] {
6
+
7
+ mapFirst[C](body: A => C): Pair[C, B] {
8
+ self.Pair(first = body(self.first))
9
+ }
10
+
11
+ mapSecond[C](body: B => C): Pair[A, C] {
12
+ self.Pair(second = body(self.second))
13
+ }
14
+
15
+ swap(): Pair[B, A] {
16
+ Pair(self.second, self.first)
17
+ }
18
+
19
+ }
20
+
21
+ extend self[A, A]: Pair[A, A] {
22
+
23
+ mapBoth[C](body: A => C): Pair[C, C] {
24
+ self.Pair(first = body(self.first), second = body(self.second))
25
+ }
26
+
27
+ toList(): List[A] {
28
+ [self.first, self.second]
29
+ }
30
+
31
+ toArray(): Array[A] {
32
+ self.toList().toArray()
33
+ }
34
+
35
+ toStack(): Stack[A] {
36
+ self.toList().toStack()
37
+ }
38
+
39
+ }
40
+
41
+ extend self[A: Order]: Pair[A, A] {
42
+
43
+ toSet(): Set[A] {
44
+ self.toList().toSet()
45
+ }
46
+
47
+ }
48
+
49
+ extend self[A: Order, B]: Pair[A, B] {
50
+
51
+ toMap(): Map[A, B] {
52
+ [self].toMap()
53
+ }
54
+
55
+ }