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.
- package/.hintrc +4 -4
- package/.vscode/settings.json +4 -4
- package/bin/Release.ff +153 -153
- package/bin/firefly.mjs +1 -1
- package/compiler/Builder.ff +257 -257
- package/compiler/Compiler.ff +227 -227
- package/compiler/Dependencies.ff +187 -187
- package/compiler/DependencyLock.ff +17 -17
- package/compiler/Inference.ff +2 -1
- package/compiler/JsEmitter.ff +940 -946
- package/compiler/LspHook.ff +202 -202
- package/compiler/Main.ff +3 -3
- package/compiler/ModuleCache.ff +178 -178
- package/compiler/Tokenizer.ff +1 -1
- package/compiler/Unification.ff +1 -1
- package/compiler/Workspace.ff +88 -88
- package/core/.firefly/include/package-lock.json +564 -564
- package/core/.firefly/include/package.json +5 -5
- package/core/.firefly/include/prepare.sh +1 -1
- package/core/.firefly/package.ff +2 -2
- package/core/Array.ff +265 -265
- package/core/Atomic.ff +64 -64
- package/core/Box.ff +7 -7
- package/core/BrowserSystem.ff +40 -40
- package/core/BuildSystem.ff +148 -148
- package/core/Crypto.ff +96 -96
- package/core/Equal.ff +36 -36
- package/core/Float.ff +25 -0
- package/core/HttpClient.ff +148 -148
- package/core/JsSystem.ff +69 -69
- package/core/Json.ff +434 -434
- package/core/List.ff +486 -486
- package/core/Lock.ff +144 -144
- package/core/NodeSystem.ff +216 -216
- package/core/Ordering.ff +161 -161
- package/core/Path.ff +401 -401
- package/core/Random.ff +134 -134
- package/core/RbMap.ff +216 -216
- package/core/Show.ff +43 -43
- package/core/SourceLocation.ff +68 -68
- package/core/Stream.ff +9 -9
- package/core/Task.ff +149 -141
- package/core/Try.ff +25 -4
- package/experimental/benchmarks/ListGrab.ff +23 -23
- package/experimental/benchmarks/ListGrab.java +55 -55
- package/experimental/benchmarks/Pyrotek45.ff +30 -30
- package/experimental/benchmarks/Pyrotek45.java +64 -64
- package/experimental/bidirectional/Bidi.ff +88 -88
- package/experimental/random/Index.ff +53 -53
- package/experimental/random/Process.ff +120 -120
- package/experimental/random/Scrape.ff +51 -51
- package/experimental/random/Symbols.ff +73 -73
- package/experimental/random/Tensor.ff +52 -52
- package/experimental/random/Units.ff +36 -36
- package/experimental/s3/S3TestAuthorizationHeader.ff +39 -39
- package/experimental/s3/S3TestPut.ff +16 -16
- package/experimental/tests/TestJson.ff +26 -26
- package/firefly.sh +0 -0
- package/fireflysite/.firefly/package.ff +4 -4
- package/fireflysite/CommunityOverview.ff +20 -20
- package/fireflysite/CountingButtonDemo.ff +58 -58
- package/fireflysite/DocumentParser.ff +331 -217
- package/fireflysite/ExamplesOverview.ff +40 -40
- package/fireflysite/FrontPage.ff +344 -360
- package/fireflysite/{GuideIntroduction.ff → GettingStarted.ff} +45 -52
- package/fireflysite/Guide.ff +442 -411
- package/fireflysite/Main.ff +151 -137
- package/fireflysite/MatchingPasswordsDemo.ff +82 -82
- package/fireflysite/PackagesOverview.ff +49 -49
- package/fireflysite/PostgresqlDemo.ff +34 -34
- package/fireflysite/ReferenceAll.ff +18 -0
- package/fireflysite/ReferenceIntroduction.ff +11 -0
- package/fireflysite/Styles.ff +567 -495
- package/fireflysite/Test.ff +46 -0
- package/fireflysite/assets/markdown/reference/BaseTypes.md +209 -0
- package/fireflysite/assets/markdown/reference/EmittedJavascript.md +66 -0
- package/fireflysite/assets/markdown/reference/Exceptions.md +101 -0
- package/fireflysite/assets/markdown/reference/FunctionsAndMethods.md +338 -0
- package/fireflysite/assets/markdown/reference/JavascriptInterop.md +134 -0
- package/fireflysite/assets/markdown/reference/ModulesAndPackages.md +162 -0
- package/fireflysite/assets/markdown/reference/OldStructuredConcurrency.md +48 -0
- package/fireflysite/assets/markdown/reference/PatternMatching.md +224 -0
- package/fireflysite/assets/markdown/reference/StatementsAndExpressions.md +86 -0
- package/fireflysite/assets/markdown/reference/StructuredConcurrency.md +99 -0
- package/fireflysite/assets/markdown/reference/TraitsAndInstances.md +100 -0
- package/fireflysite/assets/markdown/reference/UserDefinedTypes.md +184 -0
- package/fireflysite/assets/markdown/{ControlFlow.md → scratch/ControlFlow.md} +136 -136
- package/fireflysite/assets/markdown/scratch/Toc.md +41 -0
- package/lsp/.firefly/package.ff +1 -1
- package/lsp/CompletionHandler.ff +828 -828
- package/lsp/Handler.ff +714 -714
- package/lsp/HoverHandler.ff +79 -79
- package/lsp/LanguageServer.ff +272 -272
- package/lsp/SignatureHelpHandler.ff +55 -55
- package/lsp/SymbolHandler.ff +181 -181
- package/lsp/TestReferences.ff +17 -17
- package/lsp/TestReferencesCase.ff +7 -7
- package/lsp/stderr.txt +1 -1
- package/lsp/stdout.txt +34 -34
- package/lux/.firefly/package.ff +1 -1
- package/lux/Css.ff +648 -648
- package/lux/CssTest.ff +48 -48
- package/lux/Lux.ff +593 -487
- package/lux/LuxEvent.ff +116 -116
- package/lux/Main.ff +123 -123
- package/lux/Main2.ff +143 -143
- package/lux/TestDry.ff +27 -0
- package/output/js/ff/compiler/Builder.mjs +47 -47
- package/output/js/ff/compiler/Dependencies.mjs +3 -3
- package/output/js/ff/compiler/Inference.mjs +2 -2
- package/output/js/ff/compiler/JsEmitter.mjs +18 -72
- package/output/js/ff/compiler/Main.mjs +4 -4
- package/output/js/ff/compiler/ModuleCache.mjs +4 -4
- package/output/js/ff/core/Array.mjs +59 -59
- package/output/js/ff/core/Atomic.mjs +36 -36
- package/output/js/ff/core/BrowserSystem.mjs +11 -11
- package/output/js/ff/core/BuildSystem.mjs +30 -30
- package/output/js/ff/core/Crypto.mjs +40 -40
- package/output/js/ff/core/Float.mjs +50 -0
- package/output/js/ff/core/HttpClient.mjs +56 -56
- package/output/js/ff/core/Json.mjs +147 -147
- package/output/js/ff/core/List.mjs +50 -50
- package/output/js/ff/core/Lock.mjs +97 -97
- package/output/js/ff/core/NodeSystem.mjs +87 -87
- package/output/js/ff/core/Ordering.mjs +8 -8
- package/output/js/ff/core/Path.mjs +231 -231
- package/output/js/ff/core/Random.mjs +56 -56
- package/output/js/ff/core/Task.mjs +71 -39
- package/output/js/ff/core/Try.mjs +98 -4
- package/package.json +1 -1
- package/postgresql/Pg.ff +1 -1
- package/rpc/.firefly/package.ff +1 -1
- package/rpc/Rpc.ff +70 -70
- package/s3/.firefly/package.ff +1 -1
- package/s3/S3.ff +94 -94
- package/unsafejs/UnsafeJs.ff +19 -19
- package/vscode/LICENSE.txt +21 -21
- package/vscode/Prepublish.ff +15 -15
- package/vscode/README.md +16 -16
- package/vscode/client/package.json +22 -22
- package/vscode/client/src/extension.ts +104 -104
- package/vscode/icons/firefly-icon.svg +10 -10
- package/vscode/language-configuration.json +61 -61
- package/vscode/package-lock.json +3623 -3623
- package/vscode/package.json +1 -1
- package/vscode/snippets.json +241 -241
- package/vscode/syntaxes/firefly-markdown-injection.json +45 -45
- package/webserver/.firefly/include/package-lock.json +22 -22
- package/webserver/.firefly/include/package.json +5 -5
- package/webserver/.firefly/package.ff +2 -2
- package/webserver/WebServer.ff +685 -685
- package/websocket/.firefly/package.ff +1 -1
- package/websocket/WebSocket.ff +131 -131
- package/fireflysite/GuideAll.ff +0 -21
- package/fireflysite/GuideBaseTypes.ff +0 -168
- package/fireflysite/GuideControlFlow.ff +0 -212
- package/fireflysite/assets/markdown/Example.md +0 -78
- /package/fireflysite/assets/{NotoSansMono-Regular.ttf → font/NotoSansMono-Regular.ttf} +0 -0
- /package/fireflysite/assets/{NunitoSans-VariableFont_YTLC,opsz,wdth,wght.ttf → font/NunitoSans-VariableFont_YTLC,opsz,wdth,wght.ttf} +0 -0
- /package/fireflysite/assets/{autocomplete-small.png → image/autocomplete-small.png} +0 -0
- /package/fireflysite/assets/{autocomplete.png → image/autocomplete.png} +0 -0
- /package/fireflysite/assets/{edit-time-error.png → image/edit-time-error.png} +0 -0
- /package/fireflysite/assets/{firefly-logo-notext.png → image/firefly-logo-notext.png} +0 -0
- /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
|
package/websocket/WebSocket.ff
CHANGED
|
@@ -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
|
+
"""
|
package/fireflysite/GuideAll.ff
DELETED
|
@@ -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
|
-
}
|