firefly-compiler 0.4.79 → 0.4.81

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 (164) hide show
  1. package/.hintrc +4 -4
  2. package/.vscode/settings.json +4 -4
  3. package/bin/Release.ff +153 -153
  4. package/bin/firefly.mjs +1 -1
  5. package/compiler/Builder.ff +257 -257
  6. package/compiler/Compiler.ff +227 -227
  7. package/compiler/Dependencies.ff +187 -187
  8. package/compiler/DependencyLock.ff +17 -17
  9. package/compiler/Inference.ff +2 -1
  10. package/compiler/JsEmitter.ff +940 -946
  11. package/compiler/LspHook.ff +202 -202
  12. package/compiler/Main.ff +3 -3
  13. package/compiler/ModuleCache.ff +178 -178
  14. package/compiler/Tokenizer.ff +1 -1
  15. package/compiler/Unification.ff +1 -1
  16. package/compiler/Workspace.ff +88 -88
  17. package/core/.firefly/include/package-lock.json +564 -564
  18. package/core/.firefly/include/package.json +5 -5
  19. package/core/.firefly/include/prepare.sh +1 -1
  20. package/core/.firefly/package.ff +2 -2
  21. package/core/Array.ff +265 -265
  22. package/core/Atomic.ff +64 -64
  23. package/core/Box.ff +7 -7
  24. package/core/BrowserSystem.ff +40 -40
  25. package/core/BuildSystem.ff +148 -148
  26. package/core/Crypto.ff +96 -96
  27. package/core/Equal.ff +36 -36
  28. package/core/Float.ff +25 -0
  29. package/core/HttpClient.ff +148 -148
  30. package/core/JsSystem.ff +69 -69
  31. package/core/Json.ff +434 -434
  32. package/core/List.ff +486 -486
  33. package/core/Lock.ff +144 -144
  34. package/core/NodeSystem.ff +216 -216
  35. package/core/Ordering.ff +161 -161
  36. package/core/Path.ff +401 -401
  37. package/core/Random.ff +134 -134
  38. package/core/RbMap.ff +216 -216
  39. package/core/Show.ff +43 -43
  40. package/core/SourceLocation.ff +68 -68
  41. package/core/Stream.ff +9 -9
  42. package/core/Task.ff +149 -141
  43. package/core/Try.ff +25 -4
  44. package/experimental/benchmarks/ListGrab.ff +23 -23
  45. package/experimental/benchmarks/ListGrab.java +55 -55
  46. package/experimental/benchmarks/Pyrotek45.ff +30 -30
  47. package/experimental/benchmarks/Pyrotek45.java +64 -64
  48. package/experimental/bidirectional/Bidi.ff +88 -88
  49. package/experimental/random/Index.ff +53 -53
  50. package/experimental/random/Process.ff +120 -120
  51. package/experimental/random/Scrape.ff +51 -51
  52. package/experimental/random/Symbols.ff +73 -73
  53. package/experimental/random/Tensor.ff +52 -52
  54. package/experimental/random/Units.ff +36 -36
  55. package/experimental/s3/S3TestAuthorizationHeader.ff +39 -39
  56. package/experimental/s3/S3TestPut.ff +16 -16
  57. package/experimental/tests/TestJson.ff +26 -26
  58. package/firefly.sh +0 -0
  59. package/fireflysite/.firefly/package.ff +4 -4
  60. package/fireflysite/CommunityOverview.ff +20 -20
  61. package/fireflysite/CountingButtonDemo.ff +58 -58
  62. package/fireflysite/DocumentParser.ff +331 -217
  63. package/fireflysite/ExamplesOverview.ff +40 -40
  64. package/fireflysite/FrontPage.ff +344 -360
  65. package/fireflysite/{GuideIntroduction.ff → GettingStarted.ff} +45 -52
  66. package/fireflysite/Guide.ff +442 -411
  67. package/fireflysite/Main.ff +151 -137
  68. package/fireflysite/MatchingPasswordsDemo.ff +82 -82
  69. package/fireflysite/PackagesOverview.ff +49 -49
  70. package/fireflysite/PostgresqlDemo.ff +34 -34
  71. package/fireflysite/ReferenceAll.ff +18 -0
  72. package/fireflysite/ReferenceIntroduction.ff +11 -0
  73. package/fireflysite/Styles.ff +567 -495
  74. package/fireflysite/Test.ff +46 -0
  75. package/fireflysite/assets/markdown/reference/BaseTypes.md +209 -0
  76. package/fireflysite/assets/markdown/reference/EmittedJavascript.md +66 -0
  77. package/fireflysite/assets/markdown/reference/Exceptions.md +101 -0
  78. package/fireflysite/assets/markdown/reference/FunctionsAndMethods.md +338 -0
  79. package/fireflysite/assets/markdown/reference/JavascriptInterop.md +134 -0
  80. package/fireflysite/assets/markdown/reference/ModulesAndPackages.md +162 -0
  81. package/fireflysite/assets/markdown/reference/OldStructuredConcurrency.md +48 -0
  82. package/fireflysite/assets/markdown/reference/PatternMatching.md +224 -0
  83. package/fireflysite/assets/markdown/reference/StatementsAndExpressions.md +86 -0
  84. package/fireflysite/assets/markdown/reference/StructuredConcurrency.md +99 -0
  85. package/fireflysite/assets/markdown/reference/TraitsAndInstances.md +100 -0
  86. package/fireflysite/assets/markdown/reference/UserDefinedTypes.md +184 -0
  87. package/fireflysite/assets/markdown/{ControlFlow.md → scratch/ControlFlow.md} +136 -136
  88. package/fireflysite/assets/markdown/scratch/Toc.md +41 -0
  89. package/lsp/.firefly/package.ff +1 -1
  90. package/lsp/CompletionHandler.ff +828 -828
  91. package/lsp/Handler.ff +714 -714
  92. package/lsp/HoverHandler.ff +79 -79
  93. package/lsp/LanguageServer.ff +272 -272
  94. package/lsp/SignatureHelpHandler.ff +55 -55
  95. package/lsp/SymbolHandler.ff +181 -181
  96. package/lsp/TestReferences.ff +17 -17
  97. package/lsp/TestReferencesCase.ff +7 -7
  98. package/lsp/stderr.txt +1 -1
  99. package/lsp/stdout.txt +34 -34
  100. package/lux/.firefly/package.ff +1 -1
  101. package/lux/Css.ff +648 -648
  102. package/lux/CssTest.ff +48 -48
  103. package/lux/Lux.ff +593 -487
  104. package/lux/LuxEvent.ff +116 -116
  105. package/lux/Main.ff +123 -123
  106. package/lux/Main2.ff +143 -143
  107. package/lux/TestDry.ff +27 -0
  108. package/output/js/ff/compiler/Builder.mjs +47 -47
  109. package/output/js/ff/compiler/Dependencies.mjs +3 -3
  110. package/output/js/ff/compiler/Inference.mjs +2 -2
  111. package/output/js/ff/compiler/JsEmitter.mjs +18 -72
  112. package/output/js/ff/compiler/Main.mjs +4 -4
  113. package/output/js/ff/compiler/ModuleCache.mjs +4 -4
  114. package/output/js/ff/core/Array.mjs +59 -59
  115. package/output/js/ff/core/Atomic.mjs +36 -36
  116. package/output/js/ff/core/BrowserSystem.mjs +11 -11
  117. package/output/js/ff/core/BuildSystem.mjs +30 -30
  118. package/output/js/ff/core/Crypto.mjs +40 -40
  119. package/output/js/ff/core/Float.mjs +50 -0
  120. package/output/js/ff/core/HttpClient.mjs +56 -56
  121. package/output/js/ff/core/Json.mjs +147 -147
  122. package/output/js/ff/core/List.mjs +50 -50
  123. package/output/js/ff/core/Lock.mjs +97 -97
  124. package/output/js/ff/core/NodeSystem.mjs +87 -87
  125. package/output/js/ff/core/Ordering.mjs +8 -8
  126. package/output/js/ff/core/Path.mjs +231 -231
  127. package/output/js/ff/core/Random.mjs +56 -56
  128. package/output/js/ff/core/Task.mjs +71 -39
  129. package/output/js/ff/core/Try.mjs +98 -4
  130. package/package.json +1 -1
  131. package/postgresql/Pg.ff +1 -1
  132. package/rpc/.firefly/package.ff +1 -1
  133. package/rpc/Rpc.ff +70 -70
  134. package/s3/.firefly/package.ff +1 -1
  135. package/s3/S3.ff +94 -94
  136. package/unsafejs/UnsafeJs.ff +19 -19
  137. package/vscode/LICENSE.txt +21 -21
  138. package/vscode/Prepublish.ff +15 -15
  139. package/vscode/README.md +16 -16
  140. package/vscode/client/package.json +22 -22
  141. package/vscode/client/src/extension.ts +104 -104
  142. package/vscode/icons/firefly-icon.svg +10 -10
  143. package/vscode/language-configuration.json +61 -61
  144. package/vscode/package-lock.json +3623 -3623
  145. package/vscode/package.json +1 -1
  146. package/vscode/snippets.json +241 -241
  147. package/vscode/syntaxes/firefly-markdown-injection.json +45 -45
  148. package/webserver/.firefly/include/package-lock.json +22 -22
  149. package/webserver/.firefly/include/package.json +5 -5
  150. package/webserver/.firefly/package.ff +2 -2
  151. package/webserver/WebServer.ff +685 -685
  152. package/websocket/.firefly/package.ff +1 -1
  153. package/websocket/WebSocket.ff +131 -131
  154. package/fireflysite/GuideAll.ff +0 -21
  155. package/fireflysite/GuideBaseTypes.ff +0 -168
  156. package/fireflysite/GuideControlFlow.ff +0 -212
  157. package/fireflysite/assets/markdown/Example.md +0 -78
  158. /package/fireflysite/assets/{NotoSansMono-Regular.ttf → font/NotoSansMono-Regular.ttf} +0 -0
  159. /package/fireflysite/assets/{NunitoSans-VariableFont_YTLC,opsz,wdth,wght.ttf → font/NunitoSans-VariableFont_YTLC,opsz,wdth,wght.ttf} +0 -0
  160. /package/fireflysite/assets/{autocomplete-small.png → image/autocomplete-small.png} +0 -0
  161. /package/fireflysite/assets/{autocomplete.png → image/autocomplete.png} +0 -0
  162. /package/fireflysite/assets/{edit-time-error.png → image/edit-time-error.png} +0 -0
  163. /package/fireflysite/assets/{firefly-logo-notext.png → image/firefly-logo-notext.png} +0 -0
  164. /package/fireflysite/assets/{firefly-logo-yellow.png → image/firefly-logo-yellow.png} +0 -0
@@ -1 +1 @@
1
- package ff:websocket:0.0.0
1
+ package ff:websocket:0.0.0
@@ -1,131 +1,131 @@
1
- capability WebSocket {}
2
-
3
- open(browserSystem: BrowserSystem, url: String): WebSocket {
4
- internalOpenBrowserWebSocket(browserSystem, url)
5
- }
6
-
7
- extend self: WebSocket {
8
-
9
- readText(encoding: String = "utf8"): Option[String] {
10
- self.readAny {_} {_.toString(encoding)}
11
- }
12
-
13
- readBuffer(): Option[Buffer] {
14
- self.readAny {_.toBuffer()} {_}
15
- }
16
-
17
- readAny[T](fromText: String => T, fromBuffer: Buffer => T): Option[T]
18
- target browser async """
19
- ff_core_Task.Task_throwIfAborted($task);
20
- while(self_.ffFront.length === 0) {
21
- while(self_.ffBack.length !== 0) {
22
- self_.ffFront.push(self_.ffBack.pop());
23
- }
24
- if(self_.ffFront.length !== 0) break;
25
- if(self_.readyState === 3) return ff_core_Option.None();
26
- let abort = null;
27
- try {
28
- await new Promise((resolve, reject) => {
29
- self_.ffListeners.push(resolve);
30
- if($task !== self_.ffTask) {
31
- abort = () => {
32
- self_.ffListeners = self_.ffListeners.filter(l => l != resolve);
33
- reject();
34
- };
35
- $task.controller.signal.addEventListener('abort', abort);
36
- }
37
- });
38
- } finally {
39
- if($task !== self_.ffTask) {
40
- $task.controller.signal.removeEventListener('abort', abort);
41
- }
42
- }
43
- }
44
- const message = self_.ffFront.pop();
45
- if(!(message instanceof MessageEvent)) throw new Error("WebSocket error");
46
- const data = message.data;
47
- if(typeof data === 'string') return ff_core_Option.Some(await fromText_(data));
48
- return ff_core_Option.Some(await fromBuffer_(new DataView(data)));
49
- """
50
-
51
- writeBuffer(data: Buffer): Unit
52
- target browser async """
53
- ff_core_Task.Task_throwIfAborted($task);
54
- self_.send(data_);
55
- """
56
-
57
- writeText(data: String): Unit
58
- target browser async """
59
- ff_core_Task.Task_throwIfAborted($task);
60
- self_.send(data_);
61
- """
62
-
63
- close(code: Int = 1000, reason: String = ""): Unit
64
- target browser async """
65
- if(self_.readyState === 2 || self_.readyState === 3) return;
66
- await new Promise((resolve, reject) => {
67
- self_.addEventListener('close', resolve);
68
- self_.close(code_, reason !== "" ? reason : void 0);
69
- });
70
- return;
71
- """
72
-
73
- isOpen(): Bool
74
- target browser async """
75
- return self_.readyState === 1;
76
- """
77
-
78
- isClosing(): Bool
79
- target browser async """
80
- return self_.readyState === 2;
81
- """
82
-
83
- isClosed(): Bool
84
- target browser async """
85
- return self_.readyState === 3;
86
- """
87
-
88
- }
89
-
90
- internalOpenBrowserWebSocket(browserSystem: BrowserSystem, url: String): WebSocket
91
- target browser async """
92
- if(typeof location !== 'undefined' && !url_.includes("://")) {
93
- if(location.href && location.href.startsWith("http")) {
94
- url_ = new URL(url_, location.href).href.replace(/^http/, 'ws');
95
- }
96
- }
97
- const socket = new WebSocket(url_);
98
- socket.binaryType = "arraybuffer";
99
- socket.ffFront = [];
100
- socket.ffBack = [];
101
- socket.ffListeners = [];
102
- socket.ffTask = $task;
103
- $task.controller.signal.addEventListener('message', m => socket.ffBack.push(m));
104
- const abort = () => socket.close();
105
- try {
106
- await new Promise((resolve, reject) => {
107
- socket.onopen = resolve;
108
- socket.onerror = reject;
109
- $task.controller.signal.addEventListener('abort', abort);
110
- });
111
- } finally {
112
- socket.onopen = null;
113
- socket.onerror = null;
114
- }
115
- socket.addEventListener('close', () => {
116
- $task.controller.signal.removeEventListener('abort', abort);
117
- for(let i = 0; i < socket.ffListeners.length; i++) socket.ffListeners[i]();
118
- socket.ffListeners.length = 0;
119
- });
120
- socket.addEventListener('message', m => {
121
- socket.ffBack.push(m);
122
- for(let i = 0; i < socket.ffListeners.length; i++) socket.ffListeners[i]();
123
- socket.ffListeners.length = 0;
124
- });
125
- socket.addEventListener('error', e => {
126
- socket.ffBack.push(e);
127
- for(let i = 0; i < socket.ffListeners.length; i++) socket.ffListeners[i]();
128
- socket.ffListeners.length = 0;
129
- });
130
- return socket;
131
- """
1
+ capability WebSocket {}
2
+
3
+ open(browserSystem: BrowserSystem, url: String): WebSocket {
4
+ internalOpenBrowserWebSocket(browserSystem, url)
5
+ }
6
+
7
+ extend self: WebSocket {
8
+
9
+ readText(encoding: String = "utf8"): Option[String] {
10
+ self.readAny {_} {_.toString(encoding)}
11
+ }
12
+
13
+ readBuffer(): Option[Buffer] {
14
+ self.readAny {_.toBuffer()} {_}
15
+ }
16
+
17
+ readAny[T](fromText: String => T, fromBuffer: Buffer => T): Option[T]
18
+ target browser async """
19
+ ff_core_Task.Task_throwIfAborted($task);
20
+ while(self_.ffFront.length === 0) {
21
+ while(self_.ffBack.length !== 0) {
22
+ self_.ffFront.push(self_.ffBack.pop());
23
+ }
24
+ if(self_.ffFront.length !== 0) break;
25
+ if(self_.readyState === 3) return ff_core_Option.None();
26
+ let abort = null;
27
+ try {
28
+ await new Promise((resolve, reject) => {
29
+ self_.ffListeners.push(resolve);
30
+ if($task !== self_.ffTask) {
31
+ abort = () => {
32
+ self_.ffListeners = self_.ffListeners.filter(l => l != resolve);
33
+ reject();
34
+ };
35
+ $task.controller.signal.addEventListener('abort', abort);
36
+ }
37
+ });
38
+ } finally {
39
+ if($task !== self_.ffTask) {
40
+ $task.controller.signal.removeEventListener('abort', abort);
41
+ }
42
+ }
43
+ }
44
+ const message = self_.ffFront.pop();
45
+ if(!(message instanceof MessageEvent)) throw new Error("WebSocket error");
46
+ const data = message.data;
47
+ if(typeof data === 'string') return ff_core_Option.Some(await fromText_(data));
48
+ return ff_core_Option.Some(await fromBuffer_(new DataView(data)));
49
+ """
50
+
51
+ writeBuffer(data: Buffer): Unit
52
+ target browser async """
53
+ ff_core_Task.Task_throwIfAborted($task);
54
+ self_.send(data_);
55
+ """
56
+
57
+ writeText(data: String): Unit
58
+ target browser async """
59
+ ff_core_Task.Task_throwIfAborted($task);
60
+ self_.send(data_);
61
+ """
62
+
63
+ close(code: Int = 1000, reason: String = ""): Unit
64
+ target browser async """
65
+ if(self_.readyState === 2 || self_.readyState === 3) return;
66
+ await new Promise((resolve, reject) => {
67
+ self_.addEventListener('close', resolve);
68
+ self_.close(code_, reason !== "" ? reason : void 0);
69
+ });
70
+ return;
71
+ """
72
+
73
+ isOpen(): Bool
74
+ target browser async """
75
+ return self_.readyState === 1;
76
+ """
77
+
78
+ isClosing(): Bool
79
+ target browser async """
80
+ return self_.readyState === 2;
81
+ """
82
+
83
+ isClosed(): Bool
84
+ target browser async """
85
+ return self_.readyState === 3;
86
+ """
87
+
88
+ }
89
+
90
+ internalOpenBrowserWebSocket(browserSystem: BrowserSystem, url: String): WebSocket
91
+ target browser async """
92
+ if(typeof location !== 'undefined' && !url_.includes("://")) {
93
+ if(location.href && location.href.startsWith("http")) {
94
+ url_ = new URL(url_, location.href).href.replace(/^http/, 'ws');
95
+ }
96
+ }
97
+ const socket = new WebSocket(url_);
98
+ socket.binaryType = "arraybuffer";
99
+ socket.ffFront = [];
100
+ socket.ffBack = [];
101
+ socket.ffListeners = [];
102
+ socket.ffTask = $task;
103
+ $task.controller.signal.addEventListener('message', m => socket.ffBack.push(m));
104
+ const abort = () => socket.close();
105
+ try {
106
+ await new Promise((resolve, reject) => {
107
+ socket.onopen = resolve;
108
+ socket.onerror = reject;
109
+ $task.controller.signal.addEventListener('abort', abort);
110
+ });
111
+ } finally {
112
+ socket.onopen = null;
113
+ socket.onerror = null;
114
+ }
115
+ socket.addEventListener('close', () => {
116
+ $task.controller.signal.removeEventListener('abort', abort);
117
+ for(let i = 0; i < socket.ffListeners.length; i++) socket.ffListeners[i]();
118
+ socket.ffListeners.length = 0;
119
+ });
120
+ socket.addEventListener('message', m => {
121
+ socket.ffBack.push(m);
122
+ for(let i = 0; i < socket.ffListeners.length; i++) socket.ffListeners[i]();
123
+ socket.ffListeners.length = 0;
124
+ });
125
+ socket.addEventListener('error', e => {
126
+ socket.ffBack.push(e);
127
+ for(let i = 0; i < socket.ffListeners.length; i++) socket.ffListeners[i]();
128
+ socket.ffListeners.length = 0;
129
+ });
130
+ return socket;
131
+ """
@@ -1,21 +0,0 @@
1
- import Guide
2
- import GuideIntroduction
3
- import GuideControlFlow
4
- import GuideBaseTypes
5
-
6
- mock(): List[Document] {
7
- [
8
- GuideIntroduction.new()
9
- GuideBaseTypes.new()
10
- //GuideControlFlow.new()
11
- UnfetchedDocument("Control Flow")
12
- ReadyDocument([Section("Custom types", [])])
13
- ReadyDocument([Section("Async I/O", [])])
14
- ReadyDocument([Section("Structured concurrency", [])])
15
- ReadyDocument([Section("Applications", [])])
16
- ReadyDocument([Section("Packages and modules", [])])
17
- ReadyDocument([Section("Functions and methods", [])])
18
- ReadyDocument([Section("Traits and instances", [])])
19
- ReadyDocument([Section("JavaScript interop", [])])
20
- ]
21
- }
@@ -1,168 +0,0 @@
1
- import Guide
2
-
3
- new(): Document {
4
- ReadyDocument([
5
-
6
- Section("Base types", [
7
- Paragraph([
8
- Text("Firefly has four primitive types: ")
9
- Code("String, Char, Int, Float.", firefly = True)
10
- Text("They have the following literal syntax:")
11
- ])
12
- CodeBlock("""
13
- "Hello, World!" // String
14
- 'H' // Char
15
- 42 // Int
16
- 3.14 // Float
17
- """.replace("'''", "\"\"\""), firefly = True)
18
- Paragraph([
19
- Text("Strings may be concatenated using plus, e.g. ")
20
- Code("\"ban\" + \"ana\".", firefly = True)
21
- Text("String literals may contain escape sequences, e.g. ")
22
- Code("\\n, \\t, \\r, \\\", \\\'.")
23
- Text("You may also write multiline strings using triple quotes:")
24
- Code("\"\"\"...\"\"\".", firefly = True)
25
- ])
26
- Paragraph([
27
- Text("Ints support the usual arithmetic operators:")
28
- Code("+ - * / ^", firefly = True)
29
- Text("(division returns a Float, use the")
30
- Code(".div()", firefly = True)
31
- Text("method for integer division).")
32
- ])
33
- Paragraph([
34
- Text("Float literals may use scientific notation, e.g. ")
35
- Code("1.0e3, 1.0e-3", firefly = True)
36
- Text("The usual arithmetic operators are available:")
37
- Code("+ - * / ^", firefly = True)
38
- ])
39
- ])
40
- Section("Booleans", [
41
- Paragraph([
42
- Text("Bool is defined as a data type:")
43
- ])
44
- CodeBlock("""
45
- data Bool {
46
- False
47
- True
48
- }
49
- """, firefly = True)
50
- Paragraph([
51
- Text("Meaning it has two values:")
52
- Code("False, True.", firefly = True)
53
- Text("They support the usual logical operators:")
54
- Code("&& || !", firefly = True)
55
- ])
56
- ])
57
- Section("Durations and instants", [
58
- Paragraph([
59
- Text("Durations represent elapsed time, and instants represent points in time.")
60
- ])
61
- CodeBlock("""
62
- newtype Duration(seconds: Float)
63
- newtype Instant(since1970: Duration)
64
- """, firefly = True)
65
- Paragraph([
66
- Text("You can get the current instant:")
67
- Code("system.mainTask.now()", firefly = True)
68
- Text("or ask how much time elapsed since the program started:")
69
- Code("system.mainTask.elapsed().", firefly = True)
70
- Text("Note that neither has a time zone nor support for local calendars.")
71
- ])
72
- ])
73
- Section("Lists and arrays", [
74
- Paragraph([
75
- Text("List is the most common data structure in Firefly.")
76
- Text("It's an immutable contiguous blocks of values that can be indexed by integers, mapped over, filtered and so on.")
77
- ])
78
- CodeBlock("""
79
- let fruits: List[String] =
80
- ["apple", "banana", "orange"]
81
- """, firefly = True)
82
- Paragraph([
83
- Text("You can flatten one list into another using the spread syntax:")
84
- Code("[...friuts, \"cherry\"] == [\"apple\", \"banana\", \"orange\", \"cherry\"].", firefly = True)
85
- ])
86
- Paragraph([
87
- Text("Arrays is the mutable (and resizable) version of lists. You can convert a list to an array like this:")
88
- Code("fruits.toArray(),", firefly = True)
89
- Text("and you can construct an empty array like this:")
90
- Code("Array.new().", firefly = True)
91
- ])
92
- ])
93
- Section("Sets and maps", [
94
- Paragraph([
95
- Text("Set and Map are immutable and sorted collections. Sets have no duplicate entries, and maps have no duplicate keys.")
96
- ])
97
- CodeBlock("""
98
- let fruitSet: Set[String] =
99
- ["apple", "banana", "orange"].toSet()
100
-
101
- let numberMap: Map[String, Int] =
102
- [Pair("one", 1), Pair("two", 2)].toMap()
103
- """, firefly = True)
104
- Paragraph([
105
- Text("They have methods for lookup, union, intersection, etc.")
106
- Text("In addition, there's a mutable IntMap and StringMap that's optimized for integer and string keys, respectively.")
107
- ])
108
- ])
109
- Section("Streams and buffers", [
110
- Paragraph([
111
- Text("Streams are lazy sequences that are consumed when read. They're often used for streaming I/O.")
112
- ])
113
- CodeBlock("""
114
- // Streaming file copy
115
- let stream = system.path("file1.txt").readStream()
116
- system.path("file2.txt").writeStream(stream)
117
- """, firefly = True)
118
- Paragraph([
119
- Text("Note that there is no risk of leaking a file handle above, as the file isn't opened until the first element of the stream is read,")
120
- Text("and the writeStream method will take care of closing the stream, even in the face of I/O errors.")
121
- ])
122
- Paragraph([
123
- Text("In this case you get a")
124
- Code("Stream[Buffer]", firefly = True)
125
- Text("back, which is common for streaming I/O in Firefly.")
126
- Text("A buffer is a mutable fixed-size array of bytes that you can manipulate with hardware friendly binary operations (8-bit, 16-bit, 32-bit etc.).")
127
- ])
128
- ])
129
- Section("Option, Pair, Unit and Nothing", [
130
- Paragraph([
131
- Text("Option represent a value that may be missing. There's no null in Firefly, so Option is often the return type of lookups. It's defined like this:")
132
- ])
133
- CodeBlock("""
134
- data Option[T] {
135
- None
136
- Some(value: T)
137
- }
138
- """, firefly = True)
139
- Paragraph([
140
- Text("Pair is a generic record with two fields, e.g. for key/value pairs in a map:")
141
- ])
142
- CodeBlock("""
143
- data Pair[A, B](first: A, second: B)
144
- """, firefly = True)
145
- Paragraph([
146
- Text("Unit is the return type for functions that have no interesting return value:")
147
- ])
148
- CodeBlock("""
149
- data Unit {
150
- Unit
151
- }
152
- """, firefly = True)
153
- Paragraph([
154
- Text("Meaning it only has one possible value:")
155
- Code("Unit.", firefly = True)
156
- ])
157
- Paragraph([
158
- Text("Nothing is a type that has no values:")
159
- ])
160
- CodeBlock("""
161
- data Nothing {}
162
- """, firefly = True)
163
- Paragraph([
164
- Text("It's occasionally useful to statically rule out the possibility of constructing something.")
165
- ])
166
- ])
167
- ])
168
- }
@@ -1,212 +0,0 @@
1
- import Guide
2
-
3
- new(): Document {
4
- ReadyDocument([
5
-
6
- Section("Control flow", [
7
- Paragraph([
8
- Text("Firefly provides several ways to implement branching. ")
9
- Anchor("Pattern matching")
10
- Text(" is the most powerful, built directly into the language. ")
11
- Code("if")
12
- Text(", ")
13
- Code("elseIf")
14
- Text(" and ")
15
- Code("else")
16
- Text(" do what you expect and are functions and methods in the standard library, implemented using the")
17
- Anchor("Option")
18
- Text(" type. An then finally, there are ")
19
- Anchor("exceptions")
20
- Text(".")
21
- ])
22
- ])
23
-
24
- Section("Pattern matching", [
25
- Paragraph([
26
- Text("Pattern matching allows you to check a given data structure against a pattern. ")
27
- Text("For example, if we want to parse the command line arguments provided by the user, we could do it like this:")
28
- ])
29
- CodeBlock("""
30
- let pair = system.arguments().{
31
- | [host] => Pair(host, 80)
32
- | ["localhost", port] => Pair("localhost", port.grabInt())
33
- | _ =>
34
- system.writeErrorLine("Usage: 'localhost' | (host port)")
35
- system.exit(0)
36
- }
37
- """, firefly = True)
38
- Paragraph([
39
- Text("In Firefly you construct a list of strings (")
40
- Code("List[String]")
41
- Text(") like this ")
42
- Code("""["example.com", "80"]""")
43
- Text(", and using pattern matching you can de-construct in the same way.")
44
- ])
45
- Paragraph([
46
- Text("The basic syntax for pattern matching is:")
47
- ])
48
- CodeBlock("""
49
- data.{
50
- | pattern1 => // case 1
51
- | pattern2 => // case N
52
- ...
53
- }
54
- """, firefly = True)
55
- Paragraph([
56
- Text("The patterns must be exhaustive, that is, for any possible value of the given type, there must be a matching pattern. ")
57
- Text("In the example above, there are no value for the empty list ")
58
- Code("[]")
59
- Text(", list with two values, where the first is not ")
60
- Code(""""localhost"""")
61
- Text(" or lists with more than 2 arguments. That's why we need the wildcard case at the end. ")
62
- Text("Without this last case, the compiler would produce a compile-time error, stating that the patterns must be exhaustive.")
63
- ])
64
- Paragraph([
65
- Text("Here are more examples — all exhaustive. Let's start with records:")
66
- ])
67
- CodeBlock("""
68
- pair.{
69
- | Pair(first, second) =>
70
- }
71
- """, firefly = True)
72
-
73
- Paragraph([
74
- Text("Numbers")
75
- ])
76
- CodeBlock("""
77
- n.{
78
- | 1 =>
79
- | 2 =>
80
- | n =>
81
- }
82
- """, firefly = True)
83
-
84
- Paragraph([
85
- Text("Booleans")
86
- ])
87
- CodeBlock("""
88
- n.{
89
- | True =>
90
- | False =>
91
- }
92
- """, firefly = True)
93
- Paragraph([
94
- Text("And you can combine pattern as needed. Imagine you have a pair of type ")
95
- Code("Pair[List[Bool], Pair(Int, String)]")
96
- ])
97
- CodeBlock("""
98
- pair.{
99
- | Pair([True, False], Pair(42, "foo")) =>
100
- | other =>
101
- }
102
- """, firefly = True)
103
- ])
104
-
105
- Section("Option", [
106
- Paragraph([
107
- Text("Sometimes you don't have a value. Other languages uses ")
108
- Code("null")
109
- Text(" for this purpose, but Firefly does not have ")
110
- Code("null")
111
- Text(". Instead, we have ")
112
- Code("Option")
113
- Text(" from the core package.")
114
- ])
115
- CodeBlock("""
116
- data Option[T] {
117
- None
118
- Some(value: T)
119
- }
120
- """, firefly = True)
121
- Paragraph([
122
- Text("For some type T, say String, Option[String] is either some string or no value (")
123
- Code("None")
124
- Text("). This way, the type system guides you to check for no-value.")
125
- ])
126
-
127
- Paragraph([
128
- Text("Many functions and methods returns an ")
129
- Code("Option")
130
- Text(" in Firefly. For instance the ")
131
- Code("getInt ")
132
- Text(" method on ")
133
- Code("String")
134
- Text(" . This method returns ")
135
- Code("Some[Int]")
136
- Text(" when the string consists only of digits and ")
137
- Code("None")
138
- Text(" otherwise. We can perform pattern matching on ")
139
- Code("Option")
140
- Text("like this:")
141
- ])
142
- CodeBlock("""
143
- port.getInt().{
144
- | None => 80
145
- | Some(p) => p
146
- }
147
- """, firefly = True)
148
- Paragraph([
149
- Text("Many methods like ")
150
- Code("getInt")
151
- Text(" have a non-total counterpart ")
152
- Code("grabInt")
153
- Text(" , which returns an ")
154
- Code("Int")
155
- Text(" . But it will throw an exception when the input cannot be parsed. Options let's you code in an exception-safe manner.")
156
- ])
157
- ])
158
-
159
-
160
- Section("if - elseIf - else", [
161
- Paragraph([
162
- Text("You write if-statements in Firefly like this:")
163
- ])
164
- CodeBlock("""
165
- if(path == "/") {
166
- response.writeText("<!doctype html>")
167
- } elseIf {path.startsWith("/js/")} {
168
- response.writeText("<script>")
169
- } else {
170
- response.writeStatus("404 Not found")
171
- }
172
- """, firefly = True)
173
- Paragraph([
174
- Text("You can also use it as an expression like this")
175
- ])
176
- CodeBlock("""
177
- let contentType = if(path == "/") {
178
- "text/html; charset=UTF-8"
179
- } elseIf(directory2.exists) {
180
- "text/javascript; charset=UTF-8"
181
- } else {
182
- "text/plain; charset=UTF-8"
183
- }
184
- """, firefly = True)
185
- Paragraph([
186
- Code("if")
187
- Text(", ")
188
- Code("elseIf")
189
- Text(" and ")
190
- Code("else")
191
- Text(" are not keywords or construct build into Firefly. ")
192
- Text("If you are curious, you can look at how they are implemented. ")
193
- Code("if")
194
- Text(" is just a function defined like this: ")
195
- ])
196
- CodeBlock("""
197
- if[T](condition: Bool, body: () => T): Option[T] {
198
- condition.{
199
- | False => None
200
- | True => Some(body())
201
- }
202
- }
203
- """, firefly = True)
204
- // TODO: But still, why are this syntactically correct?
205
- ])
206
- Section("Exceptions", [
207
- Paragraph([
208
- Text("...")
209
- ])
210
- ])
211
- ])
212
- }