Skip to content

Commit

Permalink
Temp commit
Browse files Browse the repository at this point in the history
  • Loading branch information
alfonsogarciacaro committed Nov 23, 2022
1 parent 8e9602e commit 396e154
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 34 deletions.
44 changes: 38 additions & 6 deletions src/Fable.Core/Fable.Core.Util.fs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,44 @@ module Testing =


module Reflection =
let isUnion (x: obj): bool = nativeOnly
let isRecord (x: obj): bool = nativeOnly

let getCaseTag (x: obj): int = nativeOnly
let getCaseName (x: obj): string = nativeOnly
let getCaseFields (x: obj): obj[] = nativeOnly
open FSharp.Reflection

let isUnion (x: obj): bool =
#if FABLE_COMPILER
nativeOnly
#else
FSharpType.IsUnion(x.GetType())
#endif

let isRecord (x: obj): bool =
#if FABLE_COMPILER
nativeOnly
#else
FSharpType.IsRecord(x.GetType())
#endif

let getCaseTag (x: obj): int =
#if FABLE_COMPILER
nativeOnly
#else
let uci, _ = FSharpValue.GetUnionFields(x, x.GetType())
uci.Tag
#endif

let getCaseName (x: obj): string =
#if FABLE_COMPILER
nativeOnly
#else
let uci, _ = FSharpValue.GetUnionFields(x, x.GetType())
uci.Name
#endif

let getCaseFields (x: obj): obj[] =
#if FABLE_COMPILER
nativeOnly
#else
FSharpValue.GetUnionFields(x, x.GetType()) |> snd
#endif

module Compiler =
/// Compiler full version as string
Expand Down
85 changes: 58 additions & 27 deletions src/fable-library/Reflection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export class CaseInfo {
}
}

export const enum ErasedUnion {
Default,
WithTag
}

export type EnumCase = [string, number];

export class MethodInfo {
Expand All @@ -32,13 +37,21 @@ export class MethodInfo {
export class TypeInfo implements IEquatable<TypeInfo> {
constructor(
public fullname: string,
public generics?: TypeInfo[],
public construct?: Constructor,
public parent?: TypeInfo,
public fields?: () => FieldInfo[],
public cases?: () => CaseInfo[],
public enumCases?: EnumCase[]) {
}
private info?: {
generics?: TypeInfo[],
construct?: Constructor,
parent?: TypeInfo,
fields?: () => FieldInfo[],
cases?: () => CaseInfo[],
enumCases?: EnumCase[],
}
) { }
public get generics() { return this.info?.generics; }
public get construct() { return this.info?.construct; }
public get parent() { return this.info?.parent; }
public get fields() { return this.info?.fields; }
public get cases() { return this.info?.cases; }
public get enumCases() { return this.info?.enumCases; }
public toString() {
return fullName(this);
}
Expand Down Expand Up @@ -83,59 +96,74 @@ export function class_type(
generics?: TypeInfo[],
construct?: Constructor,
parent?: TypeInfo): TypeInfo {
return new TypeInfo(fullname, generics, construct, parent);
return new TypeInfo(fullname, { generics, construct, parent });
}

export function record_type(
fullname: string,
generics: TypeInfo[],
construct: Constructor,
fields: () => FieldInfo[]): TypeInfo {
return new TypeInfo(fullname, generics, construct, undefined, fields);
return new TypeInfo(fullname, { generics, construct, fields });
}

export function anonRecord_type(...fields: FieldInfo[]): TypeInfo {
return new TypeInfo("", undefined, undefined, undefined, () => fields);
return new TypeInfo("", { fields: () => fields });
}

export function union_type(
fullname: string,
generics: TypeInfo[],
construct: Constructor,
cases: () => FieldInfo[][]): TypeInfo {
const t: TypeInfo = new TypeInfo(fullname, generics, construct, undefined, undefined, () => {
const caseNames = construct.prototype.cases() as string[];
return cases().map((fields, i) => new CaseInfo(t, i, caseNames[i], fields))
const t: TypeInfo = new TypeInfo(fullname, {
generics,
construct,
cases() {
const caseNames = construct.prototype.cases() as string[];
return cases().map((fields, i) => new CaseInfo(t, i, caseNames[i], fields))
}
});
return t;
}

export function tuple_type(...generics: TypeInfo[]): TypeInfo {
return new TypeInfo("System.Tuple`" + generics.length, generics);
return new TypeInfo("System.Tuple`" + generics.length, { generics });
}

export function delegate_type(...generics: TypeInfo[]): TypeInfo {
return new TypeInfo("System.Func`" + generics.length, generics);
return new TypeInfo("System.Func`" + generics.length, { generics });
}

export function lambda_type(argType: TypeInfo, returnType: TypeInfo): TypeInfo {
return new TypeInfo("Microsoft.FSharp.Core.FSharpFunc`2", [argType, returnType]);
return new TypeInfo("Microsoft.FSharp.Core.FSharpFunc`2", {
generics: [argType, returnType]
});
}

export function option_type(generic: TypeInfo): TypeInfo {
return new TypeInfo("Microsoft.FSharp.Core.FSharpOption`1", [generic]);
return new TypeInfo("Microsoft.FSharp.Core.FSharpOption`1", {
generics: [generic]
});
}

export function list_type(generic: TypeInfo): TypeInfo {
return new TypeInfo("Microsoft.FSharp.Collections.FSharpList`1", [generic]);
return new TypeInfo("Microsoft.FSharp.Collections.FSharpList`1", {
generics: [generic]
});
}

export function array_type(generic: TypeInfo): TypeInfo {
return new TypeInfo("[]", [generic]);
return new TypeInfo("[]", {
generics: [generic]
});
}

export function enum_type(fullname: string, underlyingType: TypeInfo, enumCases: EnumCase[]): TypeInfo {
return new TypeInfo(fullname, [underlyingType], undefined, undefined, undefined, undefined, enumCases);
return new TypeInfo(fullname, {
generics: [underlyingType],
enumCases
});
}

export function measure_type(fullname: string): TypeInfo {
Expand Down Expand Up @@ -262,7 +290,9 @@ export function isInstanceOfType(t: TypeInfo, o: any) {
* but it should be enough for type comparison purposes
*/
export function getGenericTypeDefinition(t: TypeInfo) {
return t.generics == null ? t : new TypeInfo(t.fullname, t.generics.map(() => obj_type));
return t.generics == null ? t : new TypeInfo(t.fullname, {
generics: t.generics.map(() => obj_type)
});
}

export function getEnumUnderlyingType(t: TypeInfo) {
Expand Down Expand Up @@ -452,12 +482,13 @@ export function makeTuple(values: any[], _t: TypeInfo): any {

export function makeGenericType(t: TypeInfo, generics: TypeInfo[]): TypeInfo {
return new TypeInfo(
t.fullname,
generics,
t.construct,
t.parent,
t.fields,
t.cases);
t.fullname, {
generics,
construct: t.construct,
parent: t.parent,
fields: t.fields,
cases: t.cases
});
}

export function createInstance(t: TypeInfo, consArgs?: any[]): any {
Expand Down
17 changes: 16 additions & 1 deletion src/quicktest/QuickTest.fs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,13 @@ let measureTime (f: unit -> unit): unit = emitJsStatement () """
// testCase "Addition works" <| fun () ->
// 2 + 2 |> equal 4

[<Erase>]
// [<Erase>]
type MyRecord =
{ Foo: int }

type MyRecord2 =
{ Bar: MyRecord }

let testMyRecord (r: MyRecord) =
r.Foo

Expand All @@ -100,6 +103,18 @@ let test = function
Zas 5.67890 |> test |> printfn "%s"
Foo("oh", 3) |> test |> printfn "%s"

[<Erase>]
type WrappedNum = Num of int with
static member ( + ) (Num x, Num y) = 2 * (x + y) |> Num

let add1 (x: WrappedNum) y = x + y

let add2 (x: WrappedNum) y = x + Num y

testCase "Can resolve custom operators on erased types" <| fun () -> // See #2915
add1 (Num 4) (Num 5) |> equal (Num 18)
add2 (Num 4) 5 |> equal (Num 18)

(*
module TaggedUnion =
type Base<'Kind> =
Expand Down

0 comments on commit 396e154

Please sign in to comment.