Skip to content

Commit

Permalink
#1317 enabling custom trigonometric functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Jand42 committed Jan 19, 2023
1 parent 58f9fcd commit 23ddb6a
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 157 deletions.
1 change: 1 addition & 0 deletions src/compiler/WebSharper.Core/ASTHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ let (|BinaryOpName|_|) = function
| "op_Subtraction" -> Some BinaryOperator.``-``
| "op_Multiply" -> Some BinaryOperator.``*``
| "op_Division" -> Some BinaryOperator.``/``
| "op_Exponentiation" -> Some BinaryOperator.``**``
| "op_Modulus" -> Some BinaryOperator.``%``
| "op_ExclusiveOr" -> Some BinaryOperator.``^``
| "op_BitwiseAnd" -> Some BinaryOperator.``&``
Expand Down
152 changes: 31 additions & 121 deletions src/compiler/WebSharper.Core/Macros.fs
Original file line number Diff line number Diff line change
Expand Up @@ -55,52 +55,40 @@ let isIn (s: string Set) (t: Type) =
false

let traitCallOp (c: MacroCall) (args: Expression list) =
match c.Method.Generics with
| [ t ] ->
if t.IsParameter then
MacroNeedsResolvedTypeArg t
else
let ps =
match c.Method.Entity.Value.MethodName with
| "op_LeftShift"
| "op_RightShift" -> [ t; NonGenericType Definitions.Int ]
| _ -> List.replicate args.Length t
TraitCall(
None,
[ t ],
NonGeneric (
Method {
MethodName = c.Method.Entity.Value.MethodName
Parameters = ps
ReturnType = t
Generics = 0
}
),
args
)
|> MacroOk
| [t; u; v] ->
if t.IsParameter then
MacroNeedsResolvedTypeArg t
elif v.IsParameter then
MacroNeedsResolvedTypeArg v
else
let unres =
c.Method.Generics |> List.tryPick (fun t -> if t.IsParameter then Some (MacroNeedsResolvedTypeArg t) else None)
match unres with
| Some u -> u
| _ ->
let tc types pars ret =
TraitCall(
None,
[ t; u ],
types,
NonGeneric (
Method {
MethodName = c.Method.Entity.Value.MethodName
Parameters = [ t; u ]
ReturnType = v
Parameters = pars
ReturnType = ret
Generics = 0
}
),
args
)
|> MacroOk
| _ ->
failwith "F# Operator value expecting 1 or 3 type arguments"
match c.Method.Generics with
| [ t ] ->
let pars =
match c.Method.Entity.Value.MethodName with
| "op_LeftShift"
| "op_RightShift" -> [ t; NonGenericType Definitions.Int ]
| _ -> List.replicate args.Length t
tc [ t ] pars t
| [ t; u ] -> // for **
tc [ t ] [ t; u ] t
| [t; u; v] ->
tc [ t; u ] [ t; u ] v
| _ ->
failwith "F# Operator value expecting 1 or 3 type arguments"

let utilsModule =
TypeDefinition {
Expand Down Expand Up @@ -741,89 +729,11 @@ type Conversion() =
| f, t -> MacroError (sprintf "Conversion macro error: %O to %O" f t)

[<Sealed>]
type Abs() =
type Op() =
inherit Macro()
override this.TranslateCall(c) =
let m = c.Method
let x = c.Arguments.Head
let t = m.Generics.Head
if t.IsParameter then
MacroNeedsResolvedTypeArg t
else
match t with
| ConcreteType ct ->
if scalarTypes.Contains ct.Entity.Value.FullName then
MacroFallback
else
let absMeth =
Method {
MethodName = "Abs"
Parameters = [t]
ReturnType = t
Generics = 0
}
Call(None, ct, NonGeneric absMeth, [x]) |> MacroOk
| _ ->
MacroError (sprintf "Abs macro error, type not supported: %O" t)

[<Sealed>]
type Pow() =
inherit Macro()
override this.TranslateCall(c) =
let m = c.Method
let x = c.Arguments.Head
let t = m.Generics.Head
if t.IsParameter then
MacroNeedsResolvedTypeArg t
else
match t with
| ConcreteType ct ->
if scalarTypes.Contains ct.Entity.Value.FullName then
MacroFallback
else
let powMeth =
Method {
MethodName = "Pow"
Parameters = m.Generics
ReturnType = t
Generics = 0
}
Call(None, ct, NonGeneric powMeth, c.Arguments) |> MacroOk
| _ ->
MacroError (sprintf "Pow macro error, type not supported: %O" t)

[<Sealed>]
type Ceiling() =
inherit Macro()
override this.TranslateCall(c) =
let m = c.Method
let x = c.Arguments.Head
let t = m.Generics.Head
if t.IsParameter then
MacroNeedsResolvedTypeArg t
else
match t with
| ConcreteType ct ->
if scalarTypes.Contains ct.Entity.Value.FullName then
MacroFallback
else
let ceilMeth =
Method {
MethodName = "Ceiling"
Parameters = [t]
ReturnType = t
Generics = 0
}
Call(None, ct, NonGeneric ceilMeth, [x]) |> MacroOk
| _ ->
MacroError (sprintf "Ceiling macro error, type not supported: %O" t)

[<Sealed>]
type Floor() =
inherit Macro()
override this.TranslateCall(c) =
let m = c.Method
let x = c.Arguments.Head
let me = m.Entity.Value
let t = m.Generics.Head
if t.IsParameter then
MacroNeedsResolvedTypeArg t
Expand All @@ -833,16 +743,16 @@ type Floor() =
if scalarTypes.Contains ct.Entity.Value.FullName then
MacroFallback
else
let floorMeth =
let meth =
Method {
MethodName = "Floor"
Parameters = [t]
ReturnType = t
MethodName = me.MethodName
Parameters = me.Parameters |> List.map (fun p -> p.SubstituteGenerics(Array.ofList m.Generics))
ReturnType = me.ReturnType.SubstituteGenerics(Array.ofList m.Generics)
Generics = 0
}
Call(None, ct, NonGeneric floorMeth, [x]) |> MacroOk
TraitCall(None, [t], NonGeneric meth, c.Arguments) |> MacroOk
| _ ->
MacroError (sprintf "Floor macro error, type not supported: %O" t)
MacroError (sprintf "Op macro error on method %s, type not supported: %O" me.MethodName t)

[<Sealed>]
type Sign() =
Expand Down
19 changes: 2 additions & 17 deletions src/compiler/WebSharper.Core/Macros.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,8 @@ type Conversion =
inherit Macro

[<Sealed>]
type Abs =
new : unit -> Abs
inherit Macro

[<Sealed>]
type Pow =
new : unit -> Pow
inherit Macro

[<Sealed>]
type Ceiling =
new : unit -> Ceiling
inherit Macro

[<Sealed>]
type Floor =
new : unit -> Floor
type Op =
new : unit -> Op
inherit Macro

[<Sealed>]
Expand Down
3 changes: 3 additions & 0 deletions src/stdlib/WebSharper.Main.Proxies/BigInt.fs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ type private BigIntegerProxy =
[<Inline "$n1 <= $n2">]
static member op_LessThanOrEqual(n1 : bigint, n2 : bigint) = X<bool>

[<Inline "$n1 ** BigInt($n2)">]
static member op_Exponentiation(n1 : bigint, n2 : int) = X<bigint>

[<Inline "$n1 ** BigInt($n2)">]
static member Pow(n1 : bigint, n2 : int) = X<bigint>

Expand Down
33 changes: 15 additions & 18 deletions src/stdlib/WebSharper.Main.Proxies/Operators.fs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ let ( &&& ) (a: 'T1) (b: 'T1) = X<'T1>
[<Macro(typeof<M.Arith>)>]
let ( * ) (a: 'T1) (b: 'T2) = X<'T3>

[<Macro(typeof<M.Pow>)>]
[<Inline "Math.pow($a, $b)">]
[<Macro(typeof<M.Arith>)>]
let ( ** ) (a: 'T1) (b: 'T2) = X<'T1>

[<Inline "Math.pow($a, $p)">]
Expand Down Expand Up @@ -152,26 +151,30 @@ let ( ~- ) (x: 'T) = X<'T>
[<Macro(typeof<M.Arith>)>]
let ( ~~~ ) (x: 'T) = X<'T>

[<Macro(typeof<M.Abs>)>]
[<Macro(typeof<M.Op>)>]
[<Inline "Math.abs($x)">]
let Abs (x: 'T) = X<'T>

[<Macro(typeof<M.Op>)>]
[<Inline "Math.acos($x)">]
let Acos (x: 'T) = X<'T>

[<Macro(typeof<M.Op>)>]
[<Inline "Math.asin($x)">]
let Asin (x: 'T) = X<'T>

[<Macro(typeof<M.Op>)>]
[<Inline "Math.atan($x)">]
let Atan (x: 'T) = X<'T>

[<Macro(typeof<M.Op>)>]
[<Inline "Math.atan2($x, $y)">]
let Atan2 (x: 'T1) (y: 'T1) = X<'T2>

[<Inline "$x">]
let Box (x: 'T) = X<obj>

[<Macro(typeof<M.Ceiling>)>]
[<Macro(typeof<M.Op>)>]
[<Inline "Math.ceil($x)">]
let Ceiling (x: 'T) = X<'T>

Expand All @@ -187,9 +190,11 @@ let ToSByte (x: 'T) = X<sbyte>
[<Inline>]
let Compare<'T> (a: 'T) (b: 'T) = Unchecked.compare a b

[<Macro(typeof<M.Op>)>]
[<Inline "Math.cos($x)">]
let Cos (x: 'T) = X<'T>

[<Macro(typeof<M.Op>)>]
[<Inline "(Math.exp($x)+Math.exp(-$x))/2">]
let Cosh<'T> (x: 'T) = X<'T>

Expand Down Expand Up @@ -217,6 +222,7 @@ let ToDecimal (x: 'T) = X<decimal>
[<Macro(typeof<M.Conversion>)>]
let ToDouble (x: 'T) = X<double>

[<Macro(typeof<M.Op>)>]
[<Inline "Math.exp($x)">]
let inline Exp (x: 'T) = X<'T>

Expand All @@ -225,7 +231,7 @@ let FailWith (msg: string) : 'T = raise (exn msg)
[<Macro(typeof<M.Conversion>)>]
let ToFloat (x: 'T) = X<float>

[<Macro(typeof<M.Floor>)>]
[<Macro(typeof<M.Op>)>]
[<Inline "Math.floor($x)">]
let Floor (x: 'T) = X<'T>

Expand Down Expand Up @@ -314,19 +320,6 @@ let NaN = nan
[<Inline "!$x">]
let Not (x: bool) = X<bool>

let Pown<'T> (a: 'T) (n: int) =
let a = box a :?> double
let rec p n =
match n with
| 1 ->
a
| n when n % 2 = 0 ->
let b = p (n / 2)
b * b
| n ->
a * (p (n - 1))
p n

[<Inline "throw $e">]
let Raise (e: exn) = X<'T>

Expand All @@ -346,9 +339,11 @@ let Sign<'T> (x: 'T) =
| n when n < 0 -> -1
| _ -> 1

[<Macro(typeof<M.Op>)>]
[<Inline "Math.sin($x)">]
let Sin (x: 'T) = X<'T>

[<Macro(typeof<M.Op>)>]
[<Inline "(Math.exp($x)-Math.exp(-$x))/2">]
let Sinh (x: 'T) = x

Expand All @@ -361,9 +356,11 @@ let Sqrt (x: 'T1) = X<'T2>
[<Macro(typeof<M.String>)>]
let ToString (x: 'T) = X<string>

[<Macro(typeof<M.Op>)>]
[<Inline "Math.tan($x)">]
let inline Tan (x: 'T) = X<'T>

[<Macro(typeof<M.Op>)>]
[<Inline "(Math.exp(2*$x)-1)/(Math.exp(2*$x)+1)">]
let Tanh (x: 'T) = X<'T>

Expand Down
6 changes: 6 additions & 0 deletions src/stdlib/WebSharper.MathJS.Extensions/Decimal.fs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ type internal DecimalProxy =
[<Inline>]
static member Multiply(n1 : decimal, n2 : decimal): decimal = DecimalProxy.mul WSDecimalMath.Multiply n1 n2

[<Inline>]
static member Pow(n1 : decimal, n2 : decimal): decimal = DecimalProxy.bin WSDecimalMath.Pow n1 n2

[<Inline>]
static member Parse(s : string) = WSDecimalMath.Bignumber(MathNumber(s)) |> As<decimal>

Expand Down Expand Up @@ -221,6 +224,9 @@ type internal DecimalProxy =
[<Inline>]
static member op_Multiply(n1 : decimal, n2 : decimal): decimal = DecimalProxy.Multiply (n1, n2)

[<Inline>]
static member op_Exponentiation(n1 : decimal, n2 : decimal): decimal = DecimalProxy.Pow (n1, n2)

[<Inline>]
static member op_Subtraction(n1 : decimal, n2 : decimal) = DecimalProxy.Subtract (n1,n2)

Expand Down
Loading

0 comments on commit 23ddb6a

Please sign in to comment.