Skip to content

Commit

Permalink
Merge branch 'nagareyama' into nagareyama-type-test
Browse files Browse the repository at this point in the history
  • Loading branch information
alfonsogarciacaro authored Oct 1, 2020
2 parents 54a9193 + 7df9d89 commit 05dd2be
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 122 deletions.
9 changes: 9 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Node",
"port": 9229,
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "pwa-node"
},
{
"args": [
"${workspaceFolder}/build/tests",
Expand Down
24 changes: 15 additions & 9 deletions src/Fable.Cli/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,14 @@ type State =
ErroredFiles: Set<string>
TestInfo: TestInfo option }

let filterFiles (exclude: string option) (files: string[]) =
files
|> Array.filter (fun file -> file.EndsWith(".fs") || file.EndsWith(".fsx"))
|> fun filesToCompile ->
match exclude with
| Some exclude -> filesToCompile |> Array.filter (fun x -> not(x.Contains(exclude))) // Use regex?
| None -> filesToCompile

let rec startCompilation (changes: Set<string>) (state: State) = async {
let cracked, parsed, filesToCompile =
match state.ProjectCrackedAndParsed with
Expand Down Expand Up @@ -370,13 +378,9 @@ let rec startCompilation (changes: Set<string>) (state: State) = async {

let filesToCompile =
filesToCompile
|> Array.filter (fun file -> file.EndsWith(".fs") || file.EndsWith(".fsx"))
|> filterFiles state.CliArgs.Exclude
|> Array.append (Set.toArray state.ErroredFiles)
|> Array.distinct
|> fun filesToCompile ->
match state.CliArgs.Exclude with
| Some exclude -> filesToCompile |> Array.filter (fun x -> not(x.Contains(exclude))) // Use regex?
| None -> filesToCompile

let logs = getFSharpErrorLogs parsed.Project

Expand Down Expand Up @@ -442,10 +446,12 @@ let rec startCompilation (changes: Set<string>) (state: State) = async {

let! changes = Watcher.AwaitChanges [
cracked.ProjectFile
yield! cracked.SourceFiles |> Seq.choose (fun f ->
let path = f.NormalizedFullPath
if Naming.isInFableHiddenDir(path) then None
else Some path)
yield! cracked.SourceFiles
|> Array.choose (fun f ->
let path = f.NormalizedFullPath
if Naming.isInFableHiddenDir(path) then None
else Some path)
|> filterFiles state.CliArgs.Exclude
]
return!
{ state with ProjectCrackedAndParsed = Some(cracked, parsed)
Expand Down
16 changes: 9 additions & 7 deletions src/Fable.Transforms/Replacements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -405,13 +405,15 @@ let toString com (ctx: Context) r (args: Expr list) =
| Number Int32 -> Helper.LibCall(com, "Util", "int32ToString", String, args)
| Number _ -> Helper.InstanceCall(head, "toString", String, tail)
| DeclaredType(ent, _) ->
let moduleName, methodName =
if ent.IsFSharpUnion then "Types", "unionToString"
elif ent.IsFSharpRecord then "Types", "recordToString"
elif ent.IsValueType then "Types", "objectToString"
else "Types", "objectToString"
Helper.LibCall(com, moduleName, methodName, String, [head], ?loc=r)
| _ -> Helper.GlobalCall("String", String, [head])
let methodName =
if ent.IsFSharpUnion then "unionToString"
elif ent.IsFSharpRecord then "recordToString"
elif ent.FullName = Types.ienumerableGeneric then "seqToString"
else "objectToString"
Helper.LibCall(com, "String", methodName, String, [head], ?loc=r)
| Array _ | List _ ->
Helper.LibCall(com, "String", "seqToString", String, [head], ?loc=r)
| _ -> Helper.LibCall(com, "String", "toString", String, [head], ?loc=r)

let getParseParams (kind: NumberExtKind) =
let isFloatOrDecimal, numberModule, unsigned, bitsize =
Expand Down
4 changes: 1 addition & 3 deletions src/fable-library/Seq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,9 @@ function __failIfNone<T>(res: Option<T>) {
}

function makeSeq<T>(f: () => Iterator<T>): Iterable<T> {
const seq = {
return {
[Symbol.iterator]: f,
toString: () => "seq [" + Array.from(seq).join("; ") + "]",
};
return seq;
}

function isArrayOrBufferView<T>(xs: Iterable<T>): xs is T[] {
Expand Down
87 changes: 85 additions & 2 deletions src/fable-library/String.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import { toString as dateToString } from "./Date.js";
import Decimal from "./Decimal.js";
import Long, * as _Long from "./Long.js";
import { escape } from "./RegExp.js";
import { isIterable, isUnionLike } from "./Util.js";

type Numeric = number | Long | Decimal;

export interface IStringable {
ToString(): string;
}

const fsFormatRegExp = /(^|[^%])%([0+\- ]*)(\d+)?(?:\.(\d+))?(\w)/;
const formatRegExp = /\{(\d+)(,-?\d+)?(?:\:([a-zA-Z])(\d{0,2})|\:(.+?))?\}/g;

type Numeric = number | Long | Decimal;

// These are used for formatting and only take longs and decimals into account (no bigint)
function isNumeric(x: any) {
return typeof x === "number" || x instanceof Long || x instanceof Decimal;
Expand Down Expand Up @@ -219,6 +224,8 @@ function formatOnce(str2: string, rep: any) {
rep = String(rep);
break;
}
} else {
rep = toString(rep);
}
padLength = parseInt(padLength, 10);
if (!isNaN(padLength)) {
Expand Down Expand Up @@ -309,6 +316,8 @@ export function format(str: string, ...args: any[]) {
}
} else if (rep instanceof Date) {
rep = dateToString(rep, pattern || format);
} else {
rep = toString(rep)
}
padLength = parseInt((padLength || " ").substring(1), 10);
if (!isNaN(padLength)) {
Expand All @@ -318,6 +327,80 @@ export function format(str: string, ...args: any[]) {
});
}

export function isStringable<T>(x: T | IStringable): x is IStringable {
return x != null && typeof (x as IStringable).ToString === "function";
}

function unionToStringPrivate(self: any): string {
const name = self.cases()[self.tag];
if (self.fields.length === 0) {
return name;
} else {
let fields = "";
let withParens = true;
if (self.fields.length === 1) {
const field = toString(self.fields[0]);
withParens = field.indexOf(" ") >= 0;
fields = field;
}
else {
fields = self.fields.map((x: any) => toString(x)).join(", ");
}
return name + (withParens ? " (" : " ") + fields + (withParens ? ")" : "");
}
}

export function unionToString(self: any) {
return isStringable(self) ? self.ToString() : unionToStringPrivate(self);
}

function recordToStringPrivate(self: any, callStack=0): string {
return callStack > 10
? Object.getPrototypeOf(self).constructor.name
: "{ " + Object.entries(self).map(([k, v]) => k + " = " + toString(v, callStack)).join("\n ") + " }";
}

export function recordToString(self: any): string {
return isStringable(self) ? self.ToString() : recordToStringPrivate(self);
}

export function objectToString(self: any): string {
return isStringable(self) ? self.ToString() : Object.getPrototypeOf(self).constructor.name;
}

export function seqToString<T>(self: Iterable<T>): string {
let count = 0;
let str = "[";
for (let x of self) {
if (count === 0) {
str += toString(x);
} else if (count === 100) {
str += "; ...";
break;
} else {
str += "; " + toString(x);
}
count++;
}
return str + "]";
}

export function toString(x: any, callStack=-1): string {
if (x == null || typeof x !== "object") {
return String(x);
} else if (isStringable(x)) {
return x.ToString();
} else if (isIterable(x)) {
return seqToString(x);
} else if (isUnionLike(x)) {
return unionToStringPrivate(x);
} else {
// TODO: Defaulting to recordToString until we have a way
// to tell records apart from other objects in runtime
return recordToStringPrivate(x, callStack + 1);
}
}

export function endsWith(str: string, search: string) {
const idx = str.lastIndexOf(search);
return idx >= 0 && idx === str.length - search.length;
Expand Down
49 changes: 10 additions & 39 deletions src/fable-library/Types.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
import { IEquatable, IComparable, combineHashCodes, compare, compareArrays, equalArrays, equals, isComparable, isEquatable, isHashable, sameConstructor, isStringable, numberHash, structuralHash } from "./Util.js";

export function objectToString(self: any) {
if (isStringable(self)) {
return self.ToString();
} else {
return Object.getPrototypeOf(self).constructor.name;
}
}
import { IEquatable, IComparable, combineHashCodes, compare, compareArrays, equalArrays, equals, isComparable, isEquatable, isHashable, sameConstructor, numberHash, structuralHash } from "./Util.js";

// export class SystemObject implements IEquatable<any> {

Expand Down Expand Up @@ -66,17 +58,17 @@ export class List<T> implements IEquatable<List<T>>, IComparable<List<T>>, Itera
};
}

public toJSON() {
return Array.from(this);
}
// public toJSON() {
// return Array.from(this);
// }

public toString() {
return this.ToString();
}
// public toString() {
// return this.ToString();
// }

public ToString() {
return "[" + Array.from(this).join("; ") + "]";
}
// public ToString() {
// return "[" + Array.from(this).join("; ") + "]";
// }

public GetHashCode() {
const hashes = Array.from(this).map(structuralHash);
Expand All @@ -92,19 +84,6 @@ export class List<T> implements IEquatable<List<T>>, IComparable<List<T>>, Itera
}
}

export function unionToString(self: any) {
const name = self.cases()[self.tag];
if (isStringable(self)) {
return self.ToString();
} else if (self.fields.length === 0) {
return name;
} else if (self.fields.length === 1) {
return name + " " + String(self.fields[0]);
} else {
return name + " (" + self.fields.map((x: any) => String(x)).join(",") + ")";
}
}

export function unionToJson(self: any) {
const name = self.cases()[self.tag];
return self.fields.length === 0 ? name : [name].concat(self.fields);
Expand Down Expand Up @@ -186,14 +165,6 @@ export function unionCompareTo(self: any, other: any) {
// }
// }

export function recordToString(self: any) {
if (isStringable(self)) {
return self.ToString();
} else {
return "{" + Object.entries(self).map(([k, v]) => k + " = " + String(v)).join(";\n ") + "}";
}
}

export function recordToJson(self: any, getFieldNames?: (arg: any) => any) {
const o: any = {};
const keys = getFieldNames == null ? Object.keys(self) : getFieldNames(self);
Expand Down
10 changes: 1 addition & 9 deletions src/fable-library/Util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ export interface IDisposable {
Dispose(): void;
}

export interface IStringable {
ToString(): void;
}

export interface IComparer<T> {
Compare(x: T, y: T): number;
}
Expand Down Expand Up @@ -108,16 +104,12 @@ export function isDisposable<T>(x: T | IDisposable): x is IDisposable {
return x != null && typeof (x as IDisposable).Dispose === "function";
}

export function isStringable<T>(x: T | IStringable): x is IStringable {
return x != null && typeof (x as IStringable).ToString === "function";
}

export function sameConstructor(x: any, y: any) {
return Object.getPrototypeOf(x).constructor === Object.getPrototypeOf(y).constructor;
}

export function isUnionLike(x: any) {
return x != null && x.tag != null && x.fields != null && typeof x.cases === "function";
return x != null && typeof x.tag === "number" && Array.isArray(x.fields) && typeof x.cases === "function";
}

export class Comparer<T> implements IComparer<T> {
Expand Down
23 changes: 4 additions & 19 deletions src/quicktest/QuickTest.fs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ let testCaseAsync msg f =
printfn "%s" ex.StackTrace
} |> Async.StartImmediate)

let measureTime (f: unit -> unit) = emitJsStatement f """
let measureTime (f: unit -> unit) = emitJsStatement () """
//js
const startTime = process.hrtime();
$0();
f();
const elapsed = process.hrtime(startTime);
console.log("Ms:", elapsed[0] * 1e3 + elapsed[1] / 1e6);
//!js
Expand All @@ -67,22 +67,6 @@ let measureTime (f: unit -> unit) = emitJsStatement f """
// testCase "Addition works" <| fun () ->
// 2 + 2 |> equal 4

type MyGetter =
abstract Foo: int
abstract MyNumber: int

measureTime <| (fun () ->
let myGetter = { new MyGetter with
member _.Foo = 1
member this.MyNumber = this.Foo + 1 }

let mutable x = 0
for i = 0 to 1000000000 do
x <- x + myGetter.MyNumber

printfn "x = %i" x
)

let test (exn: exn) =
match exn with
| :? System.NotSupportedException -> ()
Expand All @@ -97,4 +81,5 @@ let test2 () =
elif false then
"bar"
else
"baz"
"baz"

Loading

0 comments on commit 05dd2be

Please sign in to comment.