firefly-compiler 0.4.69 → 0.4.71

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.
@@ -91,11 +91,12 @@ extend self: Dependencies {
91
91
  dependencyLock.do(donePath.absolute()) {
92
92
  if(!donePath.exists()) {
93
93
  Log.trace("Fetching " + location)
94
- let response = httpClient.fetch(location, throw = False)
95
- if(!response.ok()) {
96
- panic("Could not download dependency: " + location)
94
+ let buffer = httpClient.get(location, []) {response =>
95
+ if(!response.ok()) {
96
+ panic("Could not download dependency: " + location)
97
+ }
98
+ response.readBuffer()
97
99
  }
98
- let buffer = response.readBuffer()
99
100
  if(dependencyPath.exists()) {
100
101
  dependencyPath.delete()
101
102
  }
@@ -3,7 +3,7 @@ capability BrowserSystem {}
3
3
  extend self: BrowserSystem {
4
4
 
5
5
  httpClient(): HttpClient
6
- target js async "return null"
6
+ target js async "return typeof globalThis !== 'undefined' ? globalThis : window"
7
7
 
8
8
  mainTask(): Task
9
9
  target js async "return self_.task_"
package/core/Float.ff CHANGED
@@ -27,134 +27,142 @@ extend self: Float {
27
27
  target js sync "return self_.toFixed(digits_)"
28
28
 
29
29
  min(that: Float): Float
30
- target js sync "return Math.min(self, that)"
30
+ target js sync "return Math.min(self_, that_)"
31
31
 
32
32
  max(that: Float): Float
33
- target js sync "return Math.max(self, that)"
33
+ target js sync "return Math.max(self_, that_)"
34
34
 
35
- clamp(from: Float, to: Float): Float {
36
- if(self <= from) {from} elseIf {self >= to} {to} else {self}
35
+ clamp(from: Float, to: Float): Float
36
+ target js sync "return Math.min(Math.max(self_, from_), to_)"
37
+
38
+ lerp(that: Float, factor: Float): Float {
39
+ self + factor * (that - self)
40
+ }
41
+
42
+ smoothstep(that: Float, factor: Float): Float {
43
+ let t = ((factor - self) / (that - self)).clamp(0.0, 1.0)
44
+ t * t * (3.0 - 2.0 * t)
37
45
  }
38
46
 
39
- expDecay(that: Float, decay: Float, delta: Duration): Float {
40
- that + (self - that) * (-decay * delta.seconds).exp()
47
+ expDecay(that: Float, decay: Float, factor: Float): Float {
48
+ that + (self - that) * (-decay * factor).exp()
41
49
  }
42
50
 
43
51
  acos(): Float
44
52
  target js sync """
45
- return Math.acos(self);
53
+ return Math.acos(self_);
46
54
  """
47
55
 
48
56
  acosh(): Float
49
57
  target js sync """
50
- return Math.acosh(self);
58
+ return Math.acosh(self_);
51
59
  """
52
60
 
53
61
  asin(): Float
54
62
  target js sync """
55
- return Math.asin(self);
63
+ return Math.asin(self_);
56
64
  """
57
65
 
58
66
  asinh(): Float
59
67
  target js sync """
60
- return Math.asinh(self);
68
+ return Math.asinh(self_);
61
69
  """
62
70
 
63
71
  atan(): Float
64
72
  target js sync """
65
- return Math.atan(self);
73
+ return Math.atan(self_);
66
74
  """
67
75
 
68
76
  atan2(that: Float): Float
69
77
  target js sync """
70
- return Math.atan2(self, that);
78
+ return Math.atan2(self_, that_);
71
79
  """
72
80
 
73
81
  atanh(): Float
74
82
  target js sync """
75
- return Math.atanh(self);
83
+ return Math.atanh(self_);
76
84
  """
77
85
 
78
86
  cbrt(): Float
79
87
  target js sync """
80
- return Math.cbrt(self);
88
+ return Math.cbrt(self_);
81
89
  """
82
90
 
83
91
  cos(): Float
84
92
  target js sync """
85
- return Math.cos(self);
93
+ return Math.cos(self_);
86
94
  """
87
95
 
88
96
  cosh(): Float
89
97
  target js sync """
90
- return Math.cosh(self);
98
+ return Math.cosh(self_);
91
99
  """
92
100
 
93
101
  exp(): Float
94
102
  target js sync """
95
- return Math.exp(self);
103
+ return Math.exp(self_);
96
104
  """
97
105
 
98
106
  expm1(): Float
99
107
  target js sync """
100
- return Math.expm1(self);
108
+ return Math.expm1(self_);
101
109
  """
102
110
 
103
111
  log(that: Float): Float
104
112
  target js sync """
105
- return Math.log2(self) / Math.log2(that);
113
+ return Math.log2(self_) / Math.log2(that_);
106
114
  """
107
115
 
108
116
  log10(): Float
109
117
  target js sync """
110
- return Math.log10(self);
118
+ return Math.log10(self_);
111
119
  """
112
120
 
113
121
  log2(): Float
114
122
  target js sync """
115
- return Math.log2(self);
123
+ return Math.log2(self_);
116
124
  """
117
125
 
118
126
  ln(): Float
119
127
  target js sync """
120
- return Math.log(self);
128
+ return Math.log(self_);
121
129
  """
122
130
 
123
131
  ln1p(): Float
124
132
  target js sync """
125
- return Math.log1p(self);
133
+ return Math.log1p(self_);
126
134
  """
127
135
 
128
136
  sin(): Float
129
137
  target js sync """
130
- return Math.sin(self);
138
+ return Math.sin(self_);
131
139
  """
132
140
 
133
141
  sinh(): Float
134
142
  target js sync """
135
- return Math.sinh(self);
143
+ return Math.sinh(self_);
136
144
  """
137
145
 
138
146
  sqrt(): Float
139
147
  target js sync """
140
- return Math.sqrt(self);
148
+ return Math.sqrt(self_);
141
149
  """
142
150
 
143
151
  tan(): Float
144
152
  target js sync """
145
- return Math.tan(self);
153
+ return Math.tan(self_);
146
154
  """
147
155
 
148
156
  tanh(): Float
149
157
  target js sync """
150
- return Math.tanh(self);
158
+ return Math.tanh(self_);
151
159
  """
152
160
 
153
161
  }
154
162
 
155
163
  hypot(values: List[Float]): Float
156
164
  target js sync """
157
- return Math.hypot(...values);
165
+ return Math.hypot(...values_);
158
166
  """
159
167
 
160
168
  e(): Float
@@ -6,82 +6,145 @@ data FetchRedirect {
6
6
  RedirectError
7
7
  RedirectManual
8
8
  }
9
+ data FetchOptions(
10
+ redirect: FetchRedirect = RedirectFollow
11
+ referrer: Option[String] = None
12
+ integrity: Option[String] = None
13
+ mode: Option[String] = None
14
+ credentials: Option[String] = None
15
+ cache: Option[String] = None
16
+ )
9
17
 
10
18
  extend self: HttpClient {
19
+
20
+ get[T](
21
+ url: String
22
+ headers: List[Pair[String, String]]
23
+ body: FetchResponse => T
24
+ ): T {
25
+ self.fetch("GET", url, headers.toMap(), None, FetchOptions(), body)
26
+ }
27
+
28
+ post[T](
29
+ url: String
30
+ headers: List[Pair[String, String]]
31
+ payload: Buffer
32
+ body: FetchResponse => T
33
+ ): T {
34
+ self.fetch("POST", url, headers.toMap(), Some(payload), FetchOptions(), body)
35
+ }
36
+
37
+ put[T](
38
+ url: String
39
+ headers: List[Pair[String, String]]
40
+ payload: Buffer
41
+ body: FetchResponse => T
42
+ ): T {
43
+ self.fetch("PUT", url, headers.toMap(), Some(payload), FetchOptions(), body)
44
+ }
45
+
46
+ delete[T](
47
+ url: String
48
+ headers: List[Pair[String, String]]
49
+ body: FetchResponse => T
50
+ ): T {
51
+ self.fetch("DELETE", url, headers.toMap(), None, FetchOptions(), body)
52
+ }
11
53
 
12
- fetch(
54
+ fetch[T](
55
+ method: String
13
56
  url: String
14
- method: String = "GET"
15
- headers: List[Pair[String, String]] = emptyList
16
- body: Option[FetchBody] = None
17
- redirect: FetchRedirect = RedirectFollow
18
- // The rest of the options are only respected by browsers - see the MDN fetch() documentation
19
- referrer: Option[String] = None
20
- integrity: Option[String] = None
21
- mode: Option[String] = None
22
- credentials: Option[String] = None
23
- cache: Option[String] = None
24
- throw: Bool = True
25
- ): FetchResponse
57
+ headers: Map[String, String] = Map.new()
58
+ payload: Option[Buffer] = None
59
+ options: FetchOptions = FetchOptions()
60
+ body: FetchResponse => T
61
+ ): T
26
62
  target js async """
63
+ const fetchResponse = {response: null, statusChecked: false};
27
64
  try {
28
- const options = {headers: {}, signal: $task.controller.signal}
29
- options.method = method_
30
- headers_.forEach(pair => {options.headers[pair.first_] = pair.second_})
31
- if(body_.value_) options.body = body_.value_
32
- if(redirect_.RedirectError) options.redirect = "error"
33
- else if(redirect_.RedirectManual) options.redirect = "manual"
34
- if(referrer_.value_) options.referrer = referrer_.value_
35
- if(integrity_.value_) options.integrity = integrity_.value_
36
- if(mode_.value_) options.mode = mode_.value_
37
- if(credentials_.value_) options.credentials = credentials_.value_
38
- if(cache_.value_) options.cache = cache_.value_
39
- let result = await fetch(url_, options)
40
- if(throw_ && !result.ok) throw new Error("Unexpected HTTP status code: " + result.status)
41
- return result
65
+ const options = {headers: {}, signal: $task.controller.signal};
66
+ options.method = method_;
67
+ headers_.forEach(pair => {options.headers[pair.first_] = pair.second_});
68
+ if(body_.value_) options.body = body_.value_;
69
+ if(redirect_.RedirectError) options.redirect = "error";
70
+ else if(redirect_.RedirectManual) options.redirect = "manual";
71
+ if(referrer_.value_) options.referrer = referrer_.value_;
72
+ if(integrity_.value_) options.integrity = integrity_.value_;
73
+ if(mode_.value_) options.mode = mode_.value_;
74
+ if(credentials_.value_) options.credentials = credentials_.value_;
75
+ if(cache_.value_) options.cache = cache_.value_;
76
+ fetchResponse.response = await self_.fetch(url_, options);
77
+ const result = await body_(fetchResponse, $task);
78
+ if(!statusChecked && !fetchResponse.response.ok) {
79
+ throw new Error("Unexpected HTTP status code: " + fetchResponse.response.status);
80
+ }
81
+ return result;
42
82
  } finally {
83
+ fetchResponse.response = null;
43
84
  if($task.controller.signal.aborted) $task.controller = new AbortController()
44
85
  }
45
86
  """
46
87
 
47
88
  }
48
89
 
49
- emptyList: List[Pair[String, String]] = [] // TODO: Why won't this type check when inlined? Probably some dangling unification variable?
50
-
51
- bodyText(body: String): FetchBody
52
- target js sync "return body_"
53
- target js async "return body_"
54
-
55
- bodyBuffer(body: Buffer): FetchBody
56
- target js sync "return body_"
57
- target js async "return body_"
58
-
59
90
  extend self: FetchResponse {
60
91
 
61
92
  ok(): Bool
62
- target js async "return self_.ok"
93
+ target js async """
94
+ self_.statusChecked = true;
95
+ internalCheck_(self_);
96
+ return self_.response.ok;
97
+ """
63
98
 
64
99
  status(): Int
65
- target js async "return self_.status"
100
+ target js async """
101
+ self_.statusChecked = true;
102
+ internalCheck_(self_);
103
+ return self_.response.status;
104
+ """
66
105
 
67
106
  statusText(): String
68
- target js async "return self_.statusText"
107
+ target js async """
108
+ self_.statusChecked = true;
109
+ internalCheck_(self_);
110
+ return self_.response.statusText;
111
+ """
69
112
 
70
113
  header(name: String): Option[String]
71
114
  target js async """
72
- const header = self_.headers.get(name_)
115
+ internalCheck_(self_);
116
+ const header = self_.response.headers.get(name_);
73
117
  return header != null
74
118
  ? ff_core_Option.Some(header)
75
- : ff_core_Option.None()
119
+ : ff_core_Option.None();
76
120
  """
77
121
 
78
122
  readText(): String
79
- target js async "return await self_.text()"
123
+ target js async """
124
+ internalCheck_(self_);
125
+ return await self_.response.text();
126
+ """
80
127
 
81
128
  readJson(): Json
82
- target js async "return await self_.json()"
129
+ target js async """
130
+ internalCheck_(self_);
131
+ return await self_.response.json();
132
+ """
83
133
 
84
134
  readBuffer(): Buffer
85
- target js async "return new DataView(await self_.arrayBuffer())"
135
+ target js async """
136
+ internalCheck_(self_);
137
+ return new DataView(await self_.response.arrayBuffer());
138
+ """
86
139
 
87
140
  }
141
+
142
+ internalCheck(fetchResponse: FetchResponse)
143
+ target js sync """
144
+ if(fetchResponse_.response === null) {
145
+ throw new Error("Response closed");
146
+ }
147
+ if(!fetchResponse_.statusChecked && !fetchResponse_.response.ok) {
148
+ throw new Error("Unchecked HTTP status code: " + fetchResponse_.response.status);
149
+ }
150
+ """
package/core/Int.ff CHANGED
@@ -26,6 +26,9 @@ extend self: Int {
26
26
  bitRight(bits: Int, signed: Bool = True): Int
27
27
  target js sync "return signed_ ? self_ >> bits_ : self_ >>> bits_;"
28
28
 
29
+ bitLeadingZeros(): Int
30
+ target js sync "return Math.clz32(self_);"
31
+
29
32
  to(inclusiveEnd: Int): List[Int] {
30
33
  let result = Array.new()
31
34
  mutable n = self
@@ -46,17 +49,14 @@ extend self: Int {
46
49
  result.drain()
47
50
  }
48
51
 
49
- min(that: Int): Int {
50
- if(self < that) {self} else {that}
51
- }
52
+ min(that: Int): Int
53
+ target js sync "return Math.min(self_, that_)"
52
54
 
53
- max(that: Int): Int {
54
- if(self > that) {self} else {that}
55
- }
55
+ max(that: Int): Int
56
+ target js sync "return Math.max(self_, that_)"
56
57
 
57
- clamp(from: Int, to: Int): Int {
58
- if(self <= from) {from} elseIf {self >= to} {to} else {self}
59
- }
58
+ clamp(from: Int, to: Int): Int
59
+ target js sync "return Math.min(Math.max(self_, from_), to_)"
60
60
 
61
61
  pad(padding: String): String {
62
62
  ("" + self).padStart(padding.size(), padding)
@@ -40,7 +40,7 @@ extend self: NodeSystem {
40
40
  """
41
41
 
42
42
  httpClient(): HttpClient
43
- target js async "return null"
43
+ target js async "return typeof globalThis !== 'undefined' ? globalThis : window"
44
44
 
45
45
  mainTask(): Task
46
46
  target js async "return self_.task_"
@@ -11,7 +11,7 @@ nodeMain(system: NodeSystem) {
11
11
  1.to(1000).each {_ =>
12
12
  system.mainTask().spawn {task =>
13
13
  let url = urlChannel.read()
14
- let html = system.httpClient().fetch(url).readText()
14
+ let html = system.httpClient().get(url, []) {_.readText()}
15
15
  htmlChannel.write(html)
16
16
  }
17
17
  }
@@ -11,12 +11,8 @@ browserMain(system: BrowserSystem): Unit {
11
11
  let handler = system.js().function1 {event =>
12
12
  let text = input.get("value").grabString()
13
13
  let serialized = Serializable.serialize(text)
14
- let result = system.httpClient().fetch(
15
- url = "http://localhost:8080/rhyme"
16
- method = "POST"
17
- body = Some(HttpClient.bodyBuffer(serialized))
18
- )
19
- output.set("innerText", result.readText())
14
+ let innerText = system.httpClient().post("http://localhost:8080/rhyme", [], serialized) {_.readText()}
15
+ output.set("innerText", innerText)
20
16
  }
21
17
 
22
18
  button.call2("addEventListener", "click", handler)
@@ -41,9 +37,8 @@ nodeMain(system: NodeSystem): Unit {
41
37
 
42
38
  let buffer = request.readBuffer()
43
39
  let deserialized = Serializable.deserialize(buffer)
44
- let result = system.httpClient().fetch("https://api.datamuse.com/words?rel_rhy=" + deserialized)
45
- let json = system.js().parseJson(result.readText())
46
- let rhyme = json.get(0).get("word").grabString()
40
+ let json = system.httpClient().get("https://api.datamuse.com/words?rel_rhy=" + deserialized, []) {_.readJson()}
41
+ let rhyme = json.index(0).field("word").grabString()
47
42
  response.setHeader("Access-Control-Allow-Origin", ["*"])
48
43
  response.writeText(rhyme)
49
44
 
@@ -1,13 +1,15 @@
1
- dependency ff:httpserver:0.0.0
2
- import HttpServer from ff:httpserver
1
+ dependency ff:webserver:0.0.0
2
+ import WebServer from ff:webserver
3
3
 
4
4
  nodeMain(system: NodeSystem): Unit {
5
5
  let host = system.arguments().grab(0)
6
6
  let port = system.arguments().grab(1).grabInt()
7
- HttpServer.listen(system, host, port) {request, response =>
8
- let parameters = request.parameters().map {"?" + _}.else {""}
9
- response.setHeader("Location", ["https://www.firefly-lang.org" + request.path() + parameters])
10
- response.writeStatus(302, Some("Found"))
7
+ WebServer.new(system, host, port).listen {request =>
8
+ let parameters = if(request.readRawQueryString().size() == 0) {""} else {
9
+ "?" + request.readRawQueryString()
10
+ }
11
+ request.writeHeader("Location", "https://www.firefly-lang.org" + request.readPath() + parameters)
12
+ request.writeStatus("302 Found")
11
13
  }
12
14
  }
13
15