firefly-compiler 0.5.26 → 0.5.28

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.
@@ -621,13 +621,16 @@ extend self: JsEmitter {
621
621
  } =>
622
622
  let argumentCode = es.map {self.emitTerm(_, async)}.join(", ")
623
623
  Some("(new " + self.emitTerm(e1, async) + "(" + argumentCode + ")" + ")")
624
- | "ff:core/JsValue.JsValue_with" =>
624
+ | name {name == "ff:core/JsValue.JsValue_with" || name == "ff:core/Json.Json_with"} =>
625
625
  function go(e: Term, fields: List[Pair[Term, Term]]): String {
626
626
  e.{
627
- | ECall(_, StaticCall("ff:core/JsValue.JsValue_with", _, _), _, _, [a1, a2, a3], _) =>
627
+ | ECall(_, StaticCall(n, _, _), _, _, [a1, a2, a3], _) {n == name} =>
628
628
  go(a1.value, [Pair(a2.value, a3.value), ...fields])
629
- | ECall(_, StaticCall(name, _, _), _, _, [a], _) {
630
- name == "ff:core/JsSystem.JsSystem_object" || name == "ff:core/JsSystem.JsSystem_new0"
629
+ | ECall(_, StaticCall(n, _, _), _, _, [a], _) {
630
+ n == "ff:core/JsSystem.JsSystem_object" ||
631
+ n == "ff:core/JsSystem.JsSystem_new0" ||
632
+ n == "ff:core/Json.Json_object" ||
633
+ n == "ff:core/Json.Json_new0"
631
634
  } {
632
635
  noSideEffects(a.value)
633
636
  } =>
@@ -660,6 +663,28 @@ extend self: JsEmitter {
660
663
  Some("null")
661
664
  | "ff:core/JsSystem.JsSystem_undefined" {arguments | [e]} {noSideEffects(e)} =>
662
665
  Some("(void 0)")
666
+ | "ff:core/BrowserSystem.BrowserSystem_js" {arguments | [e]} {noSideEffects(e)} =>
667
+ Some("globalThis")
668
+ | "ff:core/BuildSystem.BuildSystem_js" {arguments | [e]} {noSideEffects(e)} =>
669
+ Some("globalThis")
670
+ | "ff:core/NodeSystem.NodeSystem_js" {arguments | [e]} {noSideEffects(e)} =>
671
+ Some("globalThis")
672
+ | "ff:core/UnsafeJs.jsSystem" =>
673
+ Some("globalThis")
674
+ | "ff:core/Json.string" {arguments | [e]} =>
675
+ Some(self.emitTerm(e, async))
676
+ | "ff:core/Json.int" {arguments | [e]} =>
677
+ Some(self.emitTerm(e, async))
678
+ | "ff:core/Json.float" {arguments | [e]} =>
679
+ Some(self.emitTerm(e, async))
680
+ | "ff:core/Json.bool" {arguments | [e]} =>
681
+ Some(self.emitTerm(e, async))
682
+ | "ff:core/Json.array" {arguments | [e]} =>
683
+ Some(self.emitTerm(e, async))
684
+ | "ff:core/Json.null" {arguments | [e]} =>
685
+ Some("null")
686
+ | "ff:core/Json.object" {arguments | [e]} =>
687
+ Some("{}")
663
688
  | _ =>
664
689
  None
665
690
  }
@@ -173,6 +173,23 @@ tokenize(file: String, code: String, completionAt: Option[Location], attemptFixe
173
173
 
174
174
  } elseIf {code.grab(i).isAsciiDigit()} {
175
175
 
176
+ if(i + 2 < code.size() && code.grab(i) == '0' && (
177
+ code.grab(i + 1) == 'x' || code.grab(i + 1) == 'X'
178
+ )) {
179
+ i += 2
180
+ while {i < code.size() && (code.grab(i).isAsciiDigit() || (
181
+ code.grab(i) >= 'a' && code.grab(i) <= 'f'
182
+ ) || (
183
+ code.grab(i) >= 'A' && code.grab(i) <= 'F'
184
+ ))} {
185
+ i += 1
186
+ }
187
+ if(start == i - 2) {
188
+ throwError("Unexpected character: " + Show.show(code.grab(start + 2)))
189
+ }
190
+ emitToken(LInt, start, i)
191
+ } else:
192
+
176
193
  mutable dot = False
177
194
  mutable exponent = False
178
195
  while {i < code.size() && code.grab(i).isAsciiDigit()} {
package/core/Any.ff CHANGED
@@ -1,30 +1,30 @@
1
- data Any {}
2
- data AnyTag[T] {}
3
-
4
- trait T: HasAnyTag {
5
- anyTag(): AnyTag[T]
6
- }
7
-
8
- toAny[T: HasAnyTag](value: T): Any
9
- target js sync """
10
- const anyTag = ff_core_Any_HasAnyTag$T.anyTag_()
11
- return {anyTag: anyTag, value: value_}
12
- """
13
-
14
- fromAny[T: HasAnyTag](any: Any): Option[T]
15
- target js sync """
16
- const anyTag = ff_core_Any_HasAnyTag$T.anyTag_()
17
- return any_.anyTag === anyTag ? ff_core_Option.Some(any_.value) : ff_core_Option.None()
18
- """
19
-
20
- extend self[T]: AnyTag[T] {
21
- show(): String
22
- target js sync """
23
- return self_
24
- """
25
- }
26
-
27
- internalAnyTag[T](tag: String): AnyTag[T]
28
- target js sync """
29
- return tag_
30
- """
1
+ data Any {}
2
+ data AnyTag[T] {}
3
+
4
+ trait T: HasAnyTag {
5
+ anyTag(): AnyTag[T]
6
+ }
7
+
8
+ toAny[T: HasAnyTag](value: T): Any
9
+ target js sync """
10
+ const anyTag = ff_core_Any_HasAnyTag$T.anyTag_()
11
+ return {anyTag: anyTag, value: value_}
12
+ """
13
+
14
+ fromAny[T: HasAnyTag](any: Any): Option[T]
15
+ target js sync """
16
+ const anyTag = ff_core_Any_HasAnyTag$T.anyTag_()
17
+ return any_.anyTag === anyTag ? ff_core_Option.Some(any_.value) : ff_core_Option.None()
18
+ """
19
+
20
+ extend self[T]: AnyTag[T] {
21
+ show(): String
22
+ target js sync """
23
+ return self_
24
+ """
25
+ }
26
+
27
+ internalAnyTag[T](tag: String): AnyTag[T]
28
+ target js sync """
29
+ return tag_
30
+ """
package/core/Json.ff CHANGED
@@ -44,6 +44,11 @@ object(): Json
44
44
  return {};
45
45
  """
46
46
 
47
+ new0(): Json
48
+ target js sync """
49
+ return {};
50
+ """
51
+
47
52
  fields(body: ((String, Json) => Unit) => Unit): Json
48
53
  target js sync """
49
54
  const result = {};
@@ -176,6 +181,10 @@ extend self: Json {
176
181
  return self_ === null;
177
182
  """
178
183
 
184
+ get(key: String): Json {
185
+ self.field(key)
186
+ }
187
+
179
188
  field(key: String): Json
180
189
  target js sync """
181
190
  return typeof self_ === 'object' && self_ !== null && !Array.isArray(self_) && Object.hasOwn(self_, key_)
@@ -1,65 +1,65 @@
1
- main(system: NodeSystem) {
2
- let inBuffers = 1.to(100).map {_ => Buffer.fromByteList([5, 5, 3, 1, 2].toArray())}
3
- let inStream = inBuffers.toStream()
4
- let outStream = toRunLength(inStream, 3)
5
- printRunLength(outStream)
6
- }
7
-
8
- printRunLength(outStream: Stream[Buffer]) {
9
- let buffer = Buffer.fromBufferList(outStream.toArray())
10
- Log.debug(buffer.toHex())
11
- let stack = Stack.make()
12
- mutable i = 0
13
- while {i < buffer.size()} {
14
- 1.to(buffer.grabUint8(i)).each {_ => stack.push(buffer.grabUint8(i + 1))}
15
- i += 2
16
- }
17
- Log.debug(Buffer.fromByteList(stack.drain()).toHex())
18
- }
19
-
20
- toRunLength(stream: Stream[Buffer], bufferSize: Int = 65536): Stream[Buffer] {
21
- mutable outBuffer = Buffer.new(bufferSize)
22
- mutable outOffset = 0
23
- let outBuffers = Stack.make()
24
- function writeByte(byte: Int): Unit {
25
- if(outOffset >= outBuffer.size()) {
26
- outBuffers.push(outBuffer)
27
- outBuffer = Buffer.new(bufferSize)
28
- outOffset = 0
29
- }
30
- outBuffer.setUint8(outOffset, byte)
31
- outOffset += 1
32
- }
33
- mutable extraCount = 0
34
- mutable value = 0
35
- let result = stream.flatMap {inBuffer =>
36
- mutable i = 0
37
- while {i < inBuffer.size()} {
38
- value = if(extraCount > 0) {value} else {inBuffer.grabUint8(i)}
39
- mutable j = if(extraCount > 0) {-1} else {0}
40
- doWhile {
41
- j += 1
42
- j + extraCount < 256 && i + j < inBuffer.size() && inBuffer.grabUint8(i + j) == value
43
- }
44
- i += j
45
- if(i < inBuffer.size() || j + extraCount == 256) {
46
- writeByte(j + extraCount)
47
- writeByte(value)
48
- extraCount = 0
49
- } else {
50
- extraCount += j
51
- }
52
- }
53
- outBuffers.drain().toStream()
54
- }
55
- result.addAll(Stream.init {
56
- if(extraCount > 0) {
57
- writeByte(extraCount)
58
- writeByte(value)
59
- }
60
- if(outOffset > 0) {
61
- outBuffers.push(outBuffer.view(0, outOffset))
62
- }
63
- outBuffers.drain().toStream()
64
- })
65
- }
1
+ main(system: NodeSystem) {
2
+ let inBuffers = 1.to(100).map {_ => Buffer.fromByteList([5, 5, 3, 1, 2].toArray())}
3
+ let inStream = inBuffers.toStream()
4
+ let outStream = toRunLength(inStream, 3)
5
+ printRunLength(outStream)
6
+ }
7
+
8
+ printRunLength(outStream: Stream[Buffer]) {
9
+ let buffer = Buffer.fromBufferList(outStream.toArray())
10
+ Log.debug(buffer.toHex())
11
+ let stack = Stack.make()
12
+ mutable i = 0
13
+ while {i < buffer.size()} {
14
+ 1.to(buffer.grabUint8(i)).each {_ => stack.push(buffer.grabUint8(i + 1))}
15
+ i += 2
16
+ }
17
+ Log.debug(Buffer.fromByteList(stack.drain()).toHex())
18
+ }
19
+
20
+ toRunLength(stream: Stream[Buffer], bufferSize: Int = 65536): Stream[Buffer] {
21
+ mutable outBuffer = Buffer.new(bufferSize)
22
+ mutable outOffset = 0
23
+ let outBuffers = Stack.make()
24
+ function writeByte(byte: Int): Unit {
25
+ if(outOffset >= outBuffer.size()) {
26
+ outBuffers.push(outBuffer)
27
+ outBuffer = Buffer.new(bufferSize)
28
+ outOffset = 0
29
+ }
30
+ outBuffer.setUint8(outOffset, byte)
31
+ outOffset += 1
32
+ }
33
+ mutable extraCount = 0
34
+ mutable value = 0
35
+ let result = stream.flatMap {inBuffer =>
36
+ mutable i = 0
37
+ while {i < inBuffer.size()} {
38
+ value = if(extraCount > 0) {value} else {inBuffer.grabUint8(i)}
39
+ mutable j = if(extraCount > 0) {-1} else {0}
40
+ doWhile {
41
+ j += 1
42
+ j + extraCount < 256 && i + j < inBuffer.size() && inBuffer.grabUint8(i + j) == value
43
+ }
44
+ i += j
45
+ if(i < inBuffer.size() || j + extraCount == 256) {
46
+ writeByte(j + extraCount)
47
+ writeByte(value)
48
+ extraCount = 0
49
+ } else {
50
+ extraCount += j
51
+ }
52
+ }
53
+ outBuffers.drain().toStream()
54
+ }
55
+ result.addAll(Stream.init {
56
+ if(extraCount > 0) {
57
+ writeByte(extraCount)
58
+ writeByte(value)
59
+ }
60
+ if(outOffset > 0) {
61
+ outBuffers.push(outBuffer.view(0, outOffset))
62
+ }
63
+ outBuffers.drain().toStream()
64
+ })
65
+ }
@@ -99,7 +99,7 @@ new(): Document {
99
99
  Text("You can usually fix these without even reading the error message.")
100
100
  Text("And when you need to read the error messages, they're short and to the point.")
101
101
  ])
102
- Image("/assets/image/edit-time-error.png")
102
+ Image("/assets/image/edit-time-error.webp")
103
103
  )
104
104
  SplitSection(
105
105
  "Type driven autocompletion"
@@ -107,7 +107,7 @@ new(): Document {
107
107
  Text("The language server comes with type driven autocompletion.")
108
108
  Text("It instantly presents a very precise list of completions, and the expected type is used to preselect a likely completion.")
109
109
  ])
110
- Image("/assets/image/autocomplete-small.png")
110
+ Image("/assets/image/autocomplete-small.webp")
111
111
  )
112
112
  SplitSection(
113
113
  "No async dilemma"
@@ -133,7 +133,7 @@ renderTopbar(lux: Lux, menu: Bool, setMenu: Bool => Unit) {
133
133
  lux.set("href", "/front/")
134
134
  lux.cssClass(Styles.guideTopbarLogoCss)
135
135
  lux.add("img") {
136
- lux.set("src", "/assets/image/firefly-logo-yellow.png")
136
+ lux.set("src", "/assets/image/firefly-logo-yellow.webp")
137
137
  }
138
138
  lux.div {
139
139
  lux.text("Firefly")
@@ -158,7 +158,7 @@ renderSidebar(lux: Lux, guides: List[Guide], selectedGuide: Guide, selectedHeadi
158
158
  lux.set("href", "/front/")
159
159
  lux.cssClass(Styles.guideSidebarLogoCss)
160
160
  lux.add("img") {
161
- lux.set("src", "/assets/image/firefly-logo-yellow.png")
161
+ lux.set("src", "/assets/image/firefly-logo-yellow.webp")
162
162
  }
163
163
  lux.div {
164
164
  lux.text("Firefly")
@@ -396,39 +396,51 @@ renderHighlightedCode(lux: Lux, code: String) {
396
396
  }.toOption().map {tokens =>
397
397
  mutable offset = 0
398
398
  mutable index = 0
399
- tokens.each {token =>
400
- if(token.startOffset > offset && index <= tokens.size() - 5) {
401
- lux.span {
402
- lux.cssClass(Styles.codeCommentCss)
403
- lux.text(code.slice(offset, token.startOffset))
404
- }
405
- }
406
- if(token.kind != LEnd) {
407
- let css = token.kind.{
408
- | LChar => Styles.codeStringCss
409
- | LFloat => Styles.codeNumberCss
410
- | LInt => Styles.codeNumberCss
411
- | LKeyword => Styles.codeKeywordCss
412
- | LNamespace => Styles.codeTypeCss
413
- | LString => Styles.codeStringCss
414
- | LWildcard => Styles.codeVariableCss
415
- | LUpper {tokens.get(index - 1).any {_.kind == LArrowThin}} => Styles.codeStringCss
416
- | LUpper => Styles.codeTypeCss
417
- | LLower {tokens.get(index - 1).any {_.kind == LArrowThin}} => Styles.codeStringCss
418
- | LLower {tokens.get(index - 1).any {t =>
419
- t.kind == LBracketRight || t.kind == LDot
420
- }} => Styles.codeCallCss
421
- | LLower {tokens.grab(index + 1).kind == LBracketLeft} => Styles.codeCallCss
422
- | LLower => Styles.codeVariableCss
423
- | _ => Styles.codeOtherCss
399
+ lux.span {
400
+ lux.cssClass(Styles.codeOtherCss)
401
+ tokens.each {token =>
402
+ if(token.startOffset > offset && index <= tokens.size() - 5) {
403
+ let text = code.slice(offset, token.startOffset)
404
+ if(text.all {c => c == ' ' || c == '\n'}) {
405
+ lux.text(text)
406
+ } else {
407
+ lux.span {
408
+ lux.cssClass(Styles.codeCommentCss)
409
+ lux.text(text)
410
+ }
411
+ }
424
412
  }
425
- lux.span {
426
- lux.cssClass(css)
427
- lux.text(code.slice(token.startOffset, token.stopOffset))
413
+ if(token.kind != LEnd) {
414
+ let css = token.kind.{
415
+ | LChar => Styles.codeStringCss
416
+ | LFloat => Styles.codeNumberCss
417
+ | LInt => Styles.codeNumberCss
418
+ | LKeyword => Styles.codeKeywordCss
419
+ | LNamespace => Styles.codeTypeCss
420
+ | LString => Styles.codeStringCss
421
+ | LWildcard => Styles.codeVariableCss
422
+ | LUpper {tokens.get(index - 1).any {_.kind == LArrowThin}} => Styles.codeStringCss
423
+ | LUpper => Styles.codeTypeCss
424
+ | LLower {tokens.get(index - 1).any {_.kind == LArrowThin}} => Styles.codeStringCss
425
+ | LLower {tokens.get(index - 1).any {t =>
426
+ t.kind == LBracketRight || t.kind == LDot
427
+ }} => Styles.codeCallCss
428
+ | LLower {tokens.grab(index + 1).kind == LBracketLeft} => Styles.codeCallCss
429
+ | LLower => Styles.codeVariableCss
430
+ | _ => Styles.codeOtherCss
431
+ }
432
+ if(css == Styles.codeOtherCss) {
433
+ lux.text(code.slice(token.startOffset, token.stopOffset))
434
+ } else {
435
+ lux.span {
436
+ lux.cssClass(css)
437
+ lux.text(code.slice(token.startOffset, token.stopOffset))
438
+ }
439
+ }
440
+ offset = token.stopOffset
428
441
  }
429
- offset = token.stopOffset
442
+ index += 1
430
443
  }
431
- index += 1
432
444
  }
433
445
  }.else {lux.text(code)}
434
446
  }
@@ -28,10 +28,10 @@ nodeMain(system: NodeSystem): Unit {
28
28
  serveAsset(system, cacheSalt, request, "text/javascript; charset=UTF-8", asset)
29
29
  | ["favicon.ico"] =>
30
30
  serveAsset(system, cacheSalt, request, "image/png", "/assets/image/firefly-logo-notext.png")
31
- | ["assets", "font", "FireflyMono.ttf"] =>
32
- serveAsset(system, cacheSalt, request, "font/ttf", "/assets/font/NotoSansMono-Regular.ttf")
33
- | ["assets", "font", "FireflySans.ttf"] =>
34
- serveAsset(system, cacheSalt, request, "font/ttf", "/assets/font/NunitoSans-VariableFont_YTLC,opsz,wdth,wght.ttf")
31
+ | ["assets", "font", "firefly-mono.woff2"] =>
32
+ serveAsset(system, cacheSalt, request, "font/woff2", "/assets/font/gf-noto-sans-mono-latin.woff2")
33
+ | ["assets", "font", "firefly-sans.woff2"] =>
34
+ serveAsset(system, cacheSalt, request, "font/woff2", "/assets/font/gf-nunito-sans-latin.woff2")
35
35
  | ["assets", ...rest] => serveAssets(system, cacheSalt, request, rest)
36
36
  | _ {serveGuide(system, request)} =>
37
37
  | _ =>
@@ -107,6 +107,7 @@ guessContentType(path: String): Option[String] {
107
107
  path.split('.').last().flatMap {
108
108
  | "md" => Some("text/markdown")
109
109
  | "png" => Some("image/png")
110
+ | "webp" => Some("image/webp")
110
111
  | "ttf" => Some("font/ttf")
111
112
  | _ => None
112
113
  }
@@ -132,16 +133,16 @@ serveGuideHtml(title: String, contentHtml: String, styleTags: String, request: W
132
133
  request.writeHeader("Content-Type", "text/html; charset=UTF-8")
133
134
  request.writeText("<!doctype html>")
134
135
  request.writeText("<html lang='en' style='background-color: #ffffff; color: #333333; width: 100%; height: 100%; color-scheme: light;'>")
135
- request.writeText("<script type='module' src='/js/ff/fireflysite/Main.mjs'></script>")
136
136
  request.writeText("<head>")
137
137
  request.writeText("<title>" + title + "</title>")
138
138
  request.writeText("<meta name='viewport' content='width=device-width, initial-scale=1.0'>")
139
139
  request.writeText("<meta name='theme-color' content='#ecc45e'>")
140
- request.writeText("<link rel='preload' href='/assets/font/FireflyMono.ttf' as='font' crossorigin='anonymous'>")
141
- request.writeText("<link rel='preload' href='/assets/font/FireflySans.ttf' as='font' crossorigin='anonymous'>")
142
- request.writeText("<link rel='preload' href='/assets/image/firefly-logo-yellow.png' as='image'>")
143
- request.writeText("<style>@font-face { font-family: 'Firefly Mono'; font-display: fallback; src: url('/assets/font/FireflyMono.ttf'); unicode-range: U+000-5FF; }</style>")
144
- request.writeText("<style>@font-face { font-family: 'Firefly Sans'; font-display: fallback; src: url('/assets/font/FireflySans.ttf'); unicode-range: U+000-5FF; }</style>")
140
+ request.writeText("<script type='module' src='/js/ff/fireflysite/Main.mjs'></script>")
141
+ request.writeText("<link rel='preload' href='/assets/font/firefly-mono.woff2' as='font' crossorigin='anonymous'>")
142
+ request.writeText("<link rel='preload' href='/assets/font/firefly-sans.woff2' as='font' crossorigin='anonymous'>")
143
+ request.writeText("<link rel='preload' href='/assets/image/firefly-logo-yellow.webp' as='image'>")
144
+ request.writeText("<style>@font-face { font-family: 'Firefly Mono'; font-display: fallback; src: url('/assets/font/firefly-mono.woff2'); }</style>")
145
+ request.writeText("<style>@font-face { font-family: 'Firefly Sans'; font-display: fallback; src: url('/assets/font/firefly-sans.woff2'); }</style>")
145
146
  request.writeText(styleTags)
146
147
  request.writeText("</head>")
147
148
  request.writeText("<body style='margin: 0; padding: 0; width: 100%; height: 100%; touch-action: manipulation;'>")
@@ -314,70 +314,50 @@ Firefly has methods, which are called like this:
314
314
 
315
315
  ```firefly
316
316
  Some(1).isEmpty() // False
317
- Some(1).map {_ + 1} // Some(2)
317
+ Some(1).map({_ + 1}) // Some(2)
318
318
  ```
319
319
 
320
- The examples above, calls the two methods `isEmpty` and `map` defined on `Option`. The code below, shows how these methods are defined in `ff:core` package.
320
+ The examples above, calls the two methods `isEmpty` and `map` defined on `Option`. The code below, shows how these methods are defined in `ff:core` package:
321
321
 
322
322
  ```firefly
323
- data Option[T] {
324
- None
325
- Some(value: T)
326
- }
327
-
328
323
  extend self[T]: Option[T] {
329
- isEmpty(): Bool {
330
- self.{
331
- | None => True
332
- | Some(_) => False
333
- }
334
- }
335
-
336
- map[R](body: T => R): Option[R] {
337
- self.{
338
- | None => None
339
- | Some(v) => Some(body(v))
340
- }
341
- }
324
+ isEmpty(): Bool {...}
325
+ map[R](body: T => R): Option[R] {...}
342
326
  }
343
327
  ```
344
328
 
329
+ The `extend` keyword is used to declare methods on values of a given type. The code above extend values of type `Option[T]` with two methods. The identifier `self` holds a reference to the value receiving the methods. The square bracket right after the self variable are optional and used to introduce type variables used to express the type extended with methods.
345
330
 
346
- Methods can be defined for a more narrow targer type, like `flatten` below:
331
+ The two methods above are defined for all values of type `Option[T]`, but methods can be også be defined for a more narrow targer type, like `flatten` below:
347
332
 
348
333
  ```firefly
349
334
  extend self[T]: Option[Option[T]] {
350
- flatten(): Option[T] {
351
- self.{
352
- | None => None
353
- | Some(v) => v
354
- }
355
- }
335
+ flatten(): Option[T] {...}
356
336
  }
357
337
  ```
358
338
 
359
- The extend block above, will only define `flatten` for options types of options.
360
-
361
- In code below, the extend block defines methods for the target type `Option[T]`, but only when `T` implements the `Equal` trait.
339
+ The extend block above declares `self` as ` Option[Option[T]]`, and likewise will only define `flatten` for options types of options.
362
340
 
341
+ The scope of a method can also be narrowed down with trait constraints.
363
342
 
364
343
  ```firefly
365
344
  extend self[T: Equal]: Option[T] {
366
- contains(value: T): Bool {
367
- self.{
368
- | None => False
369
- | Some(v) => v == value
370
- }
371
- }
345
+ contains(value: T): Bool {...}
372
346
  }
373
347
  ```
374
348
 
349
+ In code above, the extend block defines methods for the target type `Option[T]`, but only when `T` implements the `Equal` trait.
350
+
351
+ Extend blocks must reside in the same module at definition of the type that are extended with methods.
375
352
 
353
+ Methods are equivalent to top level functions in terms of expressibility but differnt in terms of scoping. Each type definition has its own method scope.
376
354
 
377
355
  # Special method call syntax
378
356
 
379
357
  ```firefly
380
358
  if(x == 1) {"One"} else {"Several"}
359
+ Some(1).map {_ + 1} // Some(2)
360
+
381
361
  ```
382
362
 
383
363
  # Trait functions
@@ -1795,20 +1795,25 @@ return ff_core_Option.Some(((((("(new " + ff_compiler_JsEmitter.JsEmitter_emitTe
1795
1795
  }
1796
1796
  }
1797
1797
  }
1798
- if(_1 === "ff:core/JsValue.JsValue_with") {
1798
+ {
1799
+ const name_ = _1;
1800
+ if(((name_ === "ff:core/JsValue.JsValue_with") || (name_ === "ff:core/Json.Json_with"))) {
1799
1801
  function go_(e_, fields_) {
1800
1802
  {
1801
1803
  const _1 = e_;
1802
- if(_1.ECall && _1.target_.StaticCall && _1.target_.name_ === "ff:core/JsValue.JsValue_with" && _1.arguments_.length === 3) {
1804
+ if(_1.ECall && _1.target_.StaticCall && _1.arguments_.length === 3) {
1805
+ const n_ = _1.target_.name_;
1803
1806
  const a1_ = _1.arguments_[0];
1804
1807
  const a2_ = _1.arguments_[1];
1805
1808
  const a3_ = _1.arguments_[2];
1809
+ if((n_ === name_)) {
1806
1810
  return go_(a1_.value_, [ff_core_Pair.Pair(a2_.value_, a3_.value_), ...fields_])
1807
1811
  }
1812
+ }
1808
1813
  if(_1.ECall && _1.target_.StaticCall && _1.arguments_.length === 1) {
1809
- const name_ = _1.target_.name_;
1814
+ const n_ = _1.target_.name_;
1810
1815
  const a_ = _1.arguments_[0];
1811
- const _guard2 = ((name_ === "ff:core/JsSystem.JsSystem_object") || (name_ === "ff:core/JsSystem.JsSystem_new0"));
1816
+ const _guard2 = ((((n_ === "ff:core/JsSystem.JsSystem_object") || (n_ === "ff:core/JsSystem.JsSystem_new0")) || (n_ === "ff:core/Json.Json_object")) || (n_ === "ff:core/Json.Json_new0"));
1812
1817
  if(_guard2 && ff_compiler_JsEmitter.noSideEffects_(a_.value_)) {
1813
1818
  return (("{" + ff_core_List.List_join(ff_core_List.List_map(fields_, ((p_) => {
1814
1819
  return ((ff_compiler_JsEmitter.JsEmitter_emitField(self_, p_.first_, async_, "") + ": ") + ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, p_.second_, async_))
@@ -1826,6 +1831,7 @@ return
1826
1831
  }
1827
1832
  return ff_core_Option.Some(go_(term_, []))
1828
1833
  }
1834
+ }
1829
1835
  {
1830
1836
  const name_ = _1;
1831
1837
  const _guard4 = ff_core_String.String_removeFirst(name_, "ff:core/JsSystem.JsSystem_call");
@@ -1931,6 +1937,85 @@ return ff_core_Option.Some("(void 0)")
1931
1937
  }
1932
1938
  }
1933
1939
  }
1940
+ if(_1 === "ff:core/BrowserSystem.BrowserSystem_js") {
1941
+ const _guard2 = arguments_;
1942
+ if(_guard2.length === 1) {
1943
+ const e_ = _guard2[0];
1944
+ if(ff_compiler_JsEmitter.noSideEffects_(e_)) {
1945
+ return ff_core_Option.Some("globalThis")
1946
+ }
1947
+ }
1948
+ }
1949
+ if(_1 === "ff:core/BuildSystem.BuildSystem_js") {
1950
+ const _guard2 = arguments_;
1951
+ if(_guard2.length === 1) {
1952
+ const e_ = _guard2[0];
1953
+ if(ff_compiler_JsEmitter.noSideEffects_(e_)) {
1954
+ return ff_core_Option.Some("globalThis")
1955
+ }
1956
+ }
1957
+ }
1958
+ if(_1 === "ff:core/NodeSystem.NodeSystem_js") {
1959
+ const _guard2 = arguments_;
1960
+ if(_guard2.length === 1) {
1961
+ const e_ = _guard2[0];
1962
+ if(ff_compiler_JsEmitter.noSideEffects_(e_)) {
1963
+ return ff_core_Option.Some("globalThis")
1964
+ }
1965
+ }
1966
+ }
1967
+ if(_1 === "ff:core/UnsafeJs.jsSystem") {
1968
+ return ff_core_Option.Some("globalThis")
1969
+ }
1970
+ if(_1 === "ff:core/Json.string") {
1971
+ const _guard1 = arguments_;
1972
+ if(_guard1.length === 1) {
1973
+ const e_ = _guard1[0];
1974
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
1975
+ }
1976
+ }
1977
+ if(_1 === "ff:core/Json.int") {
1978
+ const _guard1 = arguments_;
1979
+ if(_guard1.length === 1) {
1980
+ const e_ = _guard1[0];
1981
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
1982
+ }
1983
+ }
1984
+ if(_1 === "ff:core/Json.float") {
1985
+ const _guard1 = arguments_;
1986
+ if(_guard1.length === 1) {
1987
+ const e_ = _guard1[0];
1988
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
1989
+ }
1990
+ }
1991
+ if(_1 === "ff:core/Json.bool") {
1992
+ const _guard1 = arguments_;
1993
+ if(_guard1.length === 1) {
1994
+ const e_ = _guard1[0];
1995
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
1996
+ }
1997
+ }
1998
+ if(_1 === "ff:core/Json.array") {
1999
+ const _guard1 = arguments_;
2000
+ if(_guard1.length === 1) {
2001
+ const e_ = _guard1[0];
2002
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
2003
+ }
2004
+ }
2005
+ if(_1 === "ff:core/Json.null") {
2006
+ const _guard1 = arguments_;
2007
+ if(_guard1.length === 1) {
2008
+ const e_ = _guard1[0];
2009
+ return ff_core_Option.Some("null")
2010
+ }
2011
+ }
2012
+ if(_1 === "ff:core/Json.object") {
2013
+ const _guard1 = arguments_;
2014
+ if(_guard1.length === 1) {
2015
+ const e_ = _guard1[0];
2016
+ return ff_core_Option.Some("{}")
2017
+ }
2018
+ }
1934
2019
  {
1935
2020
  return ff_core_Option.None()
1936
2021
  }
@@ -3782,20 +3867,25 @@ return ff_core_Option.Some(((((("(new " + ff_compiler_JsEmitter.JsEmitter_emitTe
3782
3867
  }
3783
3868
  }
3784
3869
  }
3785
- if(_1 === "ff:core/JsValue.JsValue_with") {
3870
+ {
3871
+ const name_ = _1;
3872
+ if(((name_ === "ff:core/JsValue.JsValue_with") || (name_ === "ff:core/Json.Json_with"))) {
3786
3873
  function go_(e_, fields_) {
3787
3874
  {
3788
3875
  const _1 = e_;
3789
- if(_1.ECall && _1.target_.StaticCall && _1.target_.name_ === "ff:core/JsValue.JsValue_with" && _1.arguments_.length === 3) {
3876
+ if(_1.ECall && _1.target_.StaticCall && _1.arguments_.length === 3) {
3877
+ const n_ = _1.target_.name_;
3790
3878
  const a1_ = _1.arguments_[0];
3791
3879
  const a2_ = _1.arguments_[1];
3792
3880
  const a3_ = _1.arguments_[2];
3881
+ if((n_ === name_)) {
3793
3882
  return go_(a1_.value_, [ff_core_Pair.Pair(a2_.value_, a3_.value_), ...fields_])
3794
3883
  }
3884
+ }
3795
3885
  if(_1.ECall && _1.target_.StaticCall && _1.arguments_.length === 1) {
3796
- const name_ = _1.target_.name_;
3886
+ const n_ = _1.target_.name_;
3797
3887
  const a_ = _1.arguments_[0];
3798
- const _guard2 = ((name_ === "ff:core/JsSystem.JsSystem_object") || (name_ === "ff:core/JsSystem.JsSystem_new0"));
3888
+ const _guard2 = ((((n_ === "ff:core/JsSystem.JsSystem_object") || (n_ === "ff:core/JsSystem.JsSystem_new0")) || (n_ === "ff:core/Json.Json_object")) || (n_ === "ff:core/Json.Json_new0"));
3799
3889
  if(_guard2 && ff_compiler_JsEmitter.noSideEffects_(a_.value_)) {
3800
3890
  return (("{" + ff_core_List.List_join(ff_core_List.List_map(fields_, ((p_) => {
3801
3891
  return ((ff_compiler_JsEmitter.JsEmitter_emitField(self_, p_.first_, async_, "") + ": ") + ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, p_.second_, async_))
@@ -3813,6 +3903,7 @@ return
3813
3903
  }
3814
3904
  return ff_core_Option.Some(go_(term_, []))
3815
3905
  }
3906
+ }
3816
3907
  {
3817
3908
  const name_ = _1;
3818
3909
  const _guard4 = ff_core_String.String_removeFirst(name_, "ff:core/JsSystem.JsSystem_call");
@@ -3918,6 +4009,85 @@ return ff_core_Option.Some("(void 0)")
3918
4009
  }
3919
4010
  }
3920
4011
  }
4012
+ if(_1 === "ff:core/BrowserSystem.BrowserSystem_js") {
4013
+ const _guard2 = arguments_;
4014
+ if(_guard2.length === 1) {
4015
+ const e_ = _guard2[0];
4016
+ if(ff_compiler_JsEmitter.noSideEffects_(e_)) {
4017
+ return ff_core_Option.Some("globalThis")
4018
+ }
4019
+ }
4020
+ }
4021
+ if(_1 === "ff:core/BuildSystem.BuildSystem_js") {
4022
+ const _guard2 = arguments_;
4023
+ if(_guard2.length === 1) {
4024
+ const e_ = _guard2[0];
4025
+ if(ff_compiler_JsEmitter.noSideEffects_(e_)) {
4026
+ return ff_core_Option.Some("globalThis")
4027
+ }
4028
+ }
4029
+ }
4030
+ if(_1 === "ff:core/NodeSystem.NodeSystem_js") {
4031
+ const _guard2 = arguments_;
4032
+ if(_guard2.length === 1) {
4033
+ const e_ = _guard2[0];
4034
+ if(ff_compiler_JsEmitter.noSideEffects_(e_)) {
4035
+ return ff_core_Option.Some("globalThis")
4036
+ }
4037
+ }
4038
+ }
4039
+ if(_1 === "ff:core/UnsafeJs.jsSystem") {
4040
+ return ff_core_Option.Some("globalThis")
4041
+ }
4042
+ if(_1 === "ff:core/Json.string") {
4043
+ const _guard1 = arguments_;
4044
+ if(_guard1.length === 1) {
4045
+ const e_ = _guard1[0];
4046
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
4047
+ }
4048
+ }
4049
+ if(_1 === "ff:core/Json.int") {
4050
+ const _guard1 = arguments_;
4051
+ if(_guard1.length === 1) {
4052
+ const e_ = _guard1[0];
4053
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
4054
+ }
4055
+ }
4056
+ if(_1 === "ff:core/Json.float") {
4057
+ const _guard1 = arguments_;
4058
+ if(_guard1.length === 1) {
4059
+ const e_ = _guard1[0];
4060
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
4061
+ }
4062
+ }
4063
+ if(_1 === "ff:core/Json.bool") {
4064
+ const _guard1 = arguments_;
4065
+ if(_guard1.length === 1) {
4066
+ const e_ = _guard1[0];
4067
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
4068
+ }
4069
+ }
4070
+ if(_1 === "ff:core/Json.array") {
4071
+ const _guard1 = arguments_;
4072
+ if(_guard1.length === 1) {
4073
+ const e_ = _guard1[0];
4074
+ return ff_core_Option.Some(ff_compiler_JsEmitter.JsEmitter_emitTerm(self_, e_, async_))
4075
+ }
4076
+ }
4077
+ if(_1 === "ff:core/Json.null") {
4078
+ const _guard1 = arguments_;
4079
+ if(_guard1.length === 1) {
4080
+ const e_ = _guard1[0];
4081
+ return ff_core_Option.Some("null")
4082
+ }
4083
+ }
4084
+ if(_1 === "ff:core/Json.object") {
4085
+ const _guard1 = arguments_;
4086
+ if(_guard1.length === 1) {
4087
+ const e_ = _guard1[0];
4088
+ return ff_core_Option.Some("{}")
4089
+ }
4090
+ }
3921
4091
  {
3922
4092
  return ff_core_Option.None()
3923
4093
  }
@@ -254,6 +254,16 @@ emitToken_(ff_compiler_Token.LNamespace(), start_, i_)
254
254
  emitToken_(kind_, start_, i_)
255
255
  }
256
256
  } else if(ff_core_Char.Char_isAsciiDigit(ff_core_String.String_grab(code_, i_))) {
257
+ if(((((i_ + 2) < ff_core_String.String_size(code_)) && (ff_core_String.String_grab(code_, i_) === 48)) && ((ff_core_String.String_grab(code_, (i_ + 1)) === 120) || (ff_core_String.String_grab(code_, (i_ + 1)) === 88)))) {
258
+ i_ += 2;
259
+ while(((i_ < ff_core_String.String_size(code_)) && ((ff_core_Char.Char_isAsciiDigit(ff_core_String.String_grab(code_, i_)) || ((ff_core_String.String_grab(code_, i_) >= 97) && (ff_core_String.String_grab(code_, i_) <= 102))) || ((ff_core_String.String_grab(code_, i_) >= 65) && (ff_core_String.String_grab(code_, i_) <= 70))))) {
260
+ i_ += 1
261
+ };
262
+ if((start_ === (i_ - 2))) {
263
+ throwError_(("Unexpected character: " + ff_core_Show.ff_core_Show_Show$ff_core_Char_Char.show_(ff_core_String.String_grab(code_, (start_ + 2)))))
264
+ };
265
+ emitToken_(ff_compiler_Token.LInt(), start_, i_)
266
+ } else {
257
267
  let dot_ = false;
258
268
  let exponent_ = false;
259
269
  while(((i_ < ff_core_String.String_size(code_)) && ff_core_Char.Char_isAsciiDigit(ff_core_String.String_grab(code_, i_)))) {
@@ -274,6 +284,7 @@ dot_ = true
274
284
  emitToken_(((dot_ || exponent_)
275
285
  ? ff_compiler_Token.LFloat()
276
286
  : ff_compiler_Token.LInt()), start_, i_)
287
+ }
277
288
  } else if((ff_core_String.String_grab(code_, i_) === 95)) {
278
289
  i_ += 1;
279
290
  emitToken_(ff_compiler_Token.LWildcard(), start_, i_)
@@ -501,6 +512,16 @@ emitToken_(ff_compiler_Token.LNamespace(), start_, i_)
501
512
  emitToken_(kind_, start_, i_)
502
513
  }
503
514
  } else if(ff_core_Char.Char_isAsciiDigit(ff_core_String.String_grab(code_, i_))) {
515
+ if(((((i_ + 2) < ff_core_String.String_size(code_)) && (ff_core_String.String_grab(code_, i_) === 48)) && ((ff_core_String.String_grab(code_, (i_ + 1)) === 120) || (ff_core_String.String_grab(code_, (i_ + 1)) === 88)))) {
516
+ i_ += 2;
517
+ while(((i_ < ff_core_String.String_size(code_)) && ((ff_core_Char.Char_isAsciiDigit(ff_core_String.String_grab(code_, i_)) || ((ff_core_String.String_grab(code_, i_) >= 97) && (ff_core_String.String_grab(code_, i_) <= 102))) || ((ff_core_String.String_grab(code_, i_) >= 65) && (ff_core_String.String_grab(code_, i_) <= 70))))) {
518
+ i_ += 1
519
+ };
520
+ if((start_ === (i_ - 2))) {
521
+ throwError_(("Unexpected character: " + ff_core_Show.ff_core_Show_Show$ff_core_Char_Char.show_(ff_core_String.String_grab(code_, (start_ + 2)))))
522
+ };
523
+ emitToken_(ff_compiler_Token.LInt(), start_, i_)
524
+ } else {
504
525
  let dot_ = false;
505
526
  let exponent_ = false;
506
527
  while(((i_ < ff_core_String.String_size(code_)) && ff_core_Char.Char_isAsciiDigit(ff_core_String.String_grab(code_, i_)))) {
@@ -521,6 +542,7 @@ dot_ = true
521
542
  emitToken_(((dot_ || exponent_)
522
543
  ? ff_compiler_Token.LFloat()
523
544
  : ff_compiler_Token.LInt()), start_, i_)
545
+ }
524
546
  } else if((ff_core_String.String_grab(code_, i_) === 95)) {
525
547
  i_ += 1;
526
548
  emitToken_(ff_compiler_Token.LWildcard(), start_, i_)
@@ -101,22 +101,22 @@ import * as ff_core_UnsafeJs from "../../ff/core/UnsafeJs.mjs"
101
101
 
102
102
 
103
103
  export function toAny_(value_, ff_core_Any_HasAnyTag$T) {
104
-
105
- const anyTag = ff_core_Any_HasAnyTag$T.anyTag_()
106
- return {anyTag: anyTag, value: value_}
104
+
105
+ const anyTag = ff_core_Any_HasAnyTag$T.anyTag_()
106
+ return {anyTag: anyTag, value: value_}
107
107
 
108
108
  }
109
109
 
110
110
  export function fromAny_(any_, ff_core_Any_HasAnyTag$T) {
111
-
112
- const anyTag = ff_core_Any_HasAnyTag$T.anyTag_()
113
- return any_.anyTag === anyTag ? ff_core_Option.Some(any_.value) : ff_core_Option.None()
111
+
112
+ const anyTag = ff_core_Any_HasAnyTag$T.anyTag_()
113
+ return any_.anyTag === anyTag ? ff_core_Option.Some(any_.value) : ff_core_Option.None()
114
114
 
115
115
  }
116
116
 
117
117
  export function internalAnyTag_(tag_) {
118
-
119
- return tag_
118
+
119
+ return tag_
120
120
 
121
121
  }
122
122
 
@@ -133,8 +133,8 @@ throw new Error('Function internalAnyTag is missing on this target in async cont
133
133
  }
134
134
 
135
135
  export function AnyTag_show(self_) {
136
-
137
- return self_
136
+
137
+ return self_
138
138
 
139
139
  }
140
140
 
@@ -149,6 +149,12 @@ export function object_() {
149
149
 
150
150
  }
151
151
 
152
+ export function new0_() {
153
+
154
+ return {};
155
+
156
+ }
157
+
152
158
  export function fields_(body_) {
153
159
 
154
160
  const result = {};
@@ -273,6 +279,10 @@ export async function object_$($task) {
273
279
  throw new Error('Function object is missing on this target in async context.');
274
280
  }
275
281
 
282
+ export async function new0_$($task) {
283
+ throw new Error('Function new0 is missing on this target in async context.');
284
+ }
285
+
276
286
  export async function fields_$(body_, $task) {
277
287
 
278
288
  const result = {};
@@ -445,6 +455,10 @@ export function Json_isNull(self_) {
445
455
 
446
456
  }
447
457
 
458
+ export function Json_get(self_, key_) {
459
+ return ff_core_Json.Json_field(self_, key_)
460
+ }
461
+
448
462
  export function Json_field(self_, key_) {
449
463
 
450
464
  return typeof self_ === 'object' && self_ !== null && !Array.isArray(self_) && Object.hasOwn(self_, key_)
@@ -636,6 +650,10 @@ export async function Json_isNull$(self_, $task) {
636
650
  throw new Error('Function Json_isNull is missing on this target in async context.');
637
651
  }
638
652
 
653
+ export async function Json_get$(self_, key_, $task) {
654
+ return ff_core_Json.Json_field(self_, key_)
655
+ }
656
+
639
657
  export async function Json_field$(self_, key_, $task) {
640
658
  throw new Error('Function Json_field is missing on this target in async context.');
641
659
  }
@@ -725,7 +743,7 @@ return ff_core_Option.Some(json_)
725
743
 
726
744
  export const ff_core_Json_JsonLike$ff_core_String_String = {
727
745
  toJson_(value_) {
728
- return ff_core_Json.string_(value_)
746
+ return value_
729
747
  },
730
748
  fromJson_(json_) {
731
749
  const json_a = json_;
@@ -735,7 +753,7 @@ return ff_core_Json.Json_getString(_w1)
735
753
  }
736
754
  },
737
755
  async toJson_$(value_, $task) {
738
- return ff_core_Json.string_(value_)
756
+ return value_
739
757
  },
740
758
  async fromJson_$(json_, $task) {
741
759
  const json_a = json_;
@@ -748,7 +766,7 @@ return ff_core_Json.Json_getString(_w1)
748
766
 
749
767
  export const ff_core_Json_JsonLike$ff_core_Int_Int = {
750
768
  toJson_(value_) {
751
- return ff_core_Json.int_(value_)
769
+ return value_
752
770
  },
753
771
  fromJson_(json_) {
754
772
  const json_a = json_;
@@ -758,7 +776,7 @@ return ff_core_Json.Json_getInt(_w1)
758
776
  }
759
777
  },
760
778
  async toJson_$(value_, $task) {
761
- return ff_core_Json.int_(value_)
779
+ return value_
762
780
  },
763
781
  async fromJson_$(json_, $task) {
764
782
  const json_a = json_;
@@ -771,7 +789,7 @@ return ff_core_Json.Json_getInt(_w1)
771
789
 
772
790
  export const ff_core_Json_JsonLike$ff_core_Float_Float = {
773
791
  toJson_(value_) {
774
- return ff_core_Json.float_(value_)
792
+ return value_
775
793
  },
776
794
  fromJson_(json_) {
777
795
  const json_a = json_;
@@ -781,7 +799,7 @@ return ff_core_Json.Json_getFloat(_w1)
781
799
  }
782
800
  },
783
801
  async toJson_$(value_, $task) {
784
- return ff_core_Json.float_(value_)
802
+ return value_
785
803
  },
786
804
  async fromJson_$(json_, $task) {
787
805
  const json_a = json_;
@@ -794,7 +812,7 @@ return ff_core_Json.Json_getFloat(_w1)
794
812
 
795
813
  export const ff_core_Json_JsonLike$ff_core_Bool_Bool = {
796
814
  toJson_(value_) {
797
- return ff_core_Json.bool_(value_)
815
+ return value_
798
816
  },
799
817
  fromJson_(json_) {
800
818
  const json_a = json_;
@@ -804,7 +822,7 @@ return ff_core_Json.Json_getBool(_w1)
804
822
  }
805
823
  },
806
824
  async toJson_$(value_, $task) {
807
- return ff_core_Json.bool_(value_)
825
+ return value_
808
826
  },
809
827
  async fromJson_$(json_, $task) {
810
828
  const json_a = json_;
@@ -817,9 +835,9 @@ return ff_core_Json.Json_getBool(_w1)
817
835
 
818
836
  export function ff_core_Json_JsonLike$ff_core_List_List(ff_core_Json_JsonLike$T) { return {
819
837
  toJson_(value_) {
820
- return ff_core_Json.array_(ff_core_List.List_map(value_, ((value_) => {
838
+ return ff_core_List.List_map(value_, ((value_) => {
821
839
  return ff_core_Json_JsonLike$T.toJson_(value_)
822
- })))
840
+ }))
823
841
  },
824
842
  fromJson_(json_) {
825
843
  return ff_core_Option.Option_flatMap(ff_core_Json.Json_getArray(json_), ((array_) => {
@@ -847,9 +865,9 @@ return ff_core_Option.Some(ff_core_Array.Array_drain(result_))
847
865
  }))
848
866
  },
849
867
  async toJson_$(value_, $task) {
850
- return ff_core_Json.array_(ff_core_List.List_map(value_, ((value_) => {
868
+ return ff_core_List.List_map(value_, ((value_) => {
851
869
  return ff_core_Json_JsonLike$T.toJson_(value_)
852
- })))
870
+ }))
853
871
  },
854
872
  async fromJson_$(json_, $task) {
855
873
  return ff_core_Option.Option_flatMap(ff_core_Json.Json_getArray(json_), ((array_) => {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "description": "Firefly compiler",
5
5
  "author": "Firefly team",
6
6
  "license": "MIT",
7
- "version": "0.5.26",
7
+ "version": "0.5.28",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"
@@ -4,7 +4,7 @@
4
4
  "description": "Firefly language support",
5
5
  "author": "Firefly team",
6
6
  "license": "MIT",
7
- "version": "0.5.26",
7
+ "version": "0.5.28",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"