firefly-compiler 0.5.34 → 0.5.36

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 (228) hide show
  1. package/.hintrc +4 -4
  2. package/.vscode/settings.json +4 -4
  3. package/bin/Release.ff +157 -154
  4. package/bin/firefly.mjs +1 -1
  5. package/compiler/Builder.ff +275 -277
  6. package/compiler/Compiler.ff +234 -233
  7. package/compiler/Dependencies.ff +186 -187
  8. package/compiler/DependencyLock.ff +17 -17
  9. package/compiler/Deriver.ff +23 -31
  10. package/compiler/Dictionaries.ff +1 -1
  11. package/compiler/Inference.ff +43 -20
  12. package/compiler/JsEmitter.ff +1437 -1282
  13. package/compiler/LspHook.ff +202 -202
  14. package/compiler/Main.ff +25 -24
  15. package/compiler/ModuleCache.ff +178 -178
  16. package/compiler/Parser.ff +36 -109
  17. package/compiler/Resolver.ff +5 -8
  18. package/compiler/Substitution.ff +1 -1
  19. package/compiler/Syntax.ff +1 -16
  20. package/compiler/Token.ff +9 -0
  21. package/compiler/Tokenizer.ff +4 -0
  22. package/compiler/Workspace.ff +88 -88
  23. package/core/.firefly/include/package.json +5 -5
  24. package/core/.firefly/package.ff +2 -2
  25. package/core/Any.ff +26 -30
  26. package/core/Array.ff +298 -265
  27. package/core/Atomic.ff +63 -64
  28. package/core/Box.ff +7 -7
  29. package/core/BrowserSystem.ff +40 -40
  30. package/core/Buffer.ff +185 -152
  31. package/core/BuildSystem.ff +156 -148
  32. package/core/Channel.ff +95 -92
  33. package/core/Char.ff +3 -2
  34. package/core/Core.ff +16 -23
  35. package/core/Crypto.ff +94 -96
  36. package/core/Equal.ff +41 -36
  37. package/core/Error.ff +15 -10
  38. package/core/FileHandle.ff +45 -37
  39. package/core/Float.ff +176 -200
  40. package/core/HttpClient.ff +142 -148
  41. package/core/Instant.ff +6 -8
  42. package/core/Int.ff +40 -24
  43. package/core/IntMap.ff +61 -39
  44. package/core/Js.ff +305 -0
  45. package/core/JsSystem.ff +135 -114
  46. package/core/JsValue.ff +303 -159
  47. package/core/Json.ff +423 -443
  48. package/core/List.ff +482 -486
  49. package/core/Lock.ff +108 -144
  50. package/core/Log.ff +25 -14
  51. package/core/NodeSystem.ff +198 -191
  52. package/core/Ordering.ff +160 -161
  53. package/core/Path.ff +377 -409
  54. package/core/Queue.ff +90 -0
  55. package/core/Random.ff +140 -134
  56. package/core/RbMap.ff +216 -216
  57. package/core/Serializable.ff +16 -13
  58. package/core/Show.ff +44 -43
  59. package/core/SourceLocation.ff +68 -68
  60. package/core/Stream.ff +1 -1
  61. package/core/String.ff +224 -202
  62. package/core/StringMap.ff +58 -36
  63. package/core/Task.ff +165 -149
  64. package/experimental/benchmarks/ListGrab.ff +23 -23
  65. package/experimental/benchmarks/ListGrab.java +55 -55
  66. package/experimental/benchmarks/Pyrotek45.ff +30 -30
  67. package/experimental/benchmarks/Pyrotek45.java +64 -64
  68. package/experimental/bidirectional/Bidi.ff +88 -88
  69. package/experimental/lines/Main.ff +40 -0
  70. package/experimental/random/Index.ff +53 -53
  71. package/experimental/random/Process.ff +120 -120
  72. package/experimental/random/RunLength.ff +65 -65
  73. package/experimental/random/Scrape.ff +51 -51
  74. package/experimental/random/Symbols.ff +73 -73
  75. package/experimental/random/Tensor.ff +52 -52
  76. package/experimental/random/Units.ff +36 -36
  77. package/experimental/s3/S3TestAuthorizationHeader.ff +39 -39
  78. package/experimental/s3/S3TestPut.ff +16 -16
  79. package/experimental/tests/TestJson.ff +26 -26
  80. package/firefly.sh +0 -0
  81. package/fireflysite/.firefly/package.ff +4 -4
  82. package/fireflysite/CommunityOverview.ff +20 -20
  83. package/fireflysite/CountingButtonDemo.ff +58 -58
  84. package/fireflysite/DocumentParser.ff +325 -331
  85. package/fireflysite/ExamplesOverview.ff +40 -40
  86. package/fireflysite/FrontPage.ff +344 -344
  87. package/fireflysite/GettingStarted.ff +45 -45
  88. package/fireflysite/Guide.ff +456 -456
  89. package/fireflysite/Main.ff +163 -152
  90. package/fireflysite/MatchingPasswordsDemo.ff +82 -82
  91. package/fireflysite/PackagesOverview.ff +49 -49
  92. package/fireflysite/PostgresqlDemo.ff +34 -34
  93. package/fireflysite/ReferenceAll.ff +18 -18
  94. package/fireflysite/ReferenceIntroduction.ff +11 -11
  95. package/fireflysite/Styles.ff +567 -567
  96. package/fireflysite/Test.ff +121 -62
  97. package/fireflysite/assets/markdown/reference/BaseTypes.md +209 -209
  98. package/fireflysite/assets/markdown/reference/EmittedJavascript.md +65 -65
  99. package/fireflysite/assets/markdown/reference/Exceptions.md +101 -101
  100. package/fireflysite/assets/markdown/reference/FunctionsAndMethods.md +364 -364
  101. package/fireflysite/assets/markdown/reference/JavascriptInterop.md +235 -172
  102. package/fireflysite/assets/markdown/reference/ModulesAndPackages.md +162 -162
  103. package/fireflysite/assets/markdown/reference/OldStructuredConcurrency.md +48 -48
  104. package/fireflysite/assets/markdown/reference/PatternMatching.md +224 -224
  105. package/fireflysite/assets/markdown/reference/StatementsAndExpressions.md +86 -86
  106. package/fireflysite/assets/markdown/reference/StructuredConcurrency.md +99 -99
  107. package/fireflysite/assets/markdown/reference/TraitsAndInstances.md +100 -100
  108. package/fireflysite/assets/markdown/reference/UserDefinedTypes.md +184 -184
  109. package/fireflysite/assets/markdown/scratch/ControlFlow.md +136 -136
  110. package/fireflysite/assets/markdown/scratch/Toc.md +40 -40
  111. package/lsp/.firefly/package.ff +1 -1
  112. package/lsp/CompletionHandler.ff +827 -827
  113. package/lsp/Handler.ff +714 -714
  114. package/lsp/HoverHandler.ff +79 -79
  115. package/lsp/LanguageServer.ff +272 -272
  116. package/lsp/SignatureHelpHandler.ff +55 -55
  117. package/lsp/SymbolHandler.ff +181 -181
  118. package/lsp/TestReferences.ff +17 -17
  119. package/lsp/TestReferencesCase.ff +7 -7
  120. package/lsp/stderr.txt +1 -1
  121. package/lsp/stdout.txt +34 -34
  122. package/lux/.firefly/package.ff +1 -1
  123. package/lux/Css.ff +648 -648
  124. package/lux/CssTest.ff +48 -48
  125. package/lux/Lux.ff +608 -617
  126. package/lux/LuxEvent.ff +79 -116
  127. package/lux/Main.ff +123 -123
  128. package/lux/Main2.ff +143 -143
  129. package/lux/TestDry.ff +28 -28
  130. package/output/js/ff/compiler/Builder.mjs +72 -71
  131. package/output/js/ff/compiler/Compiler.mjs +19 -13
  132. package/output/js/ff/compiler/Dependencies.mjs +8 -7
  133. package/output/js/ff/compiler/DependencyLock.mjs +6 -4
  134. package/output/js/ff/compiler/Deriver.mjs +26 -24
  135. package/output/js/ff/compiler/Dictionaries.mjs +14 -18
  136. package/output/js/ff/compiler/Environment.mjs +6 -4
  137. package/output/js/ff/compiler/Inference.mjs +238 -164
  138. package/output/js/ff/compiler/JsEmitter.mjs +1160 -350
  139. package/output/js/ff/compiler/JsImporter.mjs +20 -18
  140. package/output/js/ff/compiler/LspHook.mjs +12 -10
  141. package/output/js/ff/compiler/Main.mjs +61 -41
  142. package/output/js/ff/compiler/ModuleCache.mjs +10 -8
  143. package/output/js/ff/compiler/Parser.mjs +153 -669
  144. package/output/js/ff/compiler/Patterns.mjs +12 -10
  145. package/output/js/ff/compiler/Resolver.mjs +52 -78
  146. package/output/js/ff/compiler/Substitution.mjs +12 -16
  147. package/output/js/ff/compiler/Syntax.mjs +50 -341
  148. package/output/js/ff/compiler/Token.mjs +126 -4
  149. package/output/js/ff/compiler/Tokenizer.mjs +62 -52
  150. package/output/js/ff/compiler/Unification.mjs +74 -90
  151. package/output/js/ff/compiler/Wildcards.mjs +4 -2
  152. package/output/js/ff/compiler/Workspace.mjs +26 -20
  153. package/output/js/ff/core/Any.mjs +20 -20
  154. package/output/js/ff/core/Array.mjs +268 -175
  155. package/output/js/ff/core/AssetSystem.mjs +8 -6
  156. package/output/js/ff/core/Atomic.mjs +84 -52
  157. package/output/js/ff/core/Bool.mjs +6 -4
  158. package/output/js/ff/core/BrowserSystem.mjs +38 -29
  159. package/output/js/ff/core/Buffer.mjs +285 -133
  160. package/output/js/ff/core/BuildSystem.mjs +36 -56
  161. package/output/js/ff/core/Channel.mjs +250 -97
  162. package/output/js/ff/core/Char.mjs +5 -3
  163. package/output/js/ff/core/Core.mjs +28 -34
  164. package/output/js/ff/core/Crypto.mjs +30 -52
  165. package/output/js/ff/core/Duration.mjs +4 -2
  166. package/output/js/ff/core/Equal.mjs +14 -12
  167. package/output/js/ff/core/Error.mjs +17 -11
  168. package/output/js/ff/core/FileHandle.mjs +76 -38
  169. package/output/js/ff/core/Float.mjs +92 -160
  170. package/output/js/ff/core/HttpClient.mjs +208 -76
  171. package/output/js/ff/core/Instant.mjs +8 -10
  172. package/output/js/ff/core/Int.mjs +36 -26
  173. package/output/js/ff/core/IntMap.mjs +79 -33
  174. package/output/js/ff/core/Js.mjs +751 -0
  175. package/output/js/ff/core/JsSystem.mjs +54 -60
  176. package/output/js/ff/core/JsValue.mjs +294 -143
  177. package/output/js/ff/core/Json.mjs +443 -253
  178. package/output/js/ff/core/List.mjs +262 -214
  179. package/output/js/ff/core/Lock.mjs +156 -125
  180. package/output/js/ff/core/Log.mjs +20 -10
  181. package/output/js/ff/core/Map.mjs +10 -8
  182. package/output/js/ff/core/NodeSystem.mjs +189 -123
  183. package/output/js/ff/core/Nothing.mjs +4 -2
  184. package/output/js/ff/core/Option.mjs +40 -38
  185. package/output/js/ff/core/Ordering.mjs +26 -20
  186. package/output/js/ff/core/Pair.mjs +4 -2
  187. package/output/js/ff/core/Path.mjs +517 -315
  188. package/output/js/ff/core/Queue.mjs +306 -0
  189. package/output/js/ff/core/Random.mjs +141 -77
  190. package/output/js/ff/core/RbMap.mjs +36 -34
  191. package/output/js/ff/core/Serializable.mjs +44 -28
  192. package/output/js/ff/core/Set.mjs +6 -4
  193. package/output/js/ff/core/Show.mjs +8 -6
  194. package/output/js/ff/core/SourceLocation.mjs +4 -2
  195. package/output/js/ff/core/Stream.mjs +30 -50
  196. package/output/js/ff/core/String.mjs +263 -172
  197. package/output/js/ff/core/StringMap.mjs +77 -31
  198. package/output/js/ff/core/Task.mjs +91 -76
  199. package/output/js/ff/core/Try.mjs +20 -18
  200. package/output/js/ff/core/Unit.mjs +4 -2
  201. package/package.json +1 -1
  202. package/postgresql/Pg.ff +53 -59
  203. package/rpc/.firefly/package.ff +1 -1
  204. package/rpc/Rpc.ff +70 -70
  205. package/s3/.firefly/package.ff +1 -1
  206. package/s3/S3.ff +92 -94
  207. package/vscode/LICENSE.txt +21 -21
  208. package/vscode/Prepublish.ff +15 -15
  209. package/vscode/README.md +16 -16
  210. package/vscode/client/package-lock.json +544 -544
  211. package/vscode/client/package.json +22 -22
  212. package/vscode/client/src/extension.ts +104 -104
  213. package/vscode/icons/firefly-icon.svg +10 -10
  214. package/vscode/language-configuration.json +61 -61
  215. package/vscode/package-lock.json +3623 -3623
  216. package/vscode/package.json +1 -1
  217. package/vscode/snippets.json +241 -241
  218. package/vscode/syntaxes/firefly-markdown-injection.json +45 -45
  219. package/webserver/.firefly/include/package.json +5 -5
  220. package/webserver/.firefly/package.ff +2 -2
  221. package/webserver/WebServer.ff +647 -685
  222. package/websocket/.firefly/package.ff +1 -1
  223. package/websocket/WebSocket.ff +100 -131
  224. package/core/.firefly/include/package-lock.json +0 -564
  225. package/core/UnsafeJs.ff +0 -42
  226. package/output/js/ff/core/UnsafeJs.mjs +0 -191
  227. package/postgresql/.firefly/include/package-lock.json +0 -250
  228. package/webserver/.firefly/include/package-lock.json +0 -22
@@ -1,66 +1,66 @@
1
- # Emitted JavaScript
2
-
3
- While most Firefly code maps directly to the JavaScript equivalent, there are two notable exceptions:
4
-
5
- * I/O appears to be blocking, but compiles down to JavaScript `async`/`await`.
6
- * Methods are resolved statically in Firefly and become top level functions in JavaScript.
7
-
8
- In addition, pattern matching doesn't have a direct equivalent in JavaScript, and neither does traits.
9
-
10
-
11
- # Example
12
-
13
- Consider the following main function:
14
-
15
- ```firefly
16
- nodeMain(system: NodeSystem) {
17
-
18
- let files = ["a.txt", "b.txt"]
19
-
20
- let contents = files.map {file =>
21
- system.path(file).readText()
22
- }
23
-
24
- let upper = contents.map {content =>
25
- content.upper()
26
- }
27
-
28
- system.writeLine("Result: " + upper.join(""))
29
-
30
- }
31
- ```
32
-
33
- The JavaScript that's emitted looks roughly like this:
34
-
35
- ```js
36
- export async function nodeMain$(system) {
37
-
38
- const files = ["a.txt", "b.txt"]
39
-
40
- const contents = await List_map$(files, async file => {
41
- return await Path_readText$(await NodeSystem_path$(system, file))
42
- })
43
-
44
- const upper = List_map(contents, content => {
45
- return String_upper(content)
46
- })
47
-
48
- NodeSystem_writeLine$("Result: " + String_join(upper, ""))
49
-
50
- }
51
- ```
52
-
53
- In JavaScript, `nodeMain` becomes an `async` function and gets the `$` suffix to distinguish it from a synchronous function.
54
-
55
- The `let` keyword in Firefly corresponds to the `const` keyword in JavaScript, and Firefly list literals become JavaScript array literals.
56
-
57
- The `map` method becomes a top level function, or rather, one `async` top level function named `List_map$` and another synchronous function named `List_map`.
58
- A static analysis is performed to decide which version to call.
59
-
60
- Because the first call to `map` is passed an anonymous function that calls a method on `system`, which is a capability, and the current top level function is asynchronous,
61
- the analysis picks the asynchronous version `List_map$` and uses the `await` keyword.
62
-
63
- The second call to `map` is passed an anonymous function that doesn't involve any other capabilities, the analysis picks the synchronous version `List_map`.
64
-
65
- This static analysis is necessarily conservative, and may occasionally call the asynchronous version of a function where the synchrhonous version would suffice.
1
+ # Emitted JavaScript
2
+
3
+ While most Firefly code maps directly to the JavaScript equivalent, there are two notable exceptions:
4
+
5
+ * I/O appears to be blocking, but compiles down to JavaScript `async`/`await`.
6
+ * Methods are resolved statically in Firefly and become top level functions in JavaScript.
7
+
8
+ In addition, pattern matching doesn't have a direct equivalent in JavaScript, and neither does traits.
9
+
10
+
11
+ # Example
12
+
13
+ Consider the following main function:
14
+
15
+ ```firefly
16
+ nodeMain(system: NodeSystem) {
17
+
18
+ let files = ["a.txt", "b.txt"]
19
+
20
+ let contents = files.map {file =>
21
+ system.path(file).readText()
22
+ }
23
+
24
+ let upper = contents.map {content =>
25
+ content.upper()
26
+ }
27
+
28
+ system.writeLine("Result: " + upper.join(""))
29
+
30
+ }
31
+ ```
32
+
33
+ The JavaScript that's emitted looks roughly like this:
34
+
35
+ ```js
36
+ export async function nodeMain$(system) {
37
+
38
+ const files = ["a.txt", "b.txt"]
39
+
40
+ const contents = await List_map$(files, async file => {
41
+ return await Path_readText$(await NodeSystem_path$(system, file))
42
+ })
43
+
44
+ const upper = List_map(contents, content => {
45
+ return String_upper(content)
46
+ })
47
+
48
+ NodeSystem_writeLine$("Result: " + String_join(upper, ""))
49
+
50
+ }
51
+ ```
52
+
53
+ In JavaScript, `nodeMain` becomes an `async` function and gets the `$` suffix to distinguish it from a synchronous function.
54
+
55
+ The `let` keyword in Firefly corresponds to the `const` keyword in JavaScript, and Firefly list literals become JavaScript array literals.
56
+
57
+ The `map` method becomes a top level function, or rather, one `async` top level function named `List_map$` and another synchronous function named `List_map`.
58
+ A static analysis is performed to decide which version to call.
59
+
60
+ Because the first call to `map` is passed an anonymous function that calls a method on `system`, which is a capability, and the current top level function is asynchronous,
61
+ the analysis picks the asynchronous version `List_map$` and uses the `await` keyword.
62
+
63
+ The second call to `map` is passed an anonymous function that doesn't involve any other capabilities, the analysis picks the synchronous version `List_map`.
64
+
65
+ This static analysis is necessarily conservative, and may occasionally call the asynchronous version of a function where the synchrhonous version would suffice.
66
66
  When using the VSCode extension, the hover information for a call will note if the call is asynchronous.
@@ -1,101 +1,101 @@
1
- # Exceptions
2
-
3
- Exceptions allow a program to transfer control from the point of error to a designated exception handler, separating error-handling logic from regular program flow.
4
-
5
-
6
- # Throwing exceptions
7
-
8
- Exceptions are thrown using the `throw` function. Example:
9
-
10
- ```firefly
11
- grabOption[T](option: Option[T]): T {
12
- | Some(v) => v
13
- | None => throw(GrabException())
14
- }
15
- ```
16
-
17
- In this example, if the argument is `Some(v)`, then `v` is returned. Otherwise, a `GrabException` is thrown.
18
-
19
- Any type declared with the `data` or `newtype` keyword can be thrown as an exception, since the type will have an instance for the `HasAnyTag` trait.
20
-
21
-
22
- # Catching exceptions
23
-
24
- When an exception is thrown, it propagates up the call chain to the nearest `try`, where it can be caught:
25
-
26
- ```firefly
27
- try {
28
- grabOption(None)
29
- } catch {| GrabException, error =>
30
- Log.trace("A GrabException occurred")
31
- error.rethrow()
32
- }
33
- ```
34
-
35
- The first argument passed to `catch` is the thrown value, and the second parameter contains the stack trace.
36
- The `rethrow()` method throws the exception again without altering the stack trace.
37
- It is used when the exception is caught where it can't be fully handled.
38
-
39
- If the exception reaches the top of the call stack, the exception value and the stack trace will be printed.
40
-
41
-
42
- # Catching any exception
43
-
44
- It is also posssible to catch any exception, regardless of its type, using the `catchAny` method:
45
-
46
- ```firefly
47
- try {
48
- let result = fragileOperation()
49
- Some(result)
50
- } catchAny {error =>
51
- None
52
- }
53
- ```
54
-
55
-
56
- # Cleaning up
57
-
58
- Cleanup often needs to happen whether or not an exception is thrown.
59
- This is what the `finally` method guarantees:
60
-
61
- ```firefly
62
- let fileHandle = path.readHandle()
63
- try {
64
- process(fileHandle)
65
- } finally {
66
- fileHandle.close()
67
- }
68
- ```
69
-
70
- If the program is terminated abnormally (force closed, power is lost, etc.) there is no guarantee that `finally` will get called.
71
- In most environments, the operating system will occasionally terminate the program abnormally, so programs should be designed such that they can recover from abnormal termination.
72
-
73
-
74
- # Catching multiple exceptions
75
-
76
- The `try` function returns a value of type `Try[T]` that is defined as follows:
77
-
78
- ```firefly
79
- data Try[T] {
80
- Success(value: T)
81
- Failure(error: Error)
82
- }
83
- ```
84
-
85
- The `catch`, `catchAny` and `finally` methods are defined on this type. However, since they don't return a `Try[T]` value, they can't be chained.
86
-
87
- However, the alternative `tryCatch`, `tryCatchAny` and `tryFinally` methods do return a `Try[T]` value, and can thus be chained:
88
-
89
- ```firefly
90
- try {
91
- doSomething()
92
- } tryCatch {| GrabException, error =>
93
- reportSpecificError()
94
- } tryCatchAny {error =>
95
- reportGeneralError()
96
- } finally {
97
- performCleanup()
98
- }
99
- ```
100
-
101
- The last method in the chain here is `finally`. If it was `tryFinally`, a value of type `Try[T]` would be returned.
1
+ # Exceptions
2
+
3
+ Exceptions allow a program to transfer control from the point of error to a designated exception handler, separating error-handling logic from regular program flow.
4
+
5
+
6
+ # Throwing exceptions
7
+
8
+ Exceptions are thrown using the `throw` function. Example:
9
+
10
+ ```firefly
11
+ grabOption[T](option: Option[T]): T {
12
+ | Some(v) => v
13
+ | None => throw(GrabException())
14
+ }
15
+ ```
16
+
17
+ In this example, if the argument is `Some(v)`, then `v` is returned. Otherwise, a `GrabException` is thrown.
18
+
19
+ Any type declared with the `data` or `newtype` keyword can be thrown as an exception, since the type will have an instance for the `HasAnyTag` trait.
20
+
21
+
22
+ # Catching exceptions
23
+
24
+ When an exception is thrown, it propagates up the call chain to the nearest `try`, where it can be caught:
25
+
26
+ ```firefly
27
+ try {
28
+ grabOption(None)
29
+ } catch {| GrabException, error =>
30
+ Log.trace("A GrabException occurred")
31
+ error.rethrow()
32
+ }
33
+ ```
34
+
35
+ The first argument passed to `catch` is the thrown value, and the second parameter contains the stack trace.
36
+ The `rethrow()` method throws the exception again without altering the stack trace.
37
+ It is used when the exception is caught where it can't be fully handled.
38
+
39
+ If the exception reaches the top of the call stack, the exception value and the stack trace will be printed.
40
+
41
+
42
+ # Catching any exception
43
+
44
+ It is also posssible to catch any exception, regardless of its type, using the `catchAny` method:
45
+
46
+ ```firefly
47
+ try {
48
+ let result = fragileOperation()
49
+ Some(result)
50
+ } catchAny {error =>
51
+ None
52
+ }
53
+ ```
54
+
55
+
56
+ # Cleaning up
57
+
58
+ Cleanup often needs to happen whether or not an exception is thrown.
59
+ This is what the `finally` method guarantees:
60
+
61
+ ```firefly
62
+ let fileHandle = path.readHandle()
63
+ try {
64
+ process(fileHandle)
65
+ } finally {
66
+ fileHandle.close()
67
+ }
68
+ ```
69
+
70
+ If the program is terminated abnormally (force closed, power is lost, etc.) there is no guarantee that `finally` will get called.
71
+ In most environments, the operating system will occasionally terminate the program abnormally, so programs should be designed such that they can recover from abnormal termination.
72
+
73
+
74
+ # Catching multiple exceptions
75
+
76
+ The `try` function returns a value of type `Try[T]` that is defined as follows:
77
+
78
+ ```firefly
79
+ data Try[T] {
80
+ Success(value: T)
81
+ Failure(error: Error)
82
+ }
83
+ ```
84
+
85
+ The `catch`, `catchAny` and `finally` methods are defined on this type. However, since they don't return a `Try[T]` value, they can't be chained.
86
+
87
+ However, the alternative `tryCatch`, `tryCatchAny` and `tryFinally` methods do return a `Try[T]` value, and can thus be chained:
88
+
89
+ ```firefly
90
+ try {
91
+ doSomething()
92
+ } tryCatch {| GrabException, error =>
93
+ reportSpecificError()
94
+ } tryCatchAny {error =>
95
+ reportGeneralError()
96
+ } finally {
97
+ performCleanup()
98
+ }
99
+ ```
100
+
101
+ The last method in the chain here is `finally`. If it was `tryFinally`, a value of type `Try[T]` would be returned.