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
@@ -0,0 +1,74 @@
1
+ nodeMain(system: NodeSystem) {
2
+ /*
3
+ Log.show(splitCamelCased(""))
4
+ Log.show(splitCamelCased("ABC"))
5
+ Log.show(splitCamelCased("abc"))
6
+ Log.show(splitCamelCased("AbC"))
7
+ Log.show(splitCamelCased("AbCd"))
8
+ Log.show(splitCamelCased("aaBccDee"))
9
+ Log.show(splitCamelCased("AaBccDee"))
10
+
11
+ Log.show(prefixes(""))
12
+ Log.show(prefixes("abcde"))
13
+
14
+ test(["add", "addAll", "addToList"], "al")
15
+ test(["aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"], "abcdefghijklmnopqrstuvwxyz")
16
+ test(["aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"], "abcdefghijklmnopqrstuvwxyzA")
17
+ test(["aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"], "aabcdefghijklmnopqrstuvwxyz")
18
+ */
19
+ printTime(system.time(), "matchSymbol") {
20
+ Log.show(matchSymbol(splitCamelCased("aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ", True), "abcdefghijklmnopqrstuvwxyzA", True))
21
+ }
22
+
23
+ }
24
+
25
+ test(symbols: List[String], query: String) {
26
+ Log.debug("")
27
+ Log.debug("#" + query)
28
+ symbols.each {s =>
29
+ let symbolWords = splitCamelCased(s, True)
30
+ let match = matchSymbol(symbolWords, query, !query.any {_.isAsciiUpper()})
31
+ Log.debug(s + " (" + Show.show(symbolWords) + " ): " + Show.show(match))
32
+ }
33
+ }
34
+
35
+ matchSymbol(symbolWords: List[String], query: String, lower: Bool): Bool {
36
+ let memo: IntMap[IntMap[Bool]] = IntMap.make()
37
+ function go(wordIndex: Int, queryOffset: Int): Bool {
38
+ memo.getOrSet(wordIndex) {IntMap.make()}.getOrSet(queryOffset):
39
+ if(queryOffset >= query.size()) {True} else:
40
+ if(wordIndex >= symbolWords.size()) {False} else:
41
+ prefixes(query.dropFirst(queryOffset)).any {prefix =>
42
+ symbolWords.grab(wordIndex).startsWith(prefix) &&
43
+ go(wordIndex + 1, queryOffset + prefix.size())
44
+ }
45
+ }
46
+ go(0, 0)
47
+ }
48
+
49
+ prefixes(string: String): List[String] {
50
+ if(string == "") {
51
+ [""]
52
+ } else {
53
+ [string, ...prefixes(string.dropLast())]
54
+ }
55
+ }
56
+
57
+ splitCamelCased(name: String, lower: Bool): List[String] {
58
+ name.first().{
59
+ | None => []
60
+ | Some(c) =>
61
+ let word = c.toString() + name.dropFirst().takeWhile {_.isAsciiLower()}
62
+ let rest = name.dropFirst(word.size())
63
+ [if(lower) {word.lower()} else {word}, ...splitCamelCased(rest, lower)]
64
+ }
65
+ }
66
+
67
+ printTime[R](ts: TimeSystem, label: String, body: () => R): R {
68
+ let start = ts.elapsed()
69
+ let result = body()
70
+ let stop = ts.elapsed()
71
+ let duration = ("" + (stop.seconds - start.seconds)).slice(0, 5)
72
+ Log.trace(label + ": " + duration + "s")
73
+ result
74
+ }
@@ -0,0 +1,49 @@
1
+ // This may solve VDOM props, but what about "render props"?
2
+ // https://reactjs.org/docs/render-props.html
3
+
4
+ data Tag[M] {
5
+ ComponentTag(component: ComponentConstructor[M], key: Option[String])
6
+ ElementTag(name: String, tags: List[Tag[M]], key: Option[String])
7
+ AttributeTag(name: String, value: String)
8
+ StyleTag(name: String, value: String)
9
+ EventTag(name: String, value: M)
10
+ TextTag(text: String)
11
+ }
12
+
13
+ data ComponentConstructor[M]() {}
14
+
15
+ extend self: Tag[M] {
16
+ map[T](body: M => T): Tag[T] {
17
+ self.{
18
+ | ComponentTag(constructor, key) => ComponentTag(constructor.map(body), key) // How to compare this function
19
+ | ElementTag(name, tags, key) => ElementTag(name, tags.map(_.map(body)), key)
20
+ | AttributeTag(_, _) => self
21
+ | StyleTag(_, _) => self
22
+ | EventTag(name, value) => EventTag(name, body(value))
23
+ }
24
+ }
25
+ }
26
+
27
+ component[C: Component[M], M](value: C, key: Option[String] = None): Tag[M] {
28
+ panic("TODO")
29
+ }
30
+
31
+ element[M](name: String, tags: List[Tag[M]], key: Option[String] = None): Tag[M] {
32
+ ElementTag(name, tags, key)
33
+ }
34
+
35
+ attribute[M](name: String, value: String): Tag[M] {
36
+ AttributeTag(name, value)
37
+ }
38
+
39
+ style[M](name: String, value: String): Tag[M] {
40
+ StyleTag(name, value)
41
+ }
42
+
43
+ event[M](name: String, value: M): Tag[M] {
44
+ EventTag(name, value)
45
+ }
46
+
47
+ text[M](value: String): Tag[M] {
48
+ TextTag(value)
49
+ }
@@ -0,0 +1,52 @@
1
+ // Brainstorming representation for Tensors where the scalar types and operators are left open ended.
2
+ // The purpose of this type is to build up a syntax tree of tensor operations that can then be
3
+ // optimized and executed on CPU/GPU/TPU, enabling machine learning and other numerical applications.
4
+
5
+ data Tensor(scalar: String, shape: List[Int]) {
6
+ TensorVariable(name: String)
7
+ TensorInts(data: Array[Int])
8
+ TensorFloats(data: Array[Float])
9
+ TensorBuffer(data: Buffer)
10
+ TensorOperator(operator: String, operands: List[Tensor])
11
+ }
12
+
13
+ data TensorException(message: String)
14
+
15
+ capability TensorProcessor(
16
+ toFloats: Tensor => Array[Float]
17
+ toInts: Tensor => Array[Int]
18
+ toBuffer: Tensor => Buffer
19
+ )
20
+
21
+ defaultProcessor(): TensorProcessor {
22
+ throw(TensorException("Default tensor processor not yet implemented"))
23
+ }
24
+
25
+ f32(shape: List[Int], data: List[Float]): Tensor {
26
+ TensorFloats("ff_f32", shape, data.toArray())
27
+ }
28
+
29
+ f32a(shape: List[Int], data: Array[Float]): Tensor {
30
+ TensorFloats("ff_f64", shape, data)
31
+ }
32
+
33
+ extend this: Tensor {
34
+
35
+ multiply(that: Tensor): Tensor {
36
+ if(this.scalar != that.scalar) {
37
+ throw(TensorException("Scalar type mismatch: " + this.scalar + " vs. " + that.scalar))
38
+ }
39
+ let scalar = this.scalar
40
+ let shape = [] // TODO: Check and compute
41
+ TensorOperator(scalar, shape, "ff_multiply", [this, that])
42
+ }
43
+
44
+ toFloats(processor: TensorProcessor = defaultProcessor()): Array[Float] {
45
+ processor.toFloats(this)
46
+ }
47
+
48
+ }
49
+
50
+ main(system: NodeSystem) {
51
+ let tensor = Tensor.f32([], [1.0])
52
+ }
@@ -0,0 +1,56 @@
1
+
2
+ try {
3
+ Parser.parse(code)
4
+ } catch[ParseException] { e =>
5
+ e.rethrow()
6
+ } orThrow()
7
+
8
+
9
+ data Try[T] {
10
+ Ok(value: T)
11
+ NotOk(exception: DynamicException)
12
+ }
13
+
14
+ extend self[T]: Try[T] {
15
+
16
+ map[S](body: T => S): Try[S] {
17
+ | Ok(value) => try { body(value) }
18
+ | NotOk(exception) => NotOk(exception)
19
+ }
20
+
21
+ flatMap[S](body: T => Try[S]): Try[S] {
22
+ self.map(body).flatten()
23
+ }
24
+
25
+ else(body: () => T): T {
26
+ | Ok(value) => value
27
+ | NotOk(_) => body()
28
+ }
29
+
30
+ grab(): T {
31
+ | Ok(value) => value
32
+ | NotOk(exception) => exception.rethrow()
33
+ }
34
+
35
+ catch[E: Exception](body: E => T): Try[T] {
36
+ | NotOk(exception) {exception.as[E]() | Some(e)} => try { body(e) }
37
+ | _ => self
38
+ }
39
+
40
+ finally(body: () => Unit): Try[T] {
41
+ | Ok(value) => try { body(); value }
42
+ | NotOk(_) => body(); self
43
+ }
44
+
45
+ }
46
+
47
+ extend self[T]: Try[Try[T]] {
48
+
49
+ flatten(): Try[T] {
50
+ | Ok(Ok(value)) => value
51
+ | Ok(NotOk(_)@t) => t
52
+ | NotOk(_)@t => t
53
+ }
54
+
55
+ }
56
+
@@ -0,0 +1,9 @@
1
+ parseTsv(fs: FileSystem, tsvFileName: String): Stream[Map[String, String]] {
2
+ fs.readFile(tsvFileName).lines().withFirst { first, rest =>
3
+ let headers = first.split("\t")
4
+ rest.map { line =>
5
+ let cells = line.split("\t")
6
+ headers.zip(cells).toMap()
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,87 @@
1
+ // Set.ff only contains the Set type
2
+
3
+ newtype Set[T](map: Map[T, Unit])
4
+
5
+ empty[T](): Set[T] {
6
+ Set(Map.empty())
7
+ }
8
+
9
+ self.add(value: T): Set[T] @Order[T] { Set(self.map.add(value, Unit)) }
10
+ self.addAll(that: Set[T]): Set[T] @Order[T] { Set(self.map.addAll(that.map)) }
11
+ self.remove(value: T): Set[T] @Order[T] { Set(self.map.remove(value)) }
12
+ self.removeAll(that: Set[T]): Set[T] @Order[T] { Set(self.map.removeAll(that.map)) }
13
+ self.contains(value: T): Bool @Order[T] { self.map.contains(value) }
14
+ self.size(): Int @Order[T] { self.map.size() }
15
+ self.toList(): List[T] @Order[T] { self.map.pairs().map { _.first } }
16
+ self.each(body: T => Unit): Unit @Order[T] { self.map.each {| k, _ => body(k)} }
17
+ self.flatten[T](): Set[T] @[Set[T]] @Order[T] { todo() }
18
+ self.join(separator: String): String @[String] @Order[T] { todo() }
19
+
20
+ // Term.ff only contains the Term type
21
+
22
+ data Term(at: Location) {
23
+ EString(value: String)
24
+ EChar(value: String)
25
+ EInt(value: String)
26
+ EFloat(value: String)
27
+ EVariable(name: String)
28
+ ELambda(lambda: Lambda)
29
+ EFunctions(functions: List[DFunction], body: Term)
30
+ ELet(mutable: Bool, name: String, valueType: Type, value: Term, body: Term)
31
+ ESequential(before: Term, after: Term)
32
+ EAssign(operator: String, variable: String, value: Term)
33
+ EAssignField(operator: String, record: Term, field: String, value: Term)
34
+ EPipe(value: Term, function: Term)
35
+ ECall(
36
+ target: CallTarget
37
+ effect: Type
38
+ typeArguments: List[Type]
39
+ arguments: List[Argument]
40
+ dictionaries: List[Dictionary]
41
+ )
42
+ EList(elementType: Type, items: List[Pair[Term, Bool]])
43
+ ECopy(name: String, record: Term, arguments: List[Field])
44
+ EVariant(name: String, typeArguments: List[Type], arguments: Option[List[Argument]])
45
+ EVariantIs(name: String, typeArguments: List[Type])
46
+ ERecord(fields: List[Field])
47
+ EField(newtype: Bool, record: Term, field: String)
48
+ EWildcard(index: Int)
49
+ }
50
+
51
+ self.toString(): String {
52
+ self.{
53
+ | string(v) => v
54
+ | char(c) => ...
55
+ }
56
+ }
57
+
58
+
59
+ // Bool.ff only contains the Bool type
60
+
61
+ data Bool {
62
+ False
63
+ True
64
+ }
65
+
66
+ self.toString(): String {
67
+ self.{
68
+ | False => "false"
69
+ | True => "true"
70
+ }
71
+ }
72
+
73
+ // False/True is resolved by expected type - or written in full as Bool.True/Bool.False
74
+ file.open(read: Bool = True, write: Bool = False): Bool {
75
+ ...
76
+ }
77
+
78
+
79
+ // Traits are defined as follows. Note that modules may define a trait instead of a type.
80
+ trait Order[T] {}
81
+
82
+ instance Order[String] {}
83
+
84
+ instance Order[List[T]] @Order[T] {}
85
+
86
+ // Imports import one type and all its constructors. The type can be renamed with as. Nothing else can be unqualified.
87
+ import ff.core.Bool as B
@@ -0,0 +1,52 @@
1
+ // Two fields, zero fields and a particular field
2
+
3
+ data BpFields[A, B](
4
+ first: A
5
+ second: B
6
+ )
7
+
8
+ data BpNoFields()
9
+
10
+ data BpField[S, V](value: V)
11
+
12
+
13
+ // Two constructors, zero constructors and a particular constructor
14
+
15
+ data BpConstructors[L, R] {
16
+ BpLeft(value: L)
17
+ BpRight(value: R)
18
+ }
19
+
20
+ data BpNoConstructors {}
21
+
22
+ data BpConstructor[S, V](value: V)
23
+
24
+
25
+ // Type declarations
26
+
27
+ data BpType[S, C](constructors: C)
28
+
29
+
30
+ // Names and such
31
+
32
+ trait S: BpFieldSymbol {
33
+ fieldName(): String
34
+ }
35
+
36
+ trait S: BpConstructorSymbol {
37
+ constructorName(): String
38
+ }
39
+
40
+ trait S: BpTypeSymbol {
41
+ typeName(): String
42
+ packageName(): String
43
+ moduleName(): String
44
+ }
45
+
46
+
47
+ // The type class that converts from/to the generic representation
48
+
49
+ trait T: Blueprint[R] {
50
+ toBlueprint(value: T): R
51
+ fromBlueprint(generic: R): T
52
+ }
@@ -0,0 +1,11 @@
1
+ import User
2
+ import Pretty
3
+
4
+ nodeMain(system: NodeSystem) {
5
+ Log.debug("Hello blueprints")
6
+ Log.debug(Pretty.pretty(User(1, "foo@example.com")))
7
+ }
8
+
9
+ // TODO: Use default trait method implementations
10
+ // TODO: Check that all trait methods have been implemented in instances
11
+ // TODO: Fix "wrong number of type parameters" above (where Unit is used)
@@ -0,0 +1,58 @@
1
+ import Blueprint
2
+
3
+ trait T: Pretty {
4
+ pretty(value: T): String {
5
+ pretty(Blueprint.toBlueprint(value))
6
+ }
7
+ }
8
+
9
+ instance Int: Pretty {
10
+ pretty(value: Int): String {
11
+ "" + value
12
+ }
13
+ }
14
+
15
+ instance String: Pretty {
16
+ pretty(value: String): String {
17
+ "\"" + value + "\""
18
+ }
19
+ }
20
+
21
+ // Example of implementing a generic instance of Pretty
22
+
23
+ instance BpFields[A: Pretty, B: Pretty]: Pretty {
24
+ pretty(v: BpFields[A, B]): String {
25
+ pretty(v.first) + ", " + pretty(v.second)
26
+ }
27
+ }
28
+
29
+ instance BpNoFields: Pretty {
30
+ pretty(v: BpNoFields): String {
31
+ ""
32
+ }
33
+ }
34
+
35
+ instance BpField[S: BpFieldSymbol, V: Pretty]: Pretty {
36
+ pretty(v: BpField[S, V]): String {
37
+ Blueprint.fieldName[S, Unit]() + " = " + pretty(v.value)
38
+ }
39
+ }
40
+
41
+ instance BpConstructors[A: Pretty, B: Pretty]: Pretty {
42
+ pretty(v: BpConstructors[A, B]): String {
43
+ | BpLeft(v) => pretty(v)
44
+ | BpRight(v) => pretty(v)
45
+ }
46
+ }
47
+
48
+ instance BpConstructor[S: BpConstructorSymbol, V: Pretty]: Pretty {
49
+ pretty(v: BpConstructor[S, V]): String {
50
+ Blueprint.constructorName[S, Unit]() + "(" + pretty(v.value) + ")"
51
+ }
52
+ }
53
+
54
+ instance BpType[S, C: Pretty]: Pretty {
55
+ pretty(v: BpType[S, C]): String {
56
+ pretty(v.constructors)
57
+ }
58
+ }
@@ -0,0 +1,64 @@
1
+ import Blueprint
2
+ import Pretty
3
+
4
+ data User(id: Int, email: String)
5
+
6
+
7
+ //instance User: Pretty
8
+
9
+ data UserIdField {}
10
+ instance UserIdField: BpFieldSymbol {
11
+ fieldName(): String { "id" }
12
+ }
13
+
14
+ data UserEmailField {}
15
+ instance UserEmailField: BpFieldSymbol {
16
+ fieldName(): String { "email" }
17
+ }
18
+
19
+ data UserUserConstructor {}
20
+ instance UserUserConstructor: BpConstructorSymbol {
21
+ constructorName(): String { "User" }
22
+ }
23
+
24
+ data UserType {}
25
+ instance UserType: BpTypeSymbol {
26
+ typeName(): String { "User" }
27
+ packageName(): String { "ff:blueprints" }
28
+ moduleName(): String { "Main" }
29
+ }
30
+
31
+ instance User: Blueprint[BpType[UserType,
32
+ BpConstructor[UserUserConstructor, BpFields[
33
+ BpField[UserIdField, Int],
34
+ BpField[UserEmailField, String]
35
+ ]]
36
+ ]] {
37
+
38
+ toBlueprint(value: User): BpType[UserType,
39
+ BpConstructor[UserUserConstructor, BpFields[
40
+ BpField[UserIdField, Int],
41
+ BpField[UserEmailField, String]
42
+ ]]
43
+ ] {
44
+ BpType(BpConstructor(BpFields(BpField(value.id), BpField(value.email))))
45
+ }
46
+
47
+ fromBlueprint(generic: BpType[UserType,
48
+ BpConstructor[UserUserConstructor, BpFields[
49
+ BpField[UserIdField, Int],
50
+ BpField[UserEmailField, String]
51
+ ]]
52
+ ]): User {
53
+ generic.{
54
+ | BpType(BpConstructor(BpFields(BpField(id), BpField(email)))) => User(id, email)
55
+ }
56
+ }
57
+
58
+ }
59
+
60
+ instance User: Pretty {
61
+ pretty(value: User): String {
62
+ Pretty.pretty(Blueprint.toBlueprint(value))
63
+ }
64
+ }
@@ -0,0 +1,48 @@
1
+ data BlueprintSystem {}
2
+ data ConstructorBlueprint {}
3
+ data FieldBlueprint {}
4
+ data TypeBlueprint {}
5
+ newtype Blueprint(code: String)
6
+
7
+ extend self: BlueprintSystem {
8
+ groupName(): String
9
+ packageName(): String
10
+ moduleName(): String
11
+ typeName(): String
12
+ typeParameters(): List[String]
13
+ commonFields(): List[FieldBlueprint]
14
+ constructors(): List[ConstructorBlueprint]
15
+
16
+ typeBlueprint(typeArguments: List[TypeBlueprint] = []): TypeBlueprint
17
+
18
+ fresh(name: String): Blueprint
19
+ bool(value: Bool): Blueprint
20
+ char(value: Char): Blueprint
21
+ int(value: Int): Blueprint
22
+ float(value: Float): Blueprint
23
+ string(value: String): Blueprint
24
+ }
25
+
26
+ extend self: ConstructorBlueprint {
27
+ typeBlueprint(typeArguments: List[TypeBlueprint] = []): TypeBlueprint
28
+ constructorName(): String
29
+ fields(): List[GeneratorField]
30
+ emit(typeArguments: List[TypeBlueprint] = []): Blueprint
31
+ }
32
+
33
+ extend self: FieldBlueprint {
34
+ fieldName(): String
35
+ fieldType(): TypeBlueprint
36
+ mutable(): Bool
37
+ defaultValue(): Option[Blueprint]
38
+ emit(): Blueprint
39
+ }
40
+
41
+ extend self: TypeBlueprint {
42
+ groupName(): String
43
+ packageName(): String
44
+ moduleName(): String
45
+ typeName(): TypeBlueprint
46
+ typeArguments(): List[TypeBlueprint]
47
+ emit(): Blueprint
48
+ }
@@ -0,0 +1,53 @@
1
+ trait T: Deserializable {
2
+ deserialize(value: Json): T { blueprint t =>
3
+ let constructors = t.constructors()
4
+ Blueprint.code("""value.get("$tag").grabString().{\n""" +
5
+ constructors.map { constructor =>
6
+ "| " + Blueprint.string(constructor.constructorName()) + " =>\n" +
7
+ constructor.emit() + "(" + constructor.fields.map { field =>
8
+ field.emit() + " = deserialize(value.get(" + Blueprint.string(field.fieldName()) + "))"
9
+ }.join(", ") + ")"
10
+ }.join("\n") +
11
+ """\n| tag => panic("Unknown tag: " + tag)\n}""")
12
+ }
13
+ }
14
+
15
+ data Shape {
16
+ Circle(radius: Float)
17
+ Rectangle(width: Float, height: Float)
18
+ }
19
+
20
+ instance Shape: Deserializable
21
+
22
+ instance Shape: Deserializable {
23
+ deserialize(value: Json): Shape {
24
+ value.get("$tag").grabString().{
25
+ | "Circle" =>
26
+ Circle(
27
+ radius = deserialize(value.get("radius"))
28
+ )
29
+ | "Rectangle" =>
30
+ Rectangle(
31
+ width = deserialize(value.get("width"))
32
+ height = deserialize(value.get("height"))
33
+ )
34
+ | tag =>
35
+ panic("Unknown tag: " + tag)
36
+ }
37
+ }
38
+ }
39
+
40
+ trait T: Foo[M] {
41
+ bar(x: Int): Int { blueprint t, m =>
42
+ ...
43
+ }
44
+ }
45
+
46
+ trait T: Baz(trimStrings: Bool) {
47
+ Quux(x: Int): Int { blueprint t =>
48
+ // Use t and trimStrings here to generate code
49
+ }
50
+ }
51
+
52
+ instance Shape: Baz(trimStrings = False)
53
+
@@ -0,0 +1,13 @@
1
+ trait T: ReadJs {
2
+ readJs(value: JsValue): T { blueprint system =>
3
+ let constructors = system.constructors()
4
+ Blueprint("""value.get("$tag").grabString().{\n""" +
5
+ constructors.map { constructor =>
6
+ "| " + system.string(constructor.constructorName()).code + " =>\n" +
7
+ constructor.emit().code + "(" + constructor.fields.map { field =>
8
+ field.emit().code + " = readJs(value.get(" + system.string(field.fieldName()) + "))"
9
+ }.join(", ") + ")"
10
+ }.join("\n") +
11
+ """\n}""")
12
+ }
13
+ }
@@ -0,0 +1,2 @@
1
+ data User(id: Int, email: String)
2
+