firefly-compiler 0.4.79 → 0.4.80

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 (158) 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 +141 -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 +443 -411
  67. package/fireflysite/Main.ff +141 -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 +19 -0
  72. package/fireflysite/ReferenceIntroduction.ff +11 -0
  73. package/fireflysite/Styles.ff +567 -495
  74. package/fireflysite/Test.ff +38 -0
  75. package/fireflysite/assets/markdown/reference/BaseTypes.md +209 -0
  76. package/fireflysite/assets/markdown/reference/FunctionsAndMethods.md +208 -0
  77. package/fireflysite/assets/markdown/reference/ModulesAndPackages.md +168 -0
  78. package/fireflysite/assets/markdown/reference/PatternMatching.md +224 -0
  79. package/fireflysite/assets/markdown/reference/StatementsAndExpressions.md +86 -0
  80. package/fireflysite/assets/markdown/reference/TraitsAndInstances.md +100 -0
  81. package/fireflysite/assets/markdown/reference/UserDefinedTypes.md +184 -0
  82. package/fireflysite/assets/markdown/{ControlFlow.md → scratch/ControlFlow.md} +136 -136
  83. package/fireflysite/assets/markdown/scratch/Toc.md +41 -0
  84. package/lsp/.firefly/package.ff +1 -1
  85. package/lsp/CompletionHandler.ff +828 -828
  86. package/lsp/Handler.ff +714 -714
  87. package/lsp/HoverHandler.ff +79 -79
  88. package/lsp/LanguageServer.ff +272 -272
  89. package/lsp/SignatureHelpHandler.ff +55 -55
  90. package/lsp/SymbolHandler.ff +181 -181
  91. package/lsp/TestReferences.ff +17 -17
  92. package/lsp/TestReferencesCase.ff +7 -7
  93. package/lsp/stderr.txt +1 -1
  94. package/lsp/stdout.txt +34 -34
  95. package/lux/.firefly/package.ff +1 -1
  96. package/lux/Css.ff +648 -648
  97. package/lux/CssTest.ff +48 -48
  98. package/lux/Lux.ff +487 -487
  99. package/lux/LuxEvent.ff +116 -116
  100. package/lux/Main.ff +123 -123
  101. package/lux/Main2.ff +143 -143
  102. package/output/js/ff/compiler/Builder.mjs +47 -47
  103. package/output/js/ff/compiler/Dependencies.mjs +3 -3
  104. package/output/js/ff/compiler/Inference.mjs +2 -2
  105. package/output/js/ff/compiler/JsEmitter.mjs +18 -72
  106. package/output/js/ff/compiler/Main.mjs +4 -4
  107. package/output/js/ff/compiler/ModuleCache.mjs +4 -4
  108. package/output/js/ff/core/Array.mjs +59 -59
  109. package/output/js/ff/core/Atomic.mjs +36 -36
  110. package/output/js/ff/core/BrowserSystem.mjs +11 -11
  111. package/output/js/ff/core/BuildSystem.mjs +30 -30
  112. package/output/js/ff/core/Crypto.mjs +40 -40
  113. package/output/js/ff/core/Float.mjs +50 -0
  114. package/output/js/ff/core/HttpClient.mjs +56 -56
  115. package/output/js/ff/core/Json.mjs +147 -147
  116. package/output/js/ff/core/List.mjs +50 -50
  117. package/output/js/ff/core/Lock.mjs +97 -97
  118. package/output/js/ff/core/NodeSystem.mjs +87 -87
  119. package/output/js/ff/core/Ordering.mjs +8 -8
  120. package/output/js/ff/core/Path.mjs +231 -231
  121. package/output/js/ff/core/Random.mjs +56 -56
  122. package/output/js/ff/core/Task.mjs +39 -39
  123. package/output/js/ff/core/Try.mjs +98 -4
  124. package/package.json +1 -1
  125. package/postgresql/Pg.ff +1 -1
  126. package/rpc/.firefly/package.ff +1 -1
  127. package/rpc/Rpc.ff +70 -70
  128. package/s3/.firefly/package.ff +1 -1
  129. package/s3/S3.ff +94 -94
  130. package/unsafejs/UnsafeJs.ff +19 -19
  131. package/vscode/LICENSE.txt +21 -21
  132. package/vscode/Prepublish.ff +15 -15
  133. package/vscode/README.md +16 -16
  134. package/vscode/client/package.json +22 -22
  135. package/vscode/client/src/extension.ts +104 -104
  136. package/vscode/icons/firefly-icon.svg +10 -10
  137. package/vscode/language-configuration.json +61 -61
  138. package/vscode/package-lock.json +3623 -3623
  139. package/vscode/package.json +1 -1
  140. package/vscode/snippets.json +241 -241
  141. package/vscode/syntaxes/firefly-markdown-injection.json +45 -45
  142. package/webserver/.firefly/include/package-lock.json +22 -22
  143. package/webserver/.firefly/include/package.json +5 -5
  144. package/webserver/.firefly/package.ff +2 -2
  145. package/webserver/WebServer.ff +685 -685
  146. package/websocket/.firefly/package.ff +1 -1
  147. package/websocket/WebSocket.ff +131 -131
  148. package/fireflysite/GuideAll.ff +0 -21
  149. package/fireflysite/GuideBaseTypes.ff +0 -168
  150. package/fireflysite/GuideControlFlow.ff +0 -212
  151. package/fireflysite/assets/markdown/Example.md +0 -78
  152. /package/fireflysite/assets/{NotoSansMono-Regular.ttf → font/NotoSansMono-Regular.ttf} +0 -0
  153. /package/fireflysite/assets/{NunitoSans-VariableFont_YTLC,opsz,wdth,wght.ttf → font/NunitoSans-VariableFont_YTLC,opsz,wdth,wght.ttf} +0 -0
  154. /package/fireflysite/assets/{autocomplete-small.png → image/autocomplete-small.png} +0 -0
  155. /package/fireflysite/assets/{autocomplete.png → image/autocomplete.png} +0 -0
  156. /package/fireflysite/assets/{edit-time-error.png → image/edit-time-error.png} +0 -0
  157. /package/fireflysite/assets/{firefly-logo-notext.png → image/firefly-logo-notext.png} +0 -0
  158. /package/fireflysite/assets/{firefly-logo-yellow.png → image/firefly-logo-yellow.png} +0 -0
@@ -0,0 +1,224 @@
1
+ # Pattern matching
2
+
3
+ Every function lets you pattern match on its arguments. Pattern matching lets you branch on the structure of arguments and extract nested values.
4
+
5
+
6
+ # In anonymous functions
7
+
8
+ In the following example, `map` is passed an anonymous function, which pattern matches on its argument:
9
+
10
+ ```firefly
11
+ blockElements.map {
12
+ | Paragraph(text) =>
13
+ renderParagraph(text)
14
+ | Code(code, Some(type)) =>
15
+ renderHighlighted(code, type)
16
+ | Code(code, None) =>
17
+ renderCode(code)
18
+ | Video(url) {vimeoId(url) | Some(id)} =>
19
+ renderVimeo(id)
20
+ | Video(url) =>
21
+ renderVideo(url)
22
+ }
23
+ ```
24
+
25
+ In this example there are five cases, and `blockElements: List[BlockElement]` with the following type definition:
26
+
27
+ ```firefly
28
+ data BlockElement {
29
+ Paragraph(text: String)
30
+ Code(code: String, type: Option[String])
31
+ Video(url: String)
32
+ }
33
+ ```
34
+
35
+ If you have multiple arguments, you need to provide a pattern for each argument, separated by commas.
36
+
37
+
38
+ # Cases
39
+
40
+ Each case must have one or more patterns, zero or more guards, and zero or more statements.
41
+
42
+ The first case starts with a pattern that matches when the argument is `Paragraph`, and extracts its `text` field into a variable named `text`:
43
+
44
+ ```firefly
45
+ | Paragraph(text) =>
46
+ ```
47
+
48
+ The variable is in scope in the statements of the case following the `=>`.
49
+ The field name and the variable name do not have to be the same.
50
+ The variable could be named `t` or `foo`, even though the type defines a field named `text`.
51
+
52
+ The second case starts with a pattern that matches when the argument is `Code`, and the second field of that is `Some`:
53
+
54
+ ```firefly
55
+ | Code(code, Some(type)) =>
56
+ ```
57
+
58
+ The third case starts with a pattern that matches when the argument is `Code`, and the second field of that is `None`:
59
+
60
+ ```firefly
61
+ | Code(code, None) =>
62
+ ```
63
+
64
+ Together with the case above, it covers all the values that can be constructed using the `Code` variant.
65
+
66
+ The fourth case starts with a pattern that matches when the argument is `Video`, and then uses a guard:
67
+
68
+ ```firefly
69
+ | Video(url) {vimeoId(url) | Some(id)} =>
70
+ ```
71
+
72
+ The guard calls a function on the extracted field, and matches the result against the pattern `Some(id)`.
73
+
74
+ The fifth and final case starts with a pattern that matches when the argument is `Video`, and has no guard:
75
+
76
+ ```firefly
77
+ | Video(url) =>
78
+ ```
79
+
80
+ Together with the case above, it convers all the values that can be constructed using the `Video` variant.
81
+
82
+
83
+ # Exhaustiveness
84
+
85
+ Since all the ways to construct a `BlockElement` has been covered by the cases, the pattern match is exhaustive.
86
+ Exhaustiveness is enforced in Firefly, so it's never possible to end up in a situation at runtime where no case matches the arguments.
87
+
88
+ Cases are tried in order until one of them matches. When a case matches, its statements will be run.
89
+ In this case a return value is expected, and thus the last statement must be an expression, whose value will be returned.
90
+
91
+
92
+ # Alias patterns
93
+
94
+ To extract all the fields of a variant as an anonymous record, use the a pattern like this:
95
+
96
+ ```firefly
97
+ | Code c =>
98
+ renderCode(c.code)
99
+ ```
100
+
101
+ Here `c: (code: String, type: Option[String])` - that is, it's an anonymous record with the fields of the variant.
102
+
103
+ To pattern match on a value while also extracting that value into a variable, use a pattern like this:
104
+
105
+ ```firefly
106
+ | Code(code, Some(_) @ typeOption) =>
107
+ ```
108
+
109
+ This ensures that the case only matches if the type field is `Some`, but binds the whole option into a variable `typeOption: Option[String]`.
110
+
111
+
112
+ # In pipes
113
+
114
+ Another way to write the above is to pipe the argument into an anonymous function that pattern matches on it:
115
+
116
+ ```firefly
117
+ blockElements.map {blockElement =>
118
+ blockElement.{
119
+ | Paragraph(text) =>
120
+ renderParagraph(text)
121
+ | Code(code, Some(type)) =>
122
+ renderHighlighted(code, type)
123
+ | Code(code, None) =>
124
+ renderCode(code)
125
+ | Video(url) {vimeoId(url) | Some(id)} =>
126
+ renderVimeo(id)
127
+ | Video(url) =>
128
+ renderVideo(url)
129
+ }
130
+ }
131
+ ```
132
+
133
+ This is also a way to pattern match on one of many arguments, a local variable or an expression.
134
+
135
+
136
+ # In named functions
137
+
138
+ Pattern matching may also be used for the arguments of named functions and methods. Here's an example of pattern matching in a local function:
139
+
140
+ ```firefly
141
+ function render(element: BlockElement) {
142
+ | Paragraph(text) =>
143
+ renderParagraph(text)
144
+ | Code(code, Some(type)) =>
145
+ renderHighlighted(code, type)
146
+ | Code(code, None) =>
147
+ renderCode(code)
148
+ | Video(url) {vimeoId(url) | Some(id)} =>
149
+ renderVimeo(id)
150
+ | Video(url) =>
151
+ renderVideo(url)
152
+ }
153
+ ```
154
+
155
+ Here's an example of pattern matching in a method:
156
+
157
+ ```firefly
158
+ extend self: Renderer {
159
+ render(element: BlockElement) {
160
+ | Paragraph(text) =>
161
+ self.renderParagraph(text)
162
+ | Code(code, Some(type)) =>
163
+ self.renderHighlighted(code, type)
164
+ | Code(code, None) =>
165
+ self.renderCode(code)
166
+ | Video(url) {vimeoId(url) | Some(id)} =>
167
+ self.renderVimeo(id)
168
+ | Video(url) =>
169
+ self.renderVideo(url)
170
+ }
171
+ }
172
+ ```
173
+
174
+
175
+ # Literals and wildcards
176
+
177
+ It's also possible to match on `Int`, `Char`, `String`, and `List[T]` values.
178
+
179
+ Here's an example that matches on `Int`:
180
+
181
+ ```firefly
182
+ fib(n: Int): Int {
183
+ | 0 => 0
184
+ | 1 => 1
185
+ | _ => fib(n - 1) + fib(n - 2)
186
+ }
187
+ ```
188
+
189
+ The wildcard pattern `_` matches any value without binding it to a variable.
190
+
191
+ Here's an example that matches on `Char`:
192
+
193
+ ```firefly
194
+ extend self: Player {
195
+ go(key: Char) {
196
+ | 'w' => self.goUp()
197
+ | 'a' => self.goLeft()
198
+ | 's' => self.goDown()
199
+ | 'd' => self.goRight()
200
+ | _ =>
201
+ }
202
+ }
203
+ ```
204
+
205
+ Here's an example that matches on `String`:
206
+
207
+ ```firefly
208
+ name.{
209
+ | "" => "Hello, there!"
210
+ | _ => "Hello, " + name + "!"
211
+ }
212
+ ```
213
+
214
+ Here's an example that matches on `List[Int]`:
215
+
216
+ ```firefly
217
+ numbers.{
218
+ | [] => "No numbers!"
219
+ | [n] => "One number, " + n + "!"
220
+ | [n, ...ns] => "A number, " + n + ", and " + ns.size() + " more numbers!"
221
+ }
222
+ ```
223
+
224
+ In patterns, the spread syntax `...` matches the rest of a list.
@@ -0,0 +1,86 @@
1
+ # Statements and expressions
2
+
3
+ In Firefly, the body of functions and methods consist of zero or more statements, separated by `;`.
4
+
5
+ When `;` is the last token on a line, it can be omitted.
6
+
7
+ A statement is either a [local function definition](functions-and-methods), a local variable definition, an assignment or an expression.
8
+
9
+ Field assignments were covered in [user defined types](user-defined types).
10
+
11
+
12
+ # Local variables
13
+
14
+ Local variables need an initial value:
15
+
16
+ ```firefly
17
+ let x = 42
18
+ ```
19
+
20
+ This defines immutable local variable `x: Int` with the value `42`.
21
+
22
+ Variables can be reffered to by name:
23
+
24
+ ```firefly
25
+ x + x // Returns 84
26
+ ```
27
+
28
+ The type of a variable can be stated explicitly:
29
+
30
+ ```firefly
31
+ let y: String = "Hello"
32
+ ```
33
+
34
+ Mutable variables are introduced using the `mutable` keyword:
35
+
36
+ ```firefly
37
+ mutable z = 1
38
+ ```
39
+
40
+ This works like `let`, except that you're allowed to update mutable variables by assigning to them:
41
+
42
+ ```firefly
43
+ z = 2 // z is now 2
44
+ z += 2 // z is now 4
45
+ z -= 1 // z is now 3
46
+ ```
47
+
48
+
49
+ # Expressions
50
+
51
+ Expressions can be one of the following syntactic constructs:
52
+
53
+ ```firefly
54
+ 42 // Int literal
55
+ 42.0 // Float literal
56
+ 'a' // Char literal
57
+ "foo" // String literal
58
+ [] // List literal
59
+ {} // Function literal
60
+ () // Record literal
61
+ True // Variant construction
62
+ x // Variable
63
+ _ // Anonymous parameter
64
+ f() // Function call
65
+ x.y // Field access
66
+ x.V() // Copy construction
67
+ x.{_} // Piping
68
+ !x // Unary operator
69
+ a + b // Binary operator
70
+ (a + b) * c // Grouping parenthesis
71
+ ```
72
+
73
+ Binary operators are left associative and the operator precedence is as follows, lowest to highest:
74
+
75
+ * `||`
76
+ * `&&`
77
+ * `!=` `==`
78
+ * `<=` `>=` `<` `>`
79
+ * `+` `-`
80
+ * `*` `/` `%`
81
+ * `^`
82
+ * `f()`
83
+ * `x.y` `x.V()` `x.{_}`
84
+
85
+ Unary operators `!` and `-` have higher precedence than `^` and lower precedence than `f()`.
86
+
@@ -0,0 +1,100 @@
1
+ # Traits and instances
2
+
3
+ A trait defines an open set of types that support a common set of functions.
4
+ For example, here's a trait for shapes with a common function to compute the area:
5
+
6
+ ```firefly
7
+ trait T: Shape {
8
+ area(shape: T): Float
9
+ }
10
+ ```
11
+
12
+ The function becomes a top level function `area[T: Shape](shape: T): Float`.
13
+ Here `T` is a bounded type parameter: It can only be instantiated to a type that has an instance of the `Shape` trait.
14
+
15
+ Consider these two types that would be good candidates for having an instance of the `Shape` trait:
16
+
17
+ ```firefly
18
+ data Circle(radius: Float)
19
+ data Rectangle(width: Float, height: Float)
20
+ ```
21
+
22
+ Only types defined with the `data` or `newtype` keyword can have trait instances.
23
+
24
+ Instances for these types can be created with the `instance` keyword as follows:
25
+
26
+ ```firefly
27
+ instance Circle: Shape {
28
+ area(shape: Circle): Float {
29
+ Float.pi() * (shape.radius ^ 2.0)
30
+ }
31
+ }
32
+
33
+ instance Rectangle: Shape {
34
+ area(shape: Rectangle): Float {
35
+ shape.width * shape.height
36
+ }
37
+ }
38
+ ```
39
+
40
+ Each instance provides an implementation of `area` specific to the type.
41
+
42
+ Here's an example of how to define a normal top level function with a bounded type parameter:
43
+
44
+ ```firefly
45
+ printArea[T: Shape](shape: T) {
46
+ Log.trace("Area: " + area(shape))
47
+ }
48
+
49
+ printArea(Circle(0.0)) // Prints "Area: 0"
50
+ printArea(Rectangle(5.0, 6.0)) // Prints "Area: 30"
51
+ ```
52
+
53
+ Multiple bounds are separated by colons, e.g. `foo[T: Bar: Baz]` means that `T` must have instances for both `Bar` and `Baz`.
54
+
55
+
56
+ # Traits with type parameters
57
+
58
+ Traits can have type parameters:
59
+
60
+ ```firefly
61
+ trait I: Rpc[O] {}
62
+
63
+ instance MyMessage: Rpc[Int] {}
64
+ ```
65
+
66
+ The choice of `I` fully determines `O` - in this case, if `I` is `MyMessage`, then `O` is `Int`.
67
+
68
+
69
+ # Automatic traits
70
+
71
+ If instances for the following traits are not explicitly defined, they will be generated automatically.
72
+ This only applies to types defined with the `data` or `newtype` keyword.
73
+
74
+ ```firefly
75
+ // Used for == !=
76
+ trait T: Equal {
77
+ equals(x: T, y: T): Bool
78
+ }
79
+
80
+ // Used for < > <= >= and sorting
81
+ trait T: Order {
82
+ compare(x: T, y: T): Ordering
83
+ }
84
+
85
+ // Used to display values for debugging
86
+ trait T: Show {
87
+ show(value: T): String
88
+ }
89
+
90
+ // Used for binary serialization
91
+ trait T: Serializable {
92
+ serializeUsing(serialization: Serialization, value: T): Unit
93
+ deserializeUsing(serialization: Serialization): T
94
+ }
95
+
96
+ // Used for throwing and catching exceptions
97
+ trait T: HasAnyTag {
98
+ anyTag(): AnyTag[T]
99
+ }
100
+ ```
@@ -0,0 +1,184 @@
1
+ # User defined types
2
+
3
+ Named types can be defined at the top level, using one of four keywords: `data`, `class`, `capability` or `newtype`.
4
+
5
+
6
+ # data
7
+
8
+ To define an immutable type, you can use the `data` keyword.
9
+
10
+ ```firefly
11
+ data Shape {
12
+ Circle(x: Float, y: Float, radius: Float)
13
+ Rectangle(x: Float, y: Float, width: Float, height: Float)
14
+ }
15
+ ```
16
+
17
+ This defines a type called `Shape` with two variants `Circle` and `Rectangle`.
18
+ The `Circle` variant has three named fields of type `Float`, while the `Rectangle` variant has four.
19
+
20
+ Type and variant names must start with a capital letter.
21
+
22
+ No `class` or `capability` types can occur in the definition of a `data` type.
23
+
24
+ A value of type `Shape` is either a `Circle` or a `Rectangle`, and they can be constructed as follows:
25
+
26
+ ```firefly
27
+ Circle(0.0, 0.0, 1.0) // Variant, : Shape
28
+ Rectangle(5.0, 7.0, 3.0, 2.0) // Variant, : Shape
29
+ ```
30
+
31
+ Above the variants are constructed using positional arguments, whose order must coincide with the order of the parameters in the type definition.
32
+
33
+ Named arguments are supported as well:
34
+
35
+ ```firefly
36
+ Circle(x = 0.0, y = 0.0, radius = 1.0)
37
+ ```
38
+
39
+ Named parameters don't have to be in order, and can be mixed with positional arguments:
40
+
41
+ ```firefly
42
+ Circle(radius = 1.0, 0.0, 0.0)
43
+ ```
44
+
45
+ To branch on the specific variant of a type, use [pattern matching](pattern-matching).
46
+
47
+
48
+ # Common fields
49
+
50
+ When all the variants share a set of fields, they can be moved to the common fields section of the declaration:
51
+
52
+ ```firefly
53
+ data Shape(x: Float, y: Float) {
54
+ Circle(radius: Float)
55
+ Rectangle(width: Float, height: Float)
56
+ }
57
+ ```
58
+
59
+ This is similar to the `Shape` definition above, but the `x` and `y` fields have been pulled out as common fields.
60
+ Given a value of a type, e.g. `shape: Shape`, common fields can be accessed without knowing which specific variant it is:
61
+
62
+ ```firefly
63
+ shape.x // Returns a Float
64
+ shape.y // Returns a Float
65
+ ```
66
+
67
+ When there is only one variant of a type, and its name coincides with the name of the type, we can use a shorthand definition:
68
+
69
+ ```firefly
70
+ data Point(x: Float, y: Float)
71
+ ```
72
+
73
+ This defines a type called `Point` with a single variant, also named `Point`, and two common fields of type `Float`.
74
+
75
+
76
+ # Copying
77
+
78
+ If you have a value and want to construct a variant, you can copy each field explicitly:
79
+
80
+ ```firefly
81
+ Rectangle(x = point.x, y = point.y, width = 2.0, height = 1.5)
82
+ ```
83
+
84
+ There's a shorthand for doing this, however:
85
+
86
+ ```firefly
87
+ point.Rectangle(width = 2.0, height = 1.5)
88
+ ```
89
+
90
+ Using this shorthand, the fields of `Rectangle` that aren't specified will be copied from `point`.
91
+
92
+
93
+
94
+ # class
95
+
96
+ Types defined with the `class` keyword work like `data` types, except for the differences noted here.
97
+
98
+ Fields of `class` types may be declared `mutable`:
99
+
100
+ ```firefly
101
+ class FruitBasket(
102
+ mutable apples: Int
103
+ mutable oranges: Int
104
+ mutable bananas: Int
105
+ )
106
+ ```
107
+
108
+ Mutable fields can be updated. Given a value `basket: FruitBasket`, its fields can be assigned to:
109
+
110
+ ```firefly
111
+ basket.apples = 42 // The apples field now holds the value 42
112
+ basket.oranges += 1 // The oranges field is now one greater
113
+ basket.bananas -= 1 // The bananas field is now one less
114
+ ```
115
+
116
+ Except for `capability` types, all types can occur in the definition of a `class` type.
117
+
118
+
119
+ # capability
120
+
121
+ Types defined with the `capability` keyword work like `class` types, except for the differences noted here.
122
+
123
+ ```firefly
124
+ capability EventHandler(
125
+ onEvent: () => Unit
126
+ )
127
+ ```
128
+
129
+ The `onEvent` field here contains a first class function, which may have captured other capabilities or classes in its closure.
130
+ Therefore, calling the function contained in this field may cause side effects.
131
+
132
+ In particular, it may have captured the `system` argument that's passed to the main function, or other capabilities that allow it to do I/O.
133
+
134
+ There are no restrictions on the types of fields that `capability` types can have.
135
+
136
+ Function types `=>` are considered `capability` types.
137
+
138
+
139
+ # newtype
140
+
141
+ Types defined with the `newtype` keyword work like `data` types, except that they must have exactly one common field and no explicitly listed variants.
142
+
143
+ ```firefly
144
+ newtype UserId(id: Int)
145
+ ```
146
+
147
+ At runtime, they are represented as values of the field type.
148
+ In this case, it means that `UserId(42)` is represented as the `Int` value `42` at runtime, with zero overhead.
149
+
150
+
151
+ # Generic types
152
+
153
+ Whether you use `data`, `class`, `capability` or `newtype` to define a type, it may have type parameters.
154
+
155
+ ```firefly
156
+ data Basket[T](
157
+ items: List[T]
158
+ )
159
+ ```
160
+
161
+ Here the `T` in `Basket[T]` is a type parameter, and it's used as a type argument in `List[T]`.
162
+
163
+ An unbounded type parameter can be instantiated to any type.
164
+ We can have a `Basket[Shape]`, which has a field `items: List[Shape]`, and a different type `Basket[EventHandler]`, which has a field `items: List[EventHandler]`.
165
+
166
+ Note that type parameters are not concrete types, and are thus not subject to the field type restrictions stated earlier.
167
+
168
+
169
+ # Anonymous records
170
+
171
+ An anonymous record is not defined anywhere, but consists of zero or more fields. The fields may have any type, but can't be reassigned after creation.
172
+
173
+ ```firefly
174
+ (red = 255, green = 255, blue = 0)
175
+ ```
176
+
177
+ This constructs an anonymous record.
178
+ If you have an anonymous record value, e.g. `color: (red: Int, green: Int, blue: Int)`, you can access its fields:
179
+
180
+ ```firefly
181
+ color.red // Returns an Int
182
+ color.green // Returns an Int
183
+ color.blue // Returns an Int
184
+ ```