pulse-framework 0.1.51__py3-none-any.whl → 0.1.53__py3-none-any.whl
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.
- pulse/__init__.py +542 -562
- pulse/_examples.py +29 -0
- pulse/app.py +0 -14
- pulse/cli/cmd.py +96 -80
- pulse/cli/dependencies.py +10 -41
- pulse/cli/folder_lock.py +3 -3
- pulse/cli/helpers.py +40 -67
- pulse/cli/logging.py +102 -0
- pulse/cli/packages.py +16 -0
- pulse/cli/processes.py +40 -23
- pulse/codegen/codegen.py +70 -35
- pulse/codegen/js.py +2 -4
- pulse/codegen/templates/route.py +94 -146
- pulse/component.py +115 -0
- pulse/components/for_.py +1 -1
- pulse/components/if_.py +1 -1
- pulse/components/react_router.py +16 -22
- pulse/{html → dom}/events.py +1 -1
- pulse/{html → dom}/props.py +6 -6
- pulse/{html → dom}/tags.py +11 -11
- pulse/dom/tags.pyi +480 -0
- pulse/form.py +7 -6
- pulse/hooks/init.py +1 -13
- pulse/js/__init__.py +37 -41
- pulse/js/__init__.pyi +22 -2
- pulse/js/_types.py +5 -3
- pulse/js/array.py +121 -38
- pulse/js/console.py +9 -9
- pulse/js/date.py +22 -19
- pulse/js/document.py +8 -4
- pulse/js/error.py +12 -14
- pulse/js/json.py +4 -3
- pulse/js/map.py +17 -7
- pulse/js/math.py +2 -2
- pulse/js/navigator.py +4 -4
- pulse/js/number.py +8 -8
- pulse/js/object.py +9 -13
- pulse/js/promise.py +25 -9
- pulse/js/regexp.py +6 -6
- pulse/js/set.py +20 -8
- pulse/js/string.py +7 -7
- pulse/js/weakmap.py +6 -6
- pulse/js/weakset.py +6 -6
- pulse/js/window.py +17 -14
- pulse/messages.py +1 -4
- pulse/react_component.py +3 -1001
- pulse/render_session.py +74 -66
- pulse/renderer.py +311 -238
- pulse/routing.py +1 -10
- pulse/transpiler/__init__.py +84 -114
- pulse/transpiler/builtins.py +661 -343
- pulse/transpiler/errors.py +78 -2
- pulse/transpiler/function.py +463 -133
- pulse/transpiler/id.py +18 -0
- pulse/transpiler/imports.py +230 -325
- pulse/transpiler/js_module.py +218 -209
- pulse/transpiler/modules/__init__.py +16 -13
- pulse/transpiler/modules/asyncio.py +45 -26
- pulse/transpiler/modules/json.py +12 -8
- pulse/transpiler/modules/math.py +161 -216
- pulse/transpiler/modules/pulse/__init__.py +5 -0
- pulse/transpiler/modules/pulse/tags.py +231 -0
- pulse/transpiler/modules/typing.py +33 -28
- pulse/transpiler/nodes.py +1607 -923
- pulse/transpiler/py_module.py +118 -95
- pulse/transpiler/react_component.py +51 -0
- pulse/transpiler/transpiler.py +593 -437
- pulse/transpiler/vdom.py +255 -0
- {pulse_framework-0.1.51.dist-info → pulse_framework-0.1.53.dist-info}/METADATA +1 -1
- pulse_framework-0.1.53.dist-info/RECORD +120 -0
- pulse/html/tags.pyi +0 -470
- pulse/transpiler/constants.py +0 -110
- pulse/transpiler/context.py +0 -26
- pulse/transpiler/ids.py +0 -16
- pulse/transpiler/modules/re.py +0 -466
- pulse/transpiler/modules/tags.py +0 -268
- pulse/transpiler/utils.py +0 -4
- pulse/vdom.py +0 -599
- pulse_framework-0.1.51.dist-info/RECORD +0 -119
- /pulse/{html → dom}/__init__.py +0 -0
- /pulse/{html → dom}/elements.py +0 -0
- /pulse/{html → dom}/svg.py +0 -0
- {pulse_framework-0.1.51.dist-info → pulse_framework-0.1.53.dist-info}/WHEEL +0 -0
- {pulse_framework-0.1.51.dist-info → pulse_framework-0.1.53.dist-info}/entry_points.txt +0 -0
pulse/transpiler/modules/math.py
CHANGED
|
@@ -1,320 +1,265 @@
|
|
|
1
1
|
"""Python math module transpilation to JavaScript Math.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
For direct JavaScript Math bindings, use `pulse.js.math` instead.
|
|
3
|
+
Provides transpilation from Python's `math` module to JavaScript's `Math` object.
|
|
5
4
|
"""
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any, final
|
|
8
9
|
|
|
9
|
-
from pulse.transpiler.constants import jsify
|
|
10
10
|
from pulse.transpiler.nodes import (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
Binary,
|
|
12
|
+
Call,
|
|
13
|
+
Expr,
|
|
14
|
+
Identifier,
|
|
15
|
+
Literal,
|
|
16
|
+
Member,
|
|
17
|
+
Unary,
|
|
18
18
|
)
|
|
19
19
|
from pulse.transpiler.py_module import PyModule
|
|
20
|
+
from pulse.transpiler.transpiler import Transpiler
|
|
20
21
|
|
|
22
|
+
# Helpers for building Math.* calls
|
|
23
|
+
_Math = Identifier("Math")
|
|
24
|
+
_Number = Identifier("Number")
|
|
21
25
|
|
|
22
|
-
# Helper for generating Math method calls during transpilation
|
|
23
|
-
def MathCall(name: str, *args: int | float | JSExpr) -> JSExpr:
|
|
24
|
-
return JSMemberCall(JSIdentifier("Math"), name, [jsify(a) for a in args])
|
|
25
26
|
|
|
27
|
+
def _math_prop(name: str) -> Expr:
|
|
28
|
+
return Member(_Math, name)
|
|
26
29
|
|
|
27
|
-
def MathProp(name: str) -> JSExpr:
|
|
28
|
-
return JSMember(JSIdentifier("Math"), name)
|
|
29
30
|
|
|
31
|
+
def _math_call(name: str, args: list[Expr]) -> Expr:
|
|
32
|
+
return Call(Member(_Math, name), args)
|
|
30
33
|
|
|
31
|
-
class PyMath(PyModule):
|
|
32
|
-
"""Provides transpilation for Python math functions to JavaScript."""
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
e = MathProp("E")
|
|
37
|
-
tau = JSBinary(JSNumber(2), "*", MathProp("PI")) # 2 * PI
|
|
38
|
-
inf = JSIdentifier("Infinity")
|
|
39
|
-
nan = JSIdentifier("NaN")
|
|
35
|
+
def _number_call(name: str, args: list[Expr]) -> Expr:
|
|
36
|
+
return Call(Member(_Number, name), args)
|
|
40
37
|
|
|
41
|
-
@staticmethod
|
|
42
|
-
def acos(x: int | float | JSExpr) -> JSExpr:
|
|
43
|
-
return MathCall("acos", x)
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
@final
|
|
40
|
+
class PyMath(PyModule):
|
|
41
|
+
"""Provides transpilation for Python math functions to JavaScript."""
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
# Constants
|
|
44
|
+
pi = _math_prop("PI")
|
|
45
|
+
e = _math_prop("E")
|
|
46
|
+
tau = Binary(Literal(2), "*", _math_prop("PI"))
|
|
47
|
+
inf = Identifier("Infinity")
|
|
48
|
+
nan = Identifier("NaN")
|
|
52
49
|
|
|
50
|
+
# Basic functions
|
|
53
51
|
@staticmethod
|
|
54
|
-
def
|
|
55
|
-
return
|
|
52
|
+
def acos(x: Any, *, ctx: Transpiler) -> Expr:
|
|
53
|
+
return _math_call("acos", [ctx.emit_expr(x)])
|
|
56
54
|
|
|
57
55
|
@staticmethod
|
|
58
|
-
def
|
|
59
|
-
return
|
|
56
|
+
def acosh(x: Any, *, ctx: Transpiler) -> Expr:
|
|
57
|
+
return _math_call("acosh", [ctx.emit_expr(x)])
|
|
60
58
|
|
|
61
59
|
@staticmethod
|
|
62
|
-
def
|
|
63
|
-
return
|
|
60
|
+
def asin(x: Any, *, ctx: Transpiler) -> Expr:
|
|
61
|
+
return _math_call("asin", [ctx.emit_expr(x)])
|
|
64
62
|
|
|
65
63
|
@staticmethod
|
|
66
|
-
def
|
|
67
|
-
return
|
|
64
|
+
def asinh(x: Any, *, ctx: Transpiler) -> Expr:
|
|
65
|
+
return _math_call("asinh", [ctx.emit_expr(x)])
|
|
68
66
|
|
|
69
67
|
@staticmethod
|
|
70
|
-
def
|
|
71
|
-
return
|
|
68
|
+
def atan(x: Any, *, ctx: Transpiler) -> Expr:
|
|
69
|
+
return _math_call("atan", [ctx.emit_expr(x)])
|
|
72
70
|
|
|
73
71
|
@staticmethod
|
|
74
|
-
def
|
|
75
|
-
return
|
|
72
|
+
def atan2(y: Any, x: Any, *, ctx: Transpiler) -> Expr:
|
|
73
|
+
return _math_call("atan2", [ctx.emit_expr(y), ctx.emit_expr(x)])
|
|
76
74
|
|
|
77
75
|
@staticmethod
|
|
78
|
-
def
|
|
79
|
-
|
|
80
|
-
return JSBinary(MathCall("sign", y), "*", MathCall("abs", x))
|
|
76
|
+
def atanh(x: Any, *, ctx: Transpiler) -> Expr:
|
|
77
|
+
return _math_call("atanh", [ctx.emit_expr(x)])
|
|
81
78
|
|
|
82
79
|
@staticmethod
|
|
83
|
-
def
|
|
84
|
-
return
|
|
80
|
+
def cbrt(x: Any, *, ctx: Transpiler) -> Expr:
|
|
81
|
+
return _math_call("cbrt", [ctx.emit_expr(x)])
|
|
85
82
|
|
|
86
83
|
@staticmethod
|
|
87
|
-
def
|
|
88
|
-
return
|
|
84
|
+
def ceil(x: Any, *, ctx: Transpiler) -> Expr:
|
|
85
|
+
return _math_call("ceil", [ctx.emit_expr(x)])
|
|
89
86
|
|
|
90
87
|
@staticmethod
|
|
91
|
-
def
|
|
92
|
-
#
|
|
93
|
-
return
|
|
88
|
+
def copysign(x: Any, y: Any, *, ctx: Transpiler) -> Expr:
|
|
89
|
+
# Math.sign(y) * Math.abs(x)
|
|
90
|
+
return Binary(
|
|
91
|
+
_math_call("sign", [ctx.emit_expr(y)]),
|
|
92
|
+
"*",
|
|
93
|
+
_math_call("abs", [ctx.emit_expr(x)]),
|
|
94
|
+
)
|
|
94
95
|
|
|
95
96
|
@staticmethod
|
|
96
|
-
def
|
|
97
|
-
|
|
98
|
-
q: int | float | JSExpr | list[int | float | JSExpr],
|
|
99
|
-
) -> JSExpr:
|
|
100
|
-
raise NotImplementedError("dist requires array/iterable handling")
|
|
97
|
+
def cos(x: Any, *, ctx: Transpiler) -> Expr:
|
|
98
|
+
return _math_call("cos", [ctx.emit_expr(x)])
|
|
101
99
|
|
|
102
100
|
@staticmethod
|
|
103
|
-
def
|
|
104
|
-
|
|
101
|
+
def cosh(x: Any, *, ctx: Transpiler) -> Expr:
|
|
102
|
+
return _math_call("cosh", [ctx.emit_expr(x)])
|
|
105
103
|
|
|
106
104
|
@staticmethod
|
|
107
|
-
def
|
|
108
|
-
|
|
105
|
+
def degrees(x: Any, *, ctx: Transpiler) -> Expr:
|
|
106
|
+
# x * (180 / PI)
|
|
107
|
+
return Binary(
|
|
108
|
+
ctx.emit_expr(x),
|
|
109
|
+
"*",
|
|
110
|
+
Binary(Literal(180), "/", _math_prop("PI")),
|
|
111
|
+
)
|
|
109
112
|
|
|
110
113
|
@staticmethod
|
|
111
|
-
def exp(x:
|
|
112
|
-
return
|
|
114
|
+
def exp(x: Any, *, ctx: Transpiler) -> Expr:
|
|
115
|
+
return _math_call("exp", [ctx.emit_expr(x)])
|
|
113
116
|
|
|
114
117
|
@staticmethod
|
|
115
|
-
def exp2(x:
|
|
118
|
+
def exp2(x: Any, *, ctx: Transpiler) -> Expr:
|
|
116
119
|
# 2 ** x
|
|
117
|
-
return
|
|
120
|
+
return Binary(Literal(2), "**", ctx.emit_expr(x))
|
|
118
121
|
|
|
119
122
|
@staticmethod
|
|
120
|
-
def expm1(x:
|
|
121
|
-
return
|
|
123
|
+
def expm1(x: Any, *, ctx: Transpiler) -> Expr:
|
|
124
|
+
return _math_call("expm1", [ctx.emit_expr(x)])
|
|
122
125
|
|
|
123
126
|
@staticmethod
|
|
124
|
-
def fabs(x:
|
|
125
|
-
return
|
|
127
|
+
def fabs(x: Any, *, ctx: Transpiler) -> Expr:
|
|
128
|
+
return _math_call("abs", [ctx.emit_expr(x)])
|
|
126
129
|
|
|
127
130
|
@staticmethod
|
|
128
|
-
def
|
|
129
|
-
|
|
131
|
+
def floor(x: Any, *, ctx: Transpiler) -> Expr:
|
|
132
|
+
return _math_call("floor", [ctx.emit_expr(x)])
|
|
130
133
|
|
|
131
134
|
@staticmethod
|
|
132
|
-
def
|
|
133
|
-
return
|
|
135
|
+
def fmod(x: Any, y: Any, *, ctx: Transpiler) -> Expr:
|
|
136
|
+
return Binary(ctx.emit_expr(x), "%", ctx.emit_expr(y))
|
|
134
137
|
|
|
135
138
|
@staticmethod
|
|
136
|
-
def
|
|
137
|
-
|
|
138
|
-
return JSBinary(jsify(x), "%", jsify(y))
|
|
139
|
-
|
|
140
|
-
@staticmethod
|
|
141
|
-
def frexp(x: int | float | JSExpr) -> JSExpr:
|
|
142
|
-
raise NotImplementedError("frexp returns tuple, requires special handling")
|
|
143
|
-
|
|
144
|
-
@staticmethod
|
|
145
|
-
def fsum(seq: int | float | JSExpr | list[int | float | JSExpr]) -> JSExpr:
|
|
146
|
-
raise NotImplementedError("fsum requires iterable handling")
|
|
147
|
-
|
|
148
|
-
@staticmethod
|
|
149
|
-
def gamma(x: int | float | JSExpr) -> JSExpr:
|
|
150
|
-
raise NotImplementedError("gamma requires special function implementation")
|
|
151
|
-
|
|
152
|
-
@staticmethod
|
|
153
|
-
def gcd(*integers: int | float | JSExpr) -> JSExpr:
|
|
154
|
-
raise NotImplementedError("gcd requires iterative implementation")
|
|
155
|
-
|
|
156
|
-
@staticmethod
|
|
157
|
-
def hypot(*coordinates: int | float | JSExpr) -> JSExpr:
|
|
158
|
-
return MathCall("hypot", *coordinates)
|
|
139
|
+
def hypot(*coords: Any, ctx: Transpiler) -> Expr:
|
|
140
|
+
return _math_call("hypot", [ctx.emit_expr(c) for c in coords])
|
|
159
141
|
|
|
160
142
|
@staticmethod
|
|
161
143
|
def isclose(
|
|
162
|
-
a:
|
|
163
|
-
|
|
164
|
-
*,
|
|
165
|
-
rel_tol: int | float | JSExpr = 1e-09,
|
|
166
|
-
abs_tol: int | float | JSExpr = 0.0,
|
|
167
|
-
) -> JSExpr:
|
|
144
|
+
a: Any, b: Any, *, rel_tol: Any = 1e-9, abs_tol: Any = 0.0, ctx: Transpiler
|
|
145
|
+
) -> Expr:
|
|
168
146
|
# abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
JSIdentifier("Math"), "max", [rel_bound, jsify(abs_tol)]
|
|
147
|
+
a_expr = ctx.emit_expr(a)
|
|
148
|
+
b_expr = ctx.emit_expr(b)
|
|
149
|
+
rel_tol_expr = ctx.emit_expr(rel_tol)
|
|
150
|
+
abs_tol_expr = ctx.emit_expr(abs_tol)
|
|
151
|
+
|
|
152
|
+
abs_diff = _math_call("abs", [Binary(a_expr, "-", b_expr)])
|
|
153
|
+
max_abs = _math_call(
|
|
154
|
+
"max", [_math_call("abs", [a_expr]), _math_call("abs", [b_expr])]
|
|
178
155
|
)
|
|
179
|
-
|
|
156
|
+
rel_bound = Binary(rel_tol_expr, "*", max_abs)
|
|
157
|
+
max_bound = _math_call("max", [rel_bound, abs_tol_expr])
|
|
158
|
+
return Binary(abs_diff, "<=", max_bound)
|
|
180
159
|
|
|
181
160
|
@staticmethod
|
|
182
|
-
def isfinite(x:
|
|
183
|
-
return
|
|
161
|
+
def isfinite(x: Any, *, ctx: Transpiler) -> Expr:
|
|
162
|
+
return _number_call("isFinite", [ctx.emit_expr(x)])
|
|
184
163
|
|
|
185
164
|
@staticmethod
|
|
186
|
-
def isinf(x:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
165
|
+
def isinf(x: Any, *, ctx: Transpiler) -> Expr:
|
|
166
|
+
# !Number.isFinite(x) && !Number.isNaN(x)
|
|
167
|
+
x_expr = ctx.emit_expr(x)
|
|
168
|
+
return Binary(
|
|
169
|
+
Unary("!", _number_call("isFinite", [x_expr])),
|
|
170
|
+
"&&",
|
|
171
|
+
Unary("!", _number_call("isNaN", [x_expr])),
|
|
172
|
+
)
|
|
194
173
|
|
|
195
174
|
@staticmethod
|
|
196
|
-
def
|
|
197
|
-
return
|
|
175
|
+
def isnan(x: Any, *, ctx: Transpiler) -> Expr:
|
|
176
|
+
return _number_call("isNaN", [ctx.emit_expr(x)])
|
|
198
177
|
|
|
199
178
|
@staticmethod
|
|
200
|
-
def
|
|
201
|
-
|
|
179
|
+
def isqrt(n: Any, *, ctx: Transpiler) -> Expr:
|
|
180
|
+
return _math_call("floor", [_math_call("sqrt", [ctx.emit_expr(n)])])
|
|
202
181
|
|
|
203
182
|
@staticmethod
|
|
204
|
-
def ldexp(x:
|
|
183
|
+
def ldexp(x: Any, i: Any, *, ctx: Transpiler) -> Expr:
|
|
205
184
|
# x * (2 ** i)
|
|
206
|
-
return
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
185
|
+
return Binary(
|
|
186
|
+
ctx.emit_expr(x),
|
|
187
|
+
"*",
|
|
188
|
+
Binary(Literal(2), "**", ctx.emit_expr(i)),
|
|
189
|
+
)
|
|
211
190
|
|
|
212
191
|
@staticmethod
|
|
213
|
-
def log(
|
|
214
|
-
value: int | float | JSExpr,
|
|
215
|
-
base: int | float | JSExpr | None = None,
|
|
216
|
-
) -> JSExpr:
|
|
192
|
+
def log(value: Any, base: Any = None, *, ctx: Transpiler) -> Expr:
|
|
217
193
|
if base is None:
|
|
218
|
-
return
|
|
219
|
-
return
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
@staticmethod
|
|
226
|
-
def log1p(x: int | float | JSExpr) -> JSExpr:
|
|
227
|
-
return MathCall("log1p", x)
|
|
228
|
-
|
|
229
|
-
@staticmethod
|
|
230
|
-
def log2(x: int | float | JSExpr) -> JSExpr:
|
|
231
|
-
return MathCall("log2", x)
|
|
232
|
-
|
|
233
|
-
@staticmethod
|
|
234
|
-
def modf(x: int | float | JSExpr) -> JSExpr:
|
|
235
|
-
raise NotImplementedError("modf returns tuple, requires special handling")
|
|
236
|
-
|
|
237
|
-
@staticmethod
|
|
238
|
-
def nextafter(
|
|
239
|
-
x: int | float | JSExpr,
|
|
240
|
-
y: int | float | JSExpr,
|
|
241
|
-
*,
|
|
242
|
-
steps: int | float | JSExpr | None = None,
|
|
243
|
-
) -> JSExpr:
|
|
244
|
-
raise NotImplementedError("nextafter requires special implementation")
|
|
245
|
-
|
|
246
|
-
@staticmethod
|
|
247
|
-
def perm(n: int | float | JSExpr, k: int | float | JSExpr | None = None) -> JSExpr:
|
|
248
|
-
raise NotImplementedError("perm requires factorial implementation")
|
|
249
|
-
|
|
250
|
-
@staticmethod
|
|
251
|
-
def pow(x: int | float | JSExpr, y: int | float | JSExpr) -> JSExpr:
|
|
252
|
-
return MathCall("pow", x, y)
|
|
194
|
+
return _math_call("log", [ctx.emit_expr(value)])
|
|
195
|
+
return Binary(
|
|
196
|
+
_math_call("log", [ctx.emit_expr(value)]),
|
|
197
|
+
"/",
|
|
198
|
+
_math_call("log", [ctx.emit_expr(base)]),
|
|
199
|
+
)
|
|
253
200
|
|
|
254
201
|
@staticmethod
|
|
255
|
-
def
|
|
256
|
-
|
|
257
|
-
*,
|
|
258
|
-
start: int | float | JSExpr = 1,
|
|
259
|
-
) -> JSExpr:
|
|
260
|
-
raise NotImplementedError("prod requires iterable handling")
|
|
202
|
+
def log10(x: Any, *, ctx: Transpiler) -> Expr:
|
|
203
|
+
return _math_call("log10", [ctx.emit_expr(x)])
|
|
261
204
|
|
|
262
205
|
@staticmethod
|
|
263
|
-
def
|
|
264
|
-
|
|
265
|
-
return JSBinary(jsify(x), "*", JSBinary(MathProp("PI"), "/", JSNumber(180)))
|
|
206
|
+
def log1p(x: Any, *, ctx: Transpiler) -> Expr:
|
|
207
|
+
return _math_call("log1p", [ctx.emit_expr(x)])
|
|
266
208
|
|
|
267
209
|
@staticmethod
|
|
268
|
-
def
|
|
269
|
-
|
|
270
|
-
n = MathCall("round", JSBinary(jsify(x), "/", jsify(y)))
|
|
271
|
-
return JSBinary(jsify(x), "-", JSBinary(n, "*", jsify(y)))
|
|
210
|
+
def log2(x: Any, *, ctx: Transpiler) -> Expr:
|
|
211
|
+
return _math_call("log2", [ctx.emit_expr(x)])
|
|
272
212
|
|
|
273
213
|
@staticmethod
|
|
274
|
-
def
|
|
275
|
-
return
|
|
214
|
+
def pow(x: Any, y: Any, *, ctx: Transpiler) -> Expr:
|
|
215
|
+
return _math_call("pow", [ctx.emit_expr(x), ctx.emit_expr(y)])
|
|
276
216
|
|
|
277
217
|
@staticmethod
|
|
278
|
-
def
|
|
279
|
-
|
|
218
|
+
def radians(x: Any, *, ctx: Transpiler) -> Expr:
|
|
219
|
+
# x * (PI / 180)
|
|
220
|
+
return Binary(
|
|
221
|
+
ctx.emit_expr(x),
|
|
222
|
+
"*",
|
|
223
|
+
Binary(_math_prop("PI"), "/", Literal(180)),
|
|
224
|
+
)
|
|
280
225
|
|
|
281
226
|
@staticmethod
|
|
282
|
-
def
|
|
283
|
-
|
|
227
|
+
def remainder(x: Any, y: Any, *, ctx: Transpiler) -> Expr:
|
|
228
|
+
# x - round(x/y) * y
|
|
229
|
+
x_expr = ctx.emit_expr(x)
|
|
230
|
+
y_expr = ctx.emit_expr(y)
|
|
231
|
+
n = _math_call("round", [Binary(x_expr, "/", y_expr)])
|
|
232
|
+
return Binary(x_expr, "-", Binary(n, "*", y_expr))
|
|
284
233
|
|
|
285
234
|
@staticmethod
|
|
286
|
-
def
|
|
287
|
-
|
|
288
|
-
q: int | float | JSExpr | list[int | float | JSExpr],
|
|
289
|
-
) -> JSExpr:
|
|
290
|
-
raise NotImplementedError("sumprod requires iterable handling")
|
|
235
|
+
def sin(x: Any, *, ctx: Transpiler) -> Expr:
|
|
236
|
+
return _math_call("sin", [ctx.emit_expr(x)])
|
|
291
237
|
|
|
292
238
|
@staticmethod
|
|
293
|
-
def
|
|
294
|
-
return
|
|
239
|
+
def sinh(x: Any, *, ctx: Transpiler) -> Expr:
|
|
240
|
+
return _math_call("sinh", [ctx.emit_expr(x)])
|
|
295
241
|
|
|
296
242
|
@staticmethod
|
|
297
|
-
def
|
|
298
|
-
return
|
|
243
|
+
def sqrt(x: Any, *, ctx: Transpiler) -> Expr:
|
|
244
|
+
return _math_call("sqrt", [ctx.emit_expr(x)])
|
|
299
245
|
|
|
300
246
|
@staticmethod
|
|
301
|
-
def
|
|
302
|
-
return
|
|
247
|
+
def tan(x: Any, *, ctx: Transpiler) -> Expr:
|
|
248
|
+
return _math_call("tan", [ctx.emit_expr(x)])
|
|
303
249
|
|
|
304
250
|
@staticmethod
|
|
305
|
-
def
|
|
306
|
-
|
|
251
|
+
def tanh(x: Any, *, ctx: Transpiler) -> Expr:
|
|
252
|
+
return _math_call("tanh", [ctx.emit_expr(x)])
|
|
307
253
|
|
|
308
254
|
@staticmethod
|
|
309
|
-
def
|
|
310
|
-
|
|
311
|
-
y: int | float | JSExpr,
|
|
312
|
-
z: int | float | JSExpr,
|
|
313
|
-
) -> JSExpr:
|
|
314
|
-
# Fused multiply-add: (x * y) + z (with single rounding)
|
|
315
|
-
# JavaScript doesn't have native fma, so we just do the operation
|
|
316
|
-
return JSBinary(JSBinary(jsify(x), "*", jsify(y)), "+", jsify(z))
|
|
255
|
+
def trunc(x: Any, *, ctx: Transpiler) -> Expr:
|
|
256
|
+
return _math_call("trunc", [ctx.emit_expr(x)])
|
|
317
257
|
|
|
318
258
|
@staticmethod
|
|
319
|
-
def
|
|
320
|
-
|
|
259
|
+
def fma(x: Any, y: Any, z: Any, *, ctx: Transpiler) -> Expr:
|
|
260
|
+
# (x * y) + z
|
|
261
|
+
return Binary(
|
|
262
|
+
Binary(ctx.emit_expr(x), "*", ctx.emit_expr(y)),
|
|
263
|
+
"+",
|
|
264
|
+
ctx.emit_expr(z),
|
|
265
|
+
)
|