From 0560c03d4b901f88b4c904c8d30525e2dbd3e666 Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Fri, 5 Jul 2024 11:03:47 +0100 Subject: [PATCH 1/5] Less nested seq-wrapping on recursive functions --- src/FSharp.Data.Csv.Core/CsvRuntime.fs | 30 ++++++----- src/FSharp.Data.Html.Core/HtmlParser.fs | 8 ++- .../NameUtils.fs | 52 ++++++++++--------- .../TextConversions.fs | 19 +++---- 4 files changed, 60 insertions(+), 49 deletions(-) diff --git a/src/FSharp.Data.Csv.Core/CsvRuntime.fs b/src/FSharp.Data.Csv.Core/CsvRuntime.fs index 0cd96ce57..6e49173ac 100644 --- a/src/FSharp.Data.Csv.Core/CsvRuntime.fs +++ b/src/FSharp.Data.Csv.Core/CsvRuntime.fs @@ -64,20 +64,22 @@ module internal CsvReader = /// Reads multiple lines from the input, skipping newline characters let rec readLines lineNumber = - seq { - match reader.Read() with - | -1 -> () - | Char '\r' - | Char '\n' -> yield! readLines lineNumber - | current -> - yield - readLine [] (StringBuilder()) current - |> List.rev - |> Array.ofList, - lineNumber - - yield! readLines (lineNumber + 1) - } + match reader.Read() with + | -1 -> Seq.empty + | Char '\r' + | Char '\n' -> readLines lineNumber + | current -> + let r1 = + readLine [] (StringBuilder()) current + |> List.rev + |> Array.ofList, + lineNumber + + let r2 = readLines (lineNumber + 1) + seq { + yield r1 + yield! r2 + } readLines 0 diff --git a/src/FSharp.Data.Html.Core/HtmlParser.fs b/src/FSharp.Data.Html.Core/HtmlParser.fs index 1c9f4519d..21f80b8bf 100644 --- a/src/FSharp.Data.Html.Core/HtmlParser.fs +++ b/src/FSharp.Data.Html.Core/HtmlParser.fs @@ -14,14 +14,18 @@ open System.Collections.Generic module private TextParser = - let toPattern f c = if f c then Some c else None + let toPattern f c = if f c then ValueSome c else ValueNone + [] let (|EndOfFile|_|) (c: char) = let value = c |> int - if (value = -1 || value = 65535) then Some c else None + if (value = -1 || value = 65535) then ValueSome c else ValueNone + [] let (|Whitespace|_|) = toPattern Char.IsWhiteSpace + [] let (|LetterDigit|_|) = toPattern Char.IsLetterOrDigit + [] let (|Letter|_|) = toPattern Char.IsLetter // -------------------------------------------------------------------------------------- diff --git a/src/FSharp.Data.Runtime.Utilities/NameUtils.fs b/src/FSharp.Data.Runtime.Utilities/NameUtils.fs index 7ad37a816..0c3adf9a6 100644 --- a/src/FSharp.Data.Runtime.Utilities/NameUtils.fs +++ b/src/FSharp.Data.Runtime.Utilities/NameUtils.fs @@ -41,36 +41,40 @@ let nicePascalName (s: string) = else // Starting to parse a new segment let rec restart i = - seq { - match tryAt s i with - | EOF -> () - | LetterDigit _ & Upper _ -> yield! upperStart i (i + 1) - | LetterDigit _ -> yield! consume i false (i + 1) - | _ -> yield! restart (i + 1) - } + match tryAt s i with + | EOF -> Seq.empty + | LetterDigit _ & Upper _ -> upperStart i (i + 1) + | LetterDigit _ -> consume i false (i + 1) + | _ -> restart (i + 1) // Parsed first upper case letter, continue either all lower or all upper and upperStart from i = - seq { - match tryAt s i with - | Upper _ -> yield! consume from true (i + 1) - | Lower _ -> yield! consume from false (i + 1) - | _ -> + match tryAt s i with + | Upper _ -> consume from true (i + 1) + | Lower _ -> consume from false (i + 1) + | _ -> + seq { yield from, i yield! restart (i + 1) - } + } // Consume are letters of the same kind (either all lower or all upper) and consume from takeUpper i = - seq { - match tryAt s i with - | Lower _ when not takeUpper -> yield! consume from takeUpper (i + 1) - | Upper _ when takeUpper -> yield! consume from takeUpper (i + 1) - | Lower _ when takeUpper -> - yield from, (i - 1) - yield! restart (i - 1) - | _ -> - yield from, i - yield! restart i - } + match takeUpper, tryAt s i with + | false, Lower _ -> consume from takeUpper (i + 1) + | true, Upper _ -> consume from takeUpper (i + 1) + | true, Lower _ -> + let r1 = from, (i - 1) + let r2 = restart (i - 1) + seq { + yield r1 + yield! r2 + } + | _ -> + let r1 = from, i + let r2 = restart i + seq { + yield r1 + yield! r2 + } // Split string into segments and turn them to PascalCase seq { diff --git a/src/FSharp.Data.Runtime.Utilities/TextConversions.fs b/src/FSharp.Data.Runtime.Utilities/TextConversions.fs index d78dc4bf3..459337652 100644 --- a/src/FSharp.Data.Runtime.Utilities/TextConversions.fs +++ b/src/FSharp.Data.Runtime.Utilities/TextConversions.fs @@ -44,8 +44,8 @@ module private Helpers = let ParseISO8601FormattedDateTime text cultureInfo = match DateTime.TryParse(text, cultureInfo, dateTimeStyles) with - | true, d -> d |> Some - | false, _ -> None + | true, d -> d |> ValueSome + | false, _ -> ValueNone // -------------------------------------------------------------------------------------- @@ -155,8 +155,9 @@ type TextConversions private () = else // Parse ISO 8601 format, fixing time zone if needed match ParseISO8601FormattedDateTime text cultureInfo with - | Some d when d.Kind = DateTimeKind.Unspecified -> new DateTime(d.Ticks, DateTimeKind.Local) |> Some - | x -> x + | ValueSome d when d.Kind = DateTimeKind.Unspecified -> new DateTime(d.Ticks, DateTimeKind.Local) |> Some + | ValueSome x -> Some x + | ValueNone -> None static member AsDateTimeOffset cultureInfo (text: string) = // get TimeSpan presentation from 4-digit integers like 0000 or -0600 @@ -167,8 +168,8 @@ type TextConversions private () = let offset str = match Int32.TryParse str with - | true, v -> getTimeSpanFromHourMin v |> Some - | false, _ -> None + | true, v -> getTimeSpanFromHourMin v |> ValueSome + | false, _ -> ValueNone let matchesMS = msDateRegex.Value.Match(text.Trim()) @@ -178,15 +179,15 @@ type TextConversions private () = // only if the timezone offset is specified with '-' or '+' prefix, after the millis // e.g. 1231456+1000, 123123+0000, 123123-0500, etc. match offset matchesMS.Groups.[2].Value with - | Some ofst -> + | ValueSome ofst -> matchesMS.Groups.[1].Value |> Double.Parse |> DateTimeOffset(1970, 1, 1, 0, 0, 0, ofst).AddMilliseconds |> Some - | None -> None + | ValueNone -> None else match ParseISO8601FormattedDateTime text cultureInfo with - | Some d when d.Kind <> DateTimeKind.Unspecified -> + | ValueSome d when d.Kind <> DateTimeKind.Unspecified -> match DateTimeOffset.TryParse(text, cultureInfo, dateTimeStyles) with | true, dto -> dto |> Some | false, _ -> None From a19878d72ce8700e2f6236b9128919dd4fa504d4 Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Fri, 5 Jul 2024 11:14:55 +0100 Subject: [PATCH 2/5] a tuple to struct tuple --- src/FSharp.Data.Runtime.Utilities/NameUtils.fs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/FSharp.Data.Runtime.Utilities/NameUtils.fs b/src/FSharp.Data.Runtime.Utilities/NameUtils.fs index 0c3adf9a6..a45e3145d 100644 --- a/src/FSharp.Data.Runtime.Utilities/NameUtils.fs +++ b/src/FSharp.Data.Runtime.Utilities/NameUtils.fs @@ -52,9 +52,11 @@ let nicePascalName (s: string) = | Upper _ -> consume from true (i + 1) | Lower _ -> consume from false (i + 1) | _ -> + let r1 = struct (from, i) + let r2 = restart (i + 1) seq { - yield from, i - yield! restart (i + 1) + yield r1 + yield! r2 } // Consume are letters of the same kind (either all lower or all upper) and consume from takeUpper i = @@ -62,14 +64,14 @@ let nicePascalName (s: string) = | false, Lower _ -> consume from takeUpper (i + 1) | true, Upper _ -> consume from takeUpper (i + 1) | true, Lower _ -> - let r1 = from, (i - 1) + let r1 = struct (from, (i - 1)) let r2 = restart (i - 1) seq { yield r1 yield! r2 } | _ -> - let r1 = from, i + let r1 = struct (from, i) let r2 = restart i seq { yield r1 From a733a40d4b7df6bc794493ea229cfa5cdbcd8f4a Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Sun, 7 Jul 2024 17:23:31 +0100 Subject: [PATCH 3/5] Fantomas formatting --- src/FSharp.Data.Csv.Core/CsvRuntime.fs | 3 ++- src/FSharp.Data.Html.Core/HtmlParser.fs | 8 +++++++- src/FSharp.Data.Runtime.Utilities/NameUtils.fs | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/FSharp.Data.Csv.Core/CsvRuntime.fs b/src/FSharp.Data.Csv.Core/CsvRuntime.fs index 6e49173ac..e3f9ff556 100644 --- a/src/FSharp.Data.Csv.Core/CsvRuntime.fs +++ b/src/FSharp.Data.Csv.Core/CsvRuntime.fs @@ -69,13 +69,14 @@ module internal CsvReader = | Char '\r' | Char '\n' -> readLines lineNumber | current -> - let r1 = + let r1 = readLine [] (StringBuilder()) current |> List.rev |> Array.ofList, lineNumber let r2 = readLines (lineNumber + 1) + seq { yield r1 yield! r2 diff --git a/src/FSharp.Data.Html.Core/HtmlParser.fs b/src/FSharp.Data.Html.Core/HtmlParser.fs index 21f80b8bf..83cf1c2d1 100644 --- a/src/FSharp.Data.Html.Core/HtmlParser.fs +++ b/src/FSharp.Data.Html.Core/HtmlParser.fs @@ -19,12 +19,18 @@ module private TextParser = [] let (|EndOfFile|_|) (c: char) = let value = c |> int - if (value = -1 || value = 65535) then ValueSome c else ValueNone + + if (value = -1 || value = 65535) then + ValueSome c + else + ValueNone [] let (|Whitespace|_|) = toPattern Char.IsWhiteSpace + [] let (|LetterDigit|_|) = toPattern Char.IsLetterOrDigit + [] let (|Letter|_|) = toPattern Char.IsLetter diff --git a/src/FSharp.Data.Runtime.Utilities/NameUtils.fs b/src/FSharp.Data.Runtime.Utilities/NameUtils.fs index a45e3145d..96cd5236b 100644 --- a/src/FSharp.Data.Runtime.Utilities/NameUtils.fs +++ b/src/FSharp.Data.Runtime.Utilities/NameUtils.fs @@ -54,6 +54,7 @@ let nicePascalName (s: string) = | _ -> let r1 = struct (from, i) let r2 = restart (i + 1) + seq { yield r1 yield! r2 @@ -66,6 +67,7 @@ let nicePascalName (s: string) = | true, Lower _ -> let r1 = struct (from, (i - 1)) let r2 = restart (i - 1) + seq { yield r1 yield! r2 @@ -73,6 +75,7 @@ let nicePascalName (s: string) = | _ -> let r1 = struct (from, i) let r2 = restart i + seq { yield r1 yield! r2 From 0f989ec1538c6d1cc9265496c429a851da86a1cb Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Sun, 7 Jul 2024 21:59:06 +0100 Subject: [PATCH 4/5] yields are needed for tail-recursion? --- src/FSharp.Data.Csv.Core/CsvRuntime.fs | 17 +++++++-------- .../NameUtils.fs | 21 ++++++------------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/src/FSharp.Data.Csv.Core/CsvRuntime.fs b/src/FSharp.Data.Csv.Core/CsvRuntime.fs index e3f9ff556..cce4072da 100644 --- a/src/FSharp.Data.Csv.Core/CsvRuntime.fs +++ b/src/FSharp.Data.Csv.Core/CsvRuntime.fs @@ -69,17 +69,14 @@ module internal CsvReader = | Char '\r' | Char '\n' -> readLines lineNumber | current -> - let r1 = - readLine [] (StringBuilder()) current - |> List.rev - |> Array.ofList, - lineNumber - - let r2 = readLines (lineNumber + 1) - seq { - yield r1 - yield! r2 + yield + readLine [] (StringBuilder()) current + |> List.rev + |> Array.ofList, + lineNumber + + yield! readLines (lineNumber + 1) } readLines 0 diff --git a/src/FSharp.Data.Runtime.Utilities/NameUtils.fs b/src/FSharp.Data.Runtime.Utilities/NameUtils.fs index 96cd5236b..724684aa1 100644 --- a/src/FSharp.Data.Runtime.Utilities/NameUtils.fs +++ b/src/FSharp.Data.Runtime.Utilities/NameUtils.fs @@ -52,12 +52,9 @@ let nicePascalName (s: string) = | Upper _ -> consume from true (i + 1) | Lower _ -> consume from false (i + 1) | _ -> - let r1 = struct (from, i) - let r2 = restart (i + 1) - seq { - yield r1 - yield! r2 + yield struct (from, i) + yield! restart (i + 1) } // Consume are letters of the same kind (either all lower or all upper) and consume from takeUpper i = @@ -65,20 +62,14 @@ let nicePascalName (s: string) = | false, Lower _ -> consume from takeUpper (i + 1) | true, Upper _ -> consume from takeUpper (i + 1) | true, Lower _ -> - let r1 = struct (from, (i - 1)) - let r2 = restart (i - 1) - seq { - yield r1 - yield! r2 + yield struct (from, (i - 1)) + yield! restart (i - 1) } | _ -> - let r1 = struct (from, i) - let r2 = restart i - seq { - yield r1 - yield! r2 + yield struct (from, i) + yield! restart i } // Split string into segments and turn them to PascalCase From 820aa86b78b74d23168174924448dc4efb1c6a52 Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Sun, 7 Jul 2024 22:13:44 +0100 Subject: [PATCH 5/5] fantomas again --- src/FSharp.Data.Csv.Core/CsvRuntime.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FSharp.Data.Csv.Core/CsvRuntime.fs b/src/FSharp.Data.Csv.Core/CsvRuntime.fs index cce4072da..c3ccbfd17 100644 --- a/src/FSharp.Data.Csv.Core/CsvRuntime.fs +++ b/src/FSharp.Data.Csv.Core/CsvRuntime.fs @@ -70,7 +70,7 @@ module internal CsvReader = | Char '\n' -> readLines lineNumber | current -> seq { - yield + yield readLine [] (StringBuilder()) current |> List.rev |> Array.ofList,