Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] add replacements for System.Numerics Vector3 / Quaternion #1638

Open
wants to merge 25 commits into
base: nagareyama
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e1a48c6
add replacements for System.Numerics Vector3 / Quaternion
0x53A Nov 14, 2018
e074968
Merge branch 'master' into replacement-system-numerics
0x53A Nov 14, 2018
33979c4
v3 / q use public fields, not properties
0x53A Nov 14, 2018
04f4fc6
add transforms for ILFieldGet / ILFieldSet
0x53A Nov 14, 2018
38fc343
ILFieldGet / Set
0x53A Nov 14, 2018
e5cf894
ILFieldGet
0x53A Nov 15, 2018
64b2b57
add (hopefully) correct transforms for ILFieldGet / ILFieldSet
0x53A Nov 16, 2018
7b472ed
oops
0x53A Nov 16, 2018
d402839
add tests for field read / write
0x53A Nov 16, 2018
d8387b8
merge from master
0x53A Dec 21, 2018
6b0db68
minor comment
0x53A Dec 21, 2018
31fbbbc
adapt to rename fable-core => fable-library
0x53A Dec 21, 2018
8271537
implement some more members of Vector3
0x53A Dec 21, 2018
7dc6c31
wip comments
0x53A Dec 21, 2018
c3733e5
merge from upstream/master
0x53A Apr 30, 2019
c6a5b3a
fable-library was moved
0x53A Apr 30, 2019
1e3a33d
Vector3.ToString
0x53A May 7, 2019
ee4e1d2
Merge remote-tracking branch 'upstream/master' into replacement-syste…
0x53A Aug 5, 2019
2cef223
Fable.Tests: add PackageReference to System.Numerics.Vectors
0x53A Aug 5, 2019
444a9c6
add support for nested "testList", fixes https://github.com/fable-com…
0x53A Aug 5, 2019
250c63e
add equality tests
0x53A Aug 5, 2019
0d4cfc1
override equality and comparison for Vector3
0x53A Aug 5, 2019
1b928ca
split file into Vector3.fs and Quaternion.fs
0x53A Aug 5, 2019
5c27ea2
add missing cases to transformTypeInfo
0x53A Aug 5, 2019
50aa0a9
Revert "split file into Vector3.fs and Quaternion.fs"
0x53A Aug 5, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr =
| _ -> return failwith "makeFunctionArgs returns args with different length"

// Getters and Setters

| BasicPatterns.FSharpFieldGet(callee, calleeType, field) ->
let! callee = transformExprOpt com ctx callee
let callee =
Expand Down Expand Up @@ -660,6 +661,7 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr =
let typ = makeType com ctx.GenericArgs fsExpr.Type
return Fable.DecisionTreeSuccess(targetIndex, boundValues, typ)

// read a static field (Example: Decimal.Zero)
| BasicPatterns.ILFieldGet(None, ownerTyp, fieldName) ->
let ownerTyp = makeType com ctx.GenericArgs ownerTyp
let typ = makeType com ctx.GenericArgs fsExpr.Type
Expand All @@ -669,6 +671,31 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr =
return sprintf "Cannot compile ILFieldGet(%A, %s)" ownerTyp fieldName
|> addErrorAndReturnNull com ctx.InlinePath (makeRangeFrom fsExpr)

// read a member field (Example: Vector3.X)
| BasicPatterns.ILFieldGet(Some callee, calleeType, fieldName)
when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs calleeType) fieldName) ->
let! callee = transformExprOpt com ctx (Some callee)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just use let! callee = transformExpr com ctx callee (same below for ILFieldSet).

let callee =
match callee with
| Some callee -> callee
| None -> entityRef com calleeType.TypeDefinition
let typ = makeType com ctx.GenericArgs fsExpr.Type
let kind = Fable.FieldGet(fieldName, true, typ)
let typ = makeType com ctx.GenericArgs fsExpr.Type
return Fable.Get(callee, kind, typ, makeRangeFrom fsExpr)

// write a member field (example: Vector3.X)
| BasicPatterns.ILFieldSet(Some callee, calleeType, fieldName, value)
when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs calleeType) fieldName) ->
let! callee = transformExprOpt com ctx (Some callee)
let! value = transformExpr com ctx value
let callee =
match callee with
| Some callee -> callee
| None -> entityRef com calleeType.TypeDefinition
let typ = makeType com ctx.GenericArgs fsExpr.Type
return Fable.Set(callee, Fable.FieldSet(fieldName, typ), value, makeRangeFrom fsExpr)

| BasicPatterns.Quote _ ->
return "Quotes are not currently supported by Fable"
|> addErrorAndReturnNull com ctx.InlinePath (makeRangeFrom fsExpr)
Expand All @@ -677,8 +704,7 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr =
| BasicPatterns.AddressOf(expr) ->
let! expr = transformExpr com ctx expr
return expr

// | BasicPatterns.ILFieldSet _

// | BasicPatterns.AddressSet _
// | BasicPatterns.ILAsm _
| expr ->
Expand Down
2 changes: 2 additions & 0 deletions src/dotnet/Fable.Compiler/Transforms/Fable2Babel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,8 @@ module Util =
| Replacements.BclUInt64 -> jsInstanceof (coreValue com ctx "Long" "default") expr
| Replacements.BclDecimal -> jsInstanceof (coreValue com ctx "Decimal" "default") expr
| Replacements.BclBigInt -> coreLibCall com ctx "BigInt" "isBigInt" [|com.TransformAsExpr(ctx, expr)|]
| Replacements.BclQuaternion -> jsInstanceof (coreValue com ctx "Quaternion" "default") expr
| Replacements.BclVector3 -> jsInstanceof (coreValue com ctx "Vector3" "default") expr
| Replacements.BclHashSet _
| Replacements.BclDictionary _
| Replacements.FSharpSet _
Expand Down
17 changes: 17 additions & 0 deletions src/dotnet/Fable.Compiler/Transforms/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ type BuiltinType =
| BclUInt64
| BclDecimal
| BclBigInt
| BclQuaternion
| BclVector3
| BclHashSet of Type
| BclDictionary of key:Type * value:Type
| FSharpSet of Type
Expand All @@ -147,6 +149,8 @@ let (|Builtin|_|) = function
| Some Types.decimal, _
| Some "Microsoft.FSharp.Core.decimal`1", _ -> Some BclDecimal
| Some Types.bigint, _ -> Some BclBigInt
| Some Types.quaternion, _ -> Some BclQuaternion
| Some Types.vector3, _ -> Some BclVector3
| Some Types.fsharpSet, [t] -> Some(FSharpSet(t))
| Some Types.fsharpMap, [k;v] -> Some(FSharpMap(k,v))
| Some Types.hashset, [t] -> Some(BclHashSet(t))
Expand Down Expand Up @@ -228,6 +232,8 @@ let coreModFor = function
| BclUInt64 -> "Long"
| BclDecimal -> "Decimal"
| BclBigInt -> "BigInt"
| BclQuaternion _ -> "Quaternion"
| BclVector3 _ -> "Vector3"
| BclTimeSpan -> "Int32"
| FSharpSet _ -> "Set"
| FSharpMap _ -> "Map"
Expand Down Expand Up @@ -2503,6 +2509,7 @@ let partialApplyAtRuntime t arity (fn: Expr) (args: Expr list) =
let args = NewArray(ArrayValues args, Any) |> Value
Helper.CoreCall("Util", "partialApply", t, [makeIntConst arity; fn; args])

/// try to map a static field (e.g. Decimal.Zero)
let tryField returnTyp ownerTyp fieldName =
match ownerTyp, fieldName with
| Builtin BclDecimal, "Zero" -> makeIntConst 0 |> makeDecimalFromExpr returnTyp |> Some
Expand All @@ -2516,6 +2523,14 @@ let tryField returnTyp ownerTyp fieldName =
Helper.CoreCall(coreModFor BclDateTimeOffset, Naming.lowerFirst fieldName, returnTyp, []) |> Some
| _ -> None

// this is queried when an IL member field is read / written.
// at the moment member fields are only supported for Vector3 / Quaternion, all other supported BCL types expose properties instead of fields.
let isILMemberFieldSupported ownerTyp _fieldName =
match ownerTyp with
| Builtin BclQuaternion
| Builtin BclVector3 -> true
| _ -> false

let private replacedModules =
dict [
"System.Math", operators
Expand Down Expand Up @@ -2617,6 +2632,8 @@ let private replacedModules =
"Microsoft.FSharp.Control.ObservableModule", observable
Types.type_, types
"System.Reflection.TypeInfo", types
"System.Numerics.Vector3", bclType
"System.Numerics.Quaternion", bclType
]

let tryCall (com: ICompiler) (ctx: Context) r t (info: CallInfo) (thisArg: Expr option) (args: Expr list) =
Expand Down
2 changes: 2 additions & 0 deletions src/dotnet/Fable.Compiler/Transforms/Transforms.Util.fs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ module Types =
let [<Literal>] float64 = "System.Double"
let [<Literal>] decimal = "System.Decimal"
let [<Literal>] bigint = "System.Numerics.BigInteger"
let [<Literal>] quaternion = "System.Numerics.Quaternion"
let [<Literal>] vector3 = "System.Numerics.Vector3"
let [<Literal>] regex = "System.Text.RegularExpressions.Regex"
let [<Literal>] unit = "Microsoft.FSharp.Core.Unit"
let [<Literal>] option = "Microsoft.FSharp.Core.FSharpOption`1"
Expand Down
1 change: 1 addition & 0 deletions src/js/fable-core/Fable.Core.JS.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="System.Numerics.fs" />
<Compile Include="Global.fs" />
<Compile Include="BigInt/n.fsi"/>
<Compile Include="BigInt/n.fs"/>
Expand Down
250 changes: 250 additions & 0 deletions src/js/fable-core/System.Numerics.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
namespace System.Numerics

// contains the types Vector3 and Quaternion.
// feel free to add the rest as required



type Vector3 =
struct

val mutable public X : single
val mutable public Y : single
val mutable public Z : single

new (value : single) = { X = value; Y = value; Z = value }
new (x : single, y : single, z : single) = { X = x; Y = y; Z = z }

member this.Abs() = Vector3(System.Math.Abs(this.X), System.Math.Abs(this.Y), System.Math.Abs(this.Z))

member this.CopyTo(arr : single array, index : int) =
arr.[index + 0] <- this.X
arr.[index + 1] <- this.Y
arr.[index + 2] <- this.Z

member this.CopyTo(arr : single array) = this.CopyTo(arr, 0)

//member __.Equals(other : Vector3) =
// x = other.X &&
// y = other.Y &&
// z = other.Z

//override this.Equals(other : obj) =
// match other with
// | :? Vector3 as vother ->
// this.Equals(vother)
// | _ -> false

//override __.GetHashCode() =
// hash(x, y, z)


// --------------------------------
// Static members of Vector3

static member One = Vector3(1.f, 1.f, 1.f)

static member UnitX = Vector3(1.f, 0.f, 0.f)
static member UnitY = Vector3(0.f, 1.f, 0.f)
static member UnitZ = Vector3(0.f, 0.f, 1.f)

static member Zero = Vector3(0.f, 0.f, 0.f)

static member Add(left : Vector3, right : Vector3) =
Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z)

static member Divide(left : Vector3, right : Vector3) =
Vector3(left.X / right.X, left.Y / right.Y, left.Z / right.Z)

static member Divide(left : Vector3, right : single) =
Vector3(left.X / right, left.Y / right, left.Z / right)

static member Clamp(value : Vector3, min : Vector3, max : Vector3) =
let inline clamp v min max =
if v < min then min
else if v > max then max
else v
Vector3(clamp value.X min.X max.X,
clamp value.Y min.Y max.Y,
clamp value.Z min.Z max.Z)

static member Cross(vector1 : Vector3, vector2 : Vector3) =
Vector3(vector1.Y * vector2.Z - vector1.Z * vector2.Y,
vector1.Z * vector2.X - vector1.X * vector2.Z,
vector1.X * vector2.Y - vector1.Y * vector2.X)

static member Distance(value1 : Vector3, value2 : Vector3) : single =
let num2 = value1.X - value2.X
let num3 = value1.Y - value2.Y
let num4 = value1.Z - value2.Z
let num5 = num2 * num2 + num3 * num3 + num4 * num4;
single ( System.Math.Sqrt(float num5) )

static member DistanceSquared(value1 : Vector3, value2 : Vector3) : single =
let num2 = value1.X - value2.X
let num3 = value1.Y - value2.Y
let num4 = value1.Z - value2.Z
let num5 = num2 * num2 + num3 * num3 + num4 * num4;
num5


// --------------------------------
// Operators of Vector3

static member (+) (left:Vector3, right:Vector3) : Vector3 =
Vector3.Add(left, right)

static member (/) (left:Vector3, right:Vector3) : Vector3 =
Vector3.Divide(left, right)

static member (/) (left:Vector3, right:single) : Vector3 =
Vector3.Divide(left, right)
end

type Quaternion =
struct

val mutable public X : single
val mutable public Y : single
val mutable public Z : single
val mutable public W : single

new (x : single, y : single, z : single, w : single) = { X = x; Y = y; Z = z; W = w }
new(vectorPart : Vector3, scalarPart : single) =
Quaternion(vectorPart.X, vectorPart.Y, vectorPart.Z, scalarPart)

member this.IsIdentity =
this.X = 0.f &&
this.Y = 0.f &&
this.Z = 0.f &&
this.W = 1.f

member this.Length() : single =
let ls = this.LengthSquared()
single ( System.Math.Sqrt(float ls) )

member this.LengthSquared() : single =
this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W


// --------------------------------
// static members of Quaternion

static member Identity = Quaternion(0.f, 0.f, 0.f, 1.f)

static member Add(value1 : Quaternion, value2 : Quaternion) =
Quaternion(
value1.X + value2.X,
value1.Y + value2.Y,
value1.Z + value2.Z,
value1.W + value2.W
)

static member Concatenate(value1 : Quaternion, value2 : Quaternion) =
let x = value2.X;
let y = value2.Y;
let z = value2.Z;
let w = value2.W;
let x2 = value1.X;
let y2 = value1.Y;
let z2 = value1.Z;
let w2 = value1.W;
let num = y * z2 - z * y2;
let num2 = z * x2 - x * z2;
let num3 = x * y2 - y * x2;
let num4 = x * x2 + y * y2 + z * z2;
Quaternion(
x * w2 + x2 * w + num,
y * w2 + y2 * w + num2,
z * w2 + z2 * w + num3,
w * w2 - num4
)

static member Conjugate(value : Quaternion) =
Quaternion(
0.f - value.X,
0.f - value.Y,
0.f - value.Z,
value.W
)

static member Divide(value1 : Quaternion, value2 : Quaternion) =
let x = value1.X;
let y = value1.Y;
let z = value1.Z;
let w = value1.W;
let num = value2.X * value2.X + value2.Y * value2.Y + value2.Z * value2.Z + value2.W * value2.W;
let num2 = 1.f / num;
let num3 = (0.f - value2.X) * num2;
let num4 = (0.f - value2.Y) * num2;
let num5 = (0.f - value2.Z) * num2;
let num6 = value2.W * num2;
let num7 = y * num5 - z * num4;
let num8 = z * num3 - x * num5;
let num9 = x * num4 - y * num3;
let num10 = x * num3 + y * num4 + z * num5;
Quaternion(
x * num6 + num3 * w + num7,
y * num6 + num4 * w + num8,
z * num6 + num5 * w + num9,
w * num6 - num10
)

static member Dot(quaternion1 : Quaternion, quaternion2 : Quaternion) : single =
quaternion1.X * quaternion2.X + quaternion1.Y * quaternion2.Y + quaternion1.Z * quaternion2.Z + quaternion1.W * quaternion2.W

static member Inverse(value : Quaternion) : Quaternion =
let num = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W;
let num2 = 1.f / num;
Quaternion(
(0.f - value.X) * num2,
(0.f - value.Y) * num2,
(0.f - value.Z) * num2,
value.W * num2
)

static member Multiply(value1 : Quaternion, value2 : Quaternion) : Quaternion =
let x = value1.X;
let y = value1.Y;
let z = value1.Z;
let w = value1.W;
let x2 = value2.X;
let y2 = value2.Y;
let z2 = value2.Z;
let w2 = value2.W;
let num = y * z2 - z * y2;
let num2 = z * x2 - x * z2;
let num3 = x * y2 - y * x2;
let num4 = x * x2 + y * y2 + z * z2;
Quaternion(
x * w2 + x2 * w + num,
y * w2 + y2 * w + num2,
z * w2 + z2 * w + num3,
w * w2 - num4
)

static member Multiply(value1 : Quaternion, value2 : single) : Quaternion =
Quaternion(
value1.X * value2,
value1.Y * value2,
value1.Z * value2,
value1.W * value2
)


// --------------------------------
// Operators of Quaternion

static member (+) (left:Quaternion, right:Quaternion) : Quaternion =
Quaternion.Add(left, right)

static member (/) (left:Quaternion, right:Quaternion) : Quaternion =
Quaternion.Divide(left, right)

static member (*) (left:Quaternion, right:Quaternion) : Quaternion =
Quaternion.Multiply(left, right)

static member (*) (left:Quaternion, right:single) : Quaternion =
Quaternion.Multiply(left, right)

end
Loading