diff --git a/tests/syntax-tests/highlighted/F#/string.fs b/tests/syntax-tests/highlighted/F#/string.fs new file mode 100644 index 00000000..338b5d60 --- /dev/null +++ b/tests/syntax-tests/highlighted/F#/string.fs @@ -0,0 +1,182 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Core + + open System + open System.Text + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + open Microsoft.FSharp.Core.Operators + open Microsoft.FSharp.Core.Operators.Checked + open Microsoft.FSharp.Collections + open Microsoft.FSharp.Primitives.Basics + + [] + [] + module String = + [] + /// LOH threshold is calculated from Internal.Utilities.Library.LOH_SIZE_THRESHOLD_BYTES, + /// and is equal to 80_000 / sizeof + let LOH_CHAR_THRESHOLD = 40_000 + + [] + let length (str:string) = if isNull str then 0 else str.Length + + [] + let concat sep (strings : seq<string>) =  + + let concatArray sep (strings: string []) = + match length sep with + | 0 -> String.Concat strings + // following line should be used when this overload becomes part of .NET Standard (it's only in .NET Core) + //| 1 -> String.Join(sep.[0], strings, 0, strings.Length) + | _ -> String.Join(sep, strings, 0, strings.Length) + + match strings with + | :? array<string> as arr ->  + concatArray sep arr + + | :? list<string> as lst ->  + lst  + |> List.toArray  + |> concatArray sep + + | _ -> + String.Join(sep, strings) + + [] + let iter (action : (char -> unit)) (str:string) = + if not (String.IsNullOrEmpty str) then + for i = 0 to str.Length - 1 do + action str.[i]  + + [] + let iteri action (str:string) = + if not (String.IsNullOrEmpty str) then + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(action) + for i = 0 to str.Length - 1 do + f.Invoke(i, str.[i])  + + [] + let map (mapping: char -> char) (str:string) = + if String.IsNullOrEmpty str then + String.Empty + else + let result = str.ToCharArray() + let mutable i = 0 + for c in result do + result.[i] <- mapping c + i <- i + 1 + + new String(result) + + [] + let mapi (mapping: int -> char -> char) (str:string) = + let len = length str + if len = 0 then  + String.Empty + else + let result = str.ToCharArray() + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(mapping) + + let mutable i = 0 + while i < len do + result.[i] <- f.Invoke(i, result.[i]) + i <- i + 1 + + new String(result) + + [] + let filter (predicate: char -> bool) (str:string) = + let len = length str + + if len = 0 then  + String.Empty + + elif len > LOH_CHAR_THRESHOLD then + // By using SB here, which is twice slower than the optimized path, we prevent LOH allocations  + // and 'stop the world' collections if the filtering results in smaller strings. + // We also don't pre-allocate SB here, to allow for less mem pressure when filter result is small. + let res = StringBuilder() + str |> iter (fun c -> if predicate c then res.Append c |> ignore) + res.ToString() + + else + // Must do it this way, since array.fs is not yet in scope, but this is safe + let target = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked len + let mutable i = 0 + for c in str do + if predicate c then  + target.[i] <- c + i <- i + 1 + + String(target, 0, i) + + [] + let collect (mapping: char -> string) (str:string) = + if String.IsNullOrEmpty str then + String.Empty + else + let res = StringBuilder str.Length + str |> iter (fun c -> res.Append(mapping c) |> ignore) + res.ToString() + + [] + let init (count:int) (initializer: int-> string) = + if count < 0 then invalidArgInputMustBeNonNegative "count" count + let res = StringBuilder count + for i = 0 to count - 1 do  + res.Append(initializer i) |> ignore + res.ToString() + + [] + let replicate (count:int) (str:string) = + if count < 0 then invalidArgInputMustBeNonNegative "count" count + + let len = length str + if len = 0 || count = 0 then  + String.Empty + + elif len = 1 then + new String(str.[0], count) + + elif count <= 4 then + match count with + | 1 -> str + | 2 -> String.Concat(str, str) + | 3 -> String.Concat(str, str, str) + | _ -> String.Concat(str, str, str, str) + + else + // Using the primitive, because array.fs is not yet in scope. It's safe: both len and count are positive. + let target = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked (len * count) + let source = str.ToCharArray() + + // O(log(n)) performance loop: + // Copy first string, then keep copying what we already copied  + // (i.e., doubling it) until we reach or pass the halfway point + Array.Copy(source, 0, target, 0, len) + let mutable i = len + while i * 2 < target.Length do + Array.Copy(target, 0, target, i, i) + i <- i * 2 + + // finally, copy the remain half, or less-then half + Array.Copy(target, 0, target, i, target.Length - i) + new String(target) + + + [] + let forall predicate (str:string) = + if String.IsNullOrEmpty str then + true + else + let rec check i = (i >= str.Length) || (predicate str.[i] && check (i+1))  + check 0 + + [] + let exists predicate (str:string) = + if String.IsNullOrEmpty str then + false + else + let rec check i = (i < str.Length) && (predicate str.[i] || check (i+1))  + check 0  diff --git a/tests/syntax-tests/source/F#/LICENSE.md b/tests/syntax-tests/source/F#/LICENSE.md new file mode 100644 index 00000000..7473c821 --- /dev/null +++ b/tests/syntax-tests/source/F#/LICENSE.md @@ -0,0 +1,27 @@ +The `string.fs` file has been added from https://github.com/dotnet/fsharp under the following license: + +```text +The MIT License (MIT) + +Copyright (c) Microsoft Corporation. +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +``` diff --git a/tests/syntax-tests/source/F#/string.fs b/tests/syntax-tests/source/F#/string.fs new file mode 100644 index 00000000..37e8fcd7 --- /dev/null +++ b/tests/syntax-tests/source/F#/string.fs @@ -0,0 +1,182 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Core + + open System + open System.Text + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + open Microsoft.FSharp.Core.Operators + open Microsoft.FSharp.Core.Operators.Checked + open Microsoft.FSharp.Collections + open Microsoft.FSharp.Primitives.Basics + + [] + [] + module String = + [] + /// LOH threshold is calculated from Internal.Utilities.Library.LOH_SIZE_THRESHOLD_BYTES, + /// and is equal to 80_000 / sizeof + let LOH_CHAR_THRESHOLD = 40_000 + + [] + let length (str:string) = if isNull str then 0 else str.Length + + [] + let concat sep (strings : seq) = + + let concatArray sep (strings: string []) = + match length sep with + | 0 -> String.Concat strings + // following line should be used when this overload becomes part of .NET Standard (it's only in .NET Core) + //| 1 -> String.Join(sep.[0], strings, 0, strings.Length) + | _ -> String.Join(sep, strings, 0, strings.Length) + + match strings with + | :? array as arr -> + concatArray sep arr + + | :? list as lst -> + lst + |> List.toArray + |> concatArray sep + + | _ -> + String.Join(sep, strings) + + [] + let iter (action : (char -> unit)) (str:string) = + if not (String.IsNullOrEmpty str) then + for i = 0 to str.Length - 1 do + action str.[i] + + [] + let iteri action (str:string) = + if not (String.IsNullOrEmpty str) then + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(action) + for i = 0 to str.Length - 1 do + f.Invoke(i, str.[i]) + + [] + let map (mapping: char -> char) (str:string) = + if String.IsNullOrEmpty str then + String.Empty + else + let result = str.ToCharArray() + let mutable i = 0 + for c in result do + result.[i] <- mapping c + i <- i + 1 + + new String(result) + + [] + let mapi (mapping: int -> char -> char) (str:string) = + let len = length str + if len = 0 then + String.Empty + else + let result = str.ToCharArray() + let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(mapping) + + let mutable i = 0 + while i < len do + result.[i] <- f.Invoke(i, result.[i]) + i <- i + 1 + + new String(result) + + [] + let filter (predicate: char -> bool) (str:string) = + let len = length str + + if len = 0 then + String.Empty + + elif len > LOH_CHAR_THRESHOLD then + // By using SB here, which is twice slower than the optimized path, we prevent LOH allocations + // and 'stop the world' collections if the filtering results in smaller strings. + // We also don't pre-allocate SB here, to allow for less mem pressure when filter result is small. + let res = StringBuilder() + str |> iter (fun c -> if predicate c then res.Append c |> ignore) + res.ToString() + + else + // Must do it this way, since array.fs is not yet in scope, but this is safe + let target = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked len + let mutable i = 0 + for c in str do + if predicate c then + target.[i] <- c + i <- i + 1 + + String(target, 0, i) + + [] + let collect (mapping: char -> string) (str:string) = + if String.IsNullOrEmpty str then + String.Empty + else + let res = StringBuilder str.Length + str |> iter (fun c -> res.Append(mapping c) |> ignore) + res.ToString() + + [] + let init (count:int) (initializer: int-> string) = + if count < 0 then invalidArgInputMustBeNonNegative "count" count + let res = StringBuilder count + for i = 0 to count - 1 do + res.Append(initializer i) |> ignore + res.ToString() + + [] + let replicate (count:int) (str:string) = + if count < 0 then invalidArgInputMustBeNonNegative "count" count + + let len = length str + if len = 0 || count = 0 then + String.Empty + + elif len = 1 then + new String(str.[0], count) + + elif count <= 4 then + match count with + | 1 -> str + | 2 -> String.Concat(str, str) + | 3 -> String.Concat(str, str, str) + | _ -> String.Concat(str, str, str, str) + + else + // Using the primitive, because array.fs is not yet in scope. It's safe: both len and count are positive. + let target = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked (len * count) + let source = str.ToCharArray() + + // O(log(n)) performance loop: + // Copy first string, then keep copying what we already copied + // (i.e., doubling it) until we reach or pass the halfway point + Array.Copy(source, 0, target, 0, len) + let mutable i = len + while i * 2 < target.Length do + Array.Copy(target, 0, target, i, i) + i <- i * 2 + + // finally, copy the remain half, or less-then half + Array.Copy(target, 0, target, i, target.Length - i) + new String(target) + + + [] + let forall predicate (str:string) = + if String.IsNullOrEmpty str then + true + else + let rec check i = (i >= str.Length) || (predicate str.[i] && check (i+1)) + check 0 + + [] + let exists predicate (str:string) = + if String.IsNullOrEmpty str then + false + else + let rec check i = (i < str.Length) && (predicate str.[i] || check (i+1)) + check 0