From a52d9e7eec9b6cad385ffb0f362b79fee8c6226e Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Sat, 18 May 2019 16:27:03 +0800 Subject: [PATCH 01/19] minor touch: typo --- src/fsharp/pars.fsy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 453e5c56342..4c19b7682d2 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -4980,7 +4980,7 @@ colonOrEquals: | COLON { mlCompatWarning (FSComp.SR.parsSyntaxModuleSigEndDeprecated()) (lhs parseState); } | EQUALS { } -/* A literal string or a string fromm a keyword like __SOURCE_FILE__ */ +/* A literal string or a string from a keyword like __SOURCE_FILE__ */ stringOrKeywordString: | STRING { $1 } | KEYWORD_STRING { $1 } From 19b33f8b5405d566c85d8e7de4982a152ec95384 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Mon, 20 May 2019 19:35:18 +0800 Subject: [PATCH 02/19] checkpoint. --- src/fsharp/.vim/coc-settings.json | 3 +++ src/fsharp/FSharp.Core/printf.fs | 27 +++++++++++++++++++-------- src/fsharp/xlf/FSComp.txt.es.xlf | 2 +- 3 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 src/fsharp/.vim/coc-settings.json diff --git a/src/fsharp/.vim/coc-settings.json b/src/fsharp/.vim/coc-settings.json new file mode 100644 index 00000000000..3e75c72cc7a --- /dev/null +++ b/src/fsharp/.vim/coc-settings.json @@ -0,0 +1,3 @@ +{ + "fsharp.project.objdirectory": "../../artifacts/obj/" +} diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 141c9752da9..d85cb0fcf9f 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -3,12 +3,20 @@ namespace Microsoft.FSharp.Core type PrintfFormat<'Printer,'State,'Residue,'Result>(value:string) = - member x.Value = value + + internal new(value, caps) as this = + PrintfFormat<_,_,_,_>(value) + then this.Captures <- caps + member x.Value = value + member val internal Captures: obj[] = [||] with get, set override __.ToString() = value type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>(value:string) = inherit PrintfFormat<'Printer,'State,'Residue,'Result>(value) + internal new(value, caps) as this = + PrintfFormat<_,_,_,_,_>(value) + then this.Captures <- caps type Format<'Printer,'State,'Residue,'Result> = PrintfFormat<'Printer,'State,'Residue,'Result> type Format<'Printer,'State,'Residue,'Result,'Tuple> = PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple> @@ -1406,7 +1414,7 @@ module internal PrintfImpl = else buildPlainFinal(plainArgs, plainTypes) - let rec parseFromFormatSpecifier (prefix: string) (s: string) (funcTy: Type) i: int = + let rec parseFromFormatSpecifier (prefix: string) (s: string) (funcTy: Type) (i: int) (caps: obj[]) = if i >= s.Length then 0 else @@ -1430,15 +1438,16 @@ module internal PrintfImpl = else 2 else 1 + if spec.TypeChar = '{' then [||] // immediate specifier takes no args + else + let n = if spec.TypeChar = '%' then n - 1 else n - System.Diagnostics.Debug.Assert(n <> 0, "n <> 0") - extractCurriedArguments funcTy n let retTy = argTys.[argTys.Length - 1] - let numberOfArgs = parseFromFormatSpecifier suffix s retTy next + let numberOfArgs = parseFromFormatSpecifier suffix s retTy next caps if spec.TypeChar = 'a' || spec.TypeChar = 't' || spec.IsStarWidth || spec.IsStarPrecision then if numberOfArgs = ContinuationOnStack then @@ -1498,7 +1507,7 @@ module internal PrintfImpl = else numberOfArgs + 1 - let parseFormatString (s: string) (funcTy: System.Type) : obj = + let parseFormatString (s: string) (funcTy: System.Type) (caps: obj[]): obj = optimizedArgCount <- 0 let prefixPos, prefix = FormatString.findNextFormatSpecifier s 0 if prefixPos = s.Length then @@ -1508,7 +1517,7 @@ module internal PrintfImpl = env.Finish() ) else - let n = parseFromFormatSpecifier prefix s funcTy prefixPos + let n = parseFromFormatSpecifier prefix s funcTy prefixPos caps if n = ContinuationOnStack || n = 0 then builderStack.PopValueUnsafe() @@ -1516,7 +1525,9 @@ module internal PrintfImpl = buildPlain n prefix member __.Build<'T>(s: string) : PrintfFactory<'S, 'Re, 'Res, 'T> * int = - parseFormatString s typeof<'T> :?> _, (2 * count + 1) - optimizedArgCount // second component is used in SprintfEnv as value for internal buffer + parseFormatString s typeof<'T> [||] :?> _, (2 * count + 1) - optimizedArgCount // second component is used in SprintfEnv as value for internal buffer + member __.Build<'T>(s: string, caps: obj[]) : PrintfFactory<'S, 'Re, 'Res, 'T> * int = + parseFormatString s typeof<'T> caps :?> _, (2 * count + 1) - optimizedArgCount /// Type of element that is stored in cache /// Pair: factory for the printer + number of text blocks that printer will produce (used to preallocate buffers) diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index f3c85065ce9..9709b6c3abf 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -109,7 +109,7 @@ All branches of a pattern match expression must return values of the same type as the first branch, which here is '{0}'. This branch returns a value of type '{1}'. - Todas las ramas de una expresión de coincidencia de patrón deben devolver valores del mismo tipo. La primera rama devolvió un valor de tipo "{0}", pero esta rama devolvió un valor de tipo "\{1 \}". + All branches of a pattern match expression must return values of the same type as the first branch, which here is '{0}'. This branch returns a value of type '{1}'. From f3fa739ffee9fbc72299e99f16f60e3813b8b47e Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Tue, 21 May 2019 18:12:15 +0800 Subject: [PATCH 03/19] captures are put in the envs. prepare to build specializers for capture indices --- src/fsharp/FSharp.Core/printf.fs | 120 +++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 36 deletions(-) diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index d85cb0fcf9f..78bbf6cdbc0 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -9,7 +9,7 @@ type PrintfFormat<'Printer,'State,'Residue,'Result>(value:string) = then this.Captures <- caps member x.Value = value - member val internal Captures: obj[] = [||] with get, set + member val internal Captures: obj[] = Unchecked.defaultof with get, set override __.ToString() = value type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>(value:string) = @@ -91,6 +91,7 @@ module internal PrintfImpl = Precision: int Width: int Flags: FormatFlags + Capture: int option } member this.IsStarPrecision = this.Precision = StarValue member this.IsPrecisionSpecified = this.Precision <> NotSpecifiedValue @@ -143,6 +144,36 @@ module internal PrintfImpl = let parseTypeChar (s: string) i = s.[i], (i + 1) + + let rec parseFormatSpecifier (s:string) (i:int) = + + System.Diagnostics.Debug.Assert(s.[i] = '%', "s.[i] = '%'") + + let isImm, i = if s.[i+1] = '{' + then true, i+1 + else false, i + + if isImm then + let rbrace = s.IndexOf('}', i) + if rbrace < 0 then raise (ArgumentException("invalid immediate specifier")) + let colon = s.IndexOf(':', i) + if colon < 0 || colon > rbrace + then + // defaults to %A + let cap, i = intFromString s i + { TypeChar = 'A'; Precision = NotSpecifiedValue; Flags = FormatFlags.None; Width = NotSpecifiedValue; Capture = Some cap }, i + else + let spec, i = parseFormatSpecifier s i + System.Diagnostics.Debug.Assert((i = colon), "i = colon") + let cap, i = intFromString s (i + 1) + { spec with Capture = Some cap }, i + else + let flags, i = parseFlags s (i + 1) + let width, i = parseWidth s i + let precision, i = parsePrecision s i + let typeChar, i = parseTypeChar s i + { TypeChar = typeChar; Precision = precision; Flags = flags; Width = width; Capture = None }, i + let findNextFormatSpecifier (s: string) i = let rec go i (buf: Text.StringBuilder) = @@ -174,7 +205,8 @@ module internal PrintfImpl = [] type PrintfEnv<'State, 'Residue, 'Result> = val State: 'State - new(s: 'State) = { State = s } + val Captures: obj[] + new(s: 'State, caps: obj[]) = { State = s; Captures = caps } abstract Finish: unit -> 'Result abstract Write: string -> unit abstract WriteT: 'Residue -> unit @@ -222,9 +254,10 @@ module internal PrintfImpl = [] let MaxArgumentsInSpecialization = 5 - /// Specializations are created via factory methods. These methods accepts 2 kinds of arguments + /// Specializations are created via factory methods. These methods accepts 3 kinds of arguments /// - parts of format string that corresponds to raw text /// - functions that can transform collected values to strings + /// - captured immediate indices /// basic shape of the signature of specialization /// + + + ... + type Specializations<'State, 'Residue, 'Result> private ()= @@ -241,6 +274,18 @@ module internal PrintfImpl = ) ) + static member Final1C<'A> + ( + s0, conv1, s1, cap: 'A + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun () -> + let env = env() + Utils.Write(env, s0, (conv1 cap), s1) + env.Finish() + ) + ) + static member FinalFastEnd1<'A> ( s0, conv1 @@ -1186,7 +1231,7 @@ module internal PrintfImpl = raise (ArgumentException(SR.GetString(SR.printfBadFormatSpecifier))) let extractCurriedArguments (ty: Type) n = - System.Diagnostics.Debug.Assert(n = 1 || n = 2 || n = 3, "n = 1 || n = 2 || n = 3") + System.Diagnostics.Debug.Assert(n = 0 || n = 1 || n = 2 || n = 3, "n = 0 || n = 1 || n = 2 || n = 3") let buf = Array.zeroCreate (n + 1) let rec go (ty: Type) i = if i < n then @@ -1223,6 +1268,7 @@ module internal PrintfImpl = member __.PopContinuationWithType() = System.Diagnostics.Debug.Assert(args.Count = 1, "args.Count = 1") System.Diagnostics.Debug.Assert(types.Count = 1, "types.Count = 1") + // XXX ContinuationOnStack not updated here? let cont = args.Pop() let contTy = types.Pop() @@ -1241,6 +1287,7 @@ module internal PrintfImpl = "incorrect type" ) + // XXX ContinuationOnStack not updated here? this.PushArgumentWithType(cont, contTy) member __.PushArgument(value: obj) = @@ -1419,15 +1466,10 @@ module internal PrintfImpl = if i >= s.Length then 0 else - System.Diagnostics.Debug.Assert(s.[i] = '%', "s.[i] = '%'") count <- count + 1 - let flags, i = FormatString.parseFlags s (i + 1) - let width, i = FormatString.parseWidth s i - let precision, i = FormatString.parsePrecision s i - let typeChar, i = FormatString.parseTypeChar s i - let spec = { TypeChar = typeChar; Precision = precision; Flags = flags; Width = width} - + let spec, i = FormatString.parseFormatSpecifier s i + let isImm, imm = spec.Capture.IsSome, Option.defaultValue -1 spec.Capture let next, suffix = FormatString.findNextFormatSpecifier s i let argTys = @@ -1438,12 +1480,18 @@ module internal PrintfImpl = else 2 else 1 - if spec.TypeChar = '{' then [||] // immediate specifier takes no args - else + // immediate spec doesn't get payload from arg + let n = if isImm then n - 1 else n - let n = if spec.TypeChar = '%' then n - 1 else n - System.Diagnostics.Debug.Assert(n <> 0, "n <> 0") - extractCurriedArguments funcTy n + System.Diagnostics.Debug.Assert(n >= 0, "n >= 0") + let argTys = extractCurriedArguments funcTy n + if isImm + // insert captured value type back into argTys + then Array.ofSeq <| seq { + if argTys.Length > 1 then yield! argTys.[0..argTys.Length-2] + yield caps.[imm].GetType() + yield argTys.[argTys.Length-1] } + else argTys let retTy = argTys.[argTys.Length - 1] @@ -1525,7 +1573,7 @@ module internal PrintfImpl = buildPlain n prefix member __.Build<'T>(s: string) : PrintfFactory<'S, 'Re, 'Res, 'T> * int = - parseFormatString s typeof<'T> [||] :?> _, (2 * count + 1) - optimizedArgCount // second component is used in SprintfEnv as value for internal buffer + parseFormatString s (typeof<'T>) (Unchecked.defaultof) :?> _, (2 * count + 1) - optimizedArgCount // second component is used in SprintfEnv as value for internal buffer member __.Build<'T>(s: string, caps: obj[]) : PrintfFactory<'S, 'Re, 'Res, 'T> * int = parseFormatString s typeof<'T> caps :?> _, (2 * count + 1) - optimizedArgCount @@ -1556,8 +1604,8 @@ module internal PrintfImpl = Cache<'T, 'State, 'Residue, 'Result>.last <- (key.Value, v) v - type StringPrintfEnv<'Result>(k, n) = - inherit PrintfEnv(()) + type StringPrintfEnv<'Result>(k, n, caps) = + inherit PrintfEnv((), caps) let buf: string[] = Array.zeroCreate n let mutable ptr = 0 @@ -1570,8 +1618,8 @@ module internal PrintfImpl = buf.[ptr] <- s ptr <- ptr + 1 - type SmallStringPrintfEnv<'Result>(k) = - inherit PrintfEnv(()) + type SmallStringPrintfEnv<'Result>(k, caps) = + inherit PrintfEnv((), caps) let mutable c = null @@ -1579,21 +1627,21 @@ module internal PrintfImpl = override __.Write(s: string) = if isNull c then c <- s else c <- c + s override __.WriteT s = if isNull c then c <- s else c <- c + s - type StringBuilderPrintfEnv<'Result>(k, buf) = - inherit PrintfEnv(buf) + type StringBuilderPrintfEnv<'Result>(k, buf, caps) = + inherit PrintfEnv(buf, caps) override __.Finish() : 'Result = k () override __.Write(s: string) = ignore(buf.Append s) override __.WriteT(()) = () - type TextWriterPrintfEnv<'Result>(k, tw: IO.TextWriter) = - inherit PrintfEnv(tw) + type TextWriterPrintfEnv<'Result>(k, tw: IO.TextWriter, caps) = + inherit PrintfEnv(tw, caps) override __.Finish() : 'Result = k() override __.Write(s: string) = tw.Write s override __.WriteT(()) = () let inline doPrintf fmt f = let formatter, n = Cache<_, _, _, _>.Get fmt - let env() = f n + let env() = f n fmt.Captures formatter env [] @@ -1613,20 +1661,20 @@ module Printf = [] let ksprintf continuation (format: StringFormat<'T, 'Result>) : 'T = - doPrintf format (fun n -> + doPrintf format (fun n caps -> if n <= 2 then - SmallStringPrintfEnv continuation :> PrintfEnv<_, _, _> + SmallStringPrintfEnv(continuation, caps) :> PrintfEnv<_, _, _> else - StringPrintfEnv(continuation, n) :> PrintfEnv<_, _, _> + StringPrintfEnv(continuation, n, caps) :> PrintfEnv<_, _, _> ) [] let sprintf (format: StringFormat<'T>) = - doPrintf format (fun n -> + doPrintf format (fun n caps -> if n <= 2 then - SmallStringPrintfEnv id :> PrintfEnv<_, _, _> + SmallStringPrintfEnv(id, caps) :> PrintfEnv<_, _, _> else - StringPrintfEnv(id, n) :> PrintfEnv<_, _, _> + StringPrintfEnv(id, n, caps) :> PrintfEnv<_, _, _> ) [] @@ -1634,14 +1682,14 @@ module Printf = [] let kbprintf continuation (builder: StringBuilder) format = - doPrintf format (fun _ -> - StringBuilderPrintfEnv(continuation, builder) :> PrintfEnv<_, _, _> + doPrintf format (fun _ caps -> + StringBuilderPrintfEnv(continuation, builder, caps) :> PrintfEnv<_, _, _> ) [] let kfprintf continuation textWriter format = - doPrintf format (fun _ -> - TextWriterPrintfEnv(continuation, textWriter) :> PrintfEnv<_, _, _> + doPrintf format (fun _ caps -> + TextWriterPrintfEnv(continuation, textWriter, caps) :> PrintfEnv<_, _, _> ) [] From 3fc2b79ad108587b0800c7a4b2bfe81a26dc96a8 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Tue, 21 May 2019 18:46:34 +0800 Subject: [PATCH 04/19] findNextFormatSpecifier also needs to consider '{' --- src/fsharp/FSharp.Core/printf.fs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 78bbf6cdbc0..25de7ad0afd 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -25,13 +25,13 @@ module internal PrintfImpl = /// Basic idea of implementation: /// Every Printf.* family should returns curried function that collects arguments and then somehow prints them. - /// Idea - instead of building functions on fly argument by argument we instead introduce some predefined parts and then construct functions from these parts + /// Idea - instead of building functions on the fly argument by argument we instead introduce some predefined parts and then construct functions from these parts /// Parts include: /// Plain ones: /// 1. Final pieces (1..5) - set of functions with arguments number 1..5. /// Primary characteristic - these functions produce final result of the *printf* operation /// 2. Chained pieces (1..5) - set of functions with arguments number 1..5. - /// Primary characteristic - these functions doesn not produce final result by itself, instead they tailed with some another piece (chained or final). + /// Primary characteristic - these functions do not produce final result by itself, instead they are tailed with another piece (chained or final). /// Plain parts correspond to simple format specifiers (that are projected to just one parameter of the function, say %d or %s). However we also have /// format specifiers that can be projected to more than one argument (i.e %a, %t or any simple format specified with * width or precision). /// For them we add special cases (both chained and final to denote that they can either return value themselves or continue with some other piece) @@ -183,6 +183,9 @@ module internal PrintfImpl = let c = s.[i] if c = '%' then if i + 1 < s.Length then + if s.[i+1] = '{' + then i, buf.ToString() + else let _, i1 = parseFlags s (i + 1) let w, i2 = parseWidth s i1 let p, i3 = parsePrecision s i2 From 30b8147fad89ca00ded188a75b7bf3712adf4848 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Tue, 21 May 2019 23:07:29 +0800 Subject: [PATCH 05/19] add comments --- src/fsharp/FSharp.Core/printf.fs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 25de7ad0afd..356c9649310 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -44,6 +44,10 @@ module internal PrintfImpl = /// with just one reflection call /// 2. we can make combinable parts independent from particular printf implementation. Thus final result can be cached and shared. /// i.e when first call to printf "%s %s" will trigger creation of the specialization. Subsequent calls will pick existing specialization + /// Note, immediate specifiers will break the aggregation of arguments. For example: + /// - function that corresponds to %s%s%{123}%s%s%s (string -> string -> string -> string -> string -> T) will have to be broken into + /// three parts: chained3 -> chainedImm1 -> final2 + /// TODO shall we also aggregate the immediates? open System open System.IO open System.Text From 52648bf383dcad969892e7eeaa6a32a72c853033 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Tue, 18 Jun 2019 01:54:03 +0800 Subject: [PATCH 06/19] checkpoint. --- src/fsharp/FSharp.Core/.vim/coc-settings.json | 64 +++++++++++++++++++ src/fsharp/FSharp.Core/printf.fs | 59 +++++++++-------- 2 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 src/fsharp/FSharp.Core/.vim/coc-settings.json diff --git a/src/fsharp/FSharp.Core/.vim/coc-settings.json b/src/fsharp/FSharp.Core/.vim/coc-settings.json new file mode 100644 index 00000000000..7b3d6c3985b --- /dev/null +++ b/src/fsharp/FSharp.Core/.vim/coc-settings.json @@ -0,0 +1,64 @@ +{ + "fsharp.codelens.references": true, + "fsharp.project.otherFlags": [ + "--warnon:1182", + "--compiling-fslib", + "--compiling-fslib-40", + "--maxerrors:20", + "--extraoptimizationloops:1", + "--tailcalls+", + "--deterministic+", + "--target:library", + "--fullpaths", + "--flaterrors", + "--highentropyva+", + "--targetprofile:netcore", + "--simpleresolution", + "-g", + "--debug:portable", + "--noframework", + "--define:TRACE", + "--define:FSHARP_CORE", + "--define:DEBUG", + "--define:NETSTANDARD", + "--define:FX_NO_APP_DOMAINS", + "--define:FX_NO_ARRAY_LONG_LENGTH", + "--define:FX_NO_BEGINEND_READWRITE", + "--define:FX_NO_BINARY_SERIALIZATION", + "--define:FX_NO_CONVERTER", + "--define:FX_NO_DEFAULT_DEPENDENCY_TYPE", + "--define:FX_NO_CORHOST_SIGNER", + "--define:FX_NO_EVENTWAITHANDLE_IDISPOSABLE", + "--define:FX_NO_EXIT_CONTEXT_FLAGS", + "--define:FX_NO_LINKEDRESOURCES", + "--define:FX_NO_PARAMETERIZED_THREAD_START", + "--define:FX_NO_PDB_READER", + "--define:FX_NO_PDB_WRITER", + "--define:FX_NO_REFLECTION_MODULE_HANDLES", + "--define:FX_NO_REFLECTION_ONLY", + "--define:FX_NO_RUNTIMEENVIRONMENT", + "--define:FX_NO_SECURITY_PERMISSIONS", + "--define:FX_NO_SERVERCODEPAGES", + "--define:FX_NO_SYMBOLSTORE", + "--define:FX_NO_SYSTEM_CONFIGURATION", + "--define:FX_NO_THREAD", + "--define:FX_NO_THREADABORT", + "--define:FX_NO_WAITONE_MILLISECONDS", + "--define:FX_NO_WEB_CLIENT", + "--define:FX_NO_WIN_REGISTRY", + "--define:FX_NO_WINFORMS", + "--define:FX_NO_INDENTED_TEXT_WRITER", + "--define:FX_REDUCED_EXCEPTIONS", + "--define:FX_RESHAPED_REFEMIT", + "--define:FX_RESHAPED_GLOBALIZATION", + "--define:FX_RESHAPED_REFLECTION", + "--define:FX_RESHAPED_MSBUILD", + "--define:NETSTANDARD", + "--define:NETSTANDARD1_6", + //"--keyfile:C:\Users\Yatao\.nuget\packages\microsoft.dotnet.arcade.sdk\1.0.0-beta.19264.13\tools\snk/MSFT.snk + //"--publicsign+ + "--optimize-", + //"--resource:C:\Users\Yatao\git\visualfsharp\artifacts\obj\FSharp.Core\Debug\netstandard1.6\FSCore.resources + ], + "fsharp.project.includeCompileBefore": true +} diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 356c9649310..ba89234d37d 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -10,6 +10,9 @@ type PrintfFormat<'Printer,'State,'Residue,'Result>(value:string) = member x.Value = value member val internal Captures: obj[] = Unchecked.defaultof with get, set + member x.GetCaptureTypes() = + if System.Object.ReferenceEquals(x.Captures, null) then [||] + else Microsoft.FSharp.Collections.Array.map (fun (c: obj) -> c.GetType()) x.Captures override __.ToString() = value type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>(value:string) = @@ -101,16 +104,18 @@ module internal PrintfImpl = member this.IsPrecisionSpecified = this.Precision <> NotSpecifiedValue member this.IsStarWidth = this.Width = StarValue member this.IsWidthSpecified = this.Width <> NotSpecifiedValue + member this.HasCapture = this.Capture.IsSome override this.ToString() = let valueOf n = match n with StarValue -> "*" | NotSpecifiedValue -> "-" | n -> n.ToString() System.String.Format ( - "'{0}', Precision={1}, Width={2}, Flags={3}", + "'{0}', Precision={1}, Width={2}, Flags={3}, Captures={4}", this.TypeChar, (valueOf this.Precision), (valueOf this.Width), - this.Flags + this.Flags, + this.Capture ) /// Set of helpers to parse format string @@ -151,7 +156,8 @@ module internal PrintfImpl = let rec parseFormatSpecifier (s:string) (i:int) = - System.Diagnostics.Debug.Assert(s.[i] = '%', "s.[i] = '%'") + // when called recursively for %{nn:FFF} i could point to ':' + System.Diagnostics.Debug.Assert(s.[i] = '%' || s.[i] = ':', "s.[i] = '%' || s.[i] = ':'") let isImm, i = if s.[i+1] = '{' then true, i+1 @@ -213,6 +219,7 @@ module internal PrintfImpl = type PrintfEnv<'State, 'Residue, 'Result> = val State: 'State val Captures: obj[] + new(s: 'State) = { State = s; Captures = Unchecked.defaultof<_> } new(s: 'State, caps: obj[]) = { State = s; Captures = caps } abstract Finish: unit -> 'Result abstract Write: string -> unit @@ -283,12 +290,12 @@ module internal PrintfImpl = static member Final1C<'A> ( - s0, conv1, s1, cap: 'A + s0, cap1: int, conv1, s1 ) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun () -> let env = env() - Utils.Write(env, s0, (conv1 cap), s1) + Utils.Write(env, s0, (conv1 env.Captures.[cap1]), s1) env.Finish() ) ) @@ -1447,6 +1454,9 @@ module internal PrintfImpl = let builderStack = PrintfBuilderStack() + // XXX currently ContinuationOnStack is not updated anywhere. + // marking it a constant. + [] let ContinuationOnStack = -1 let buildPlain numberOfArgs prefix = @@ -1468,7 +1478,7 @@ module internal PrintfImpl = else buildPlainFinal(plainArgs, plainTypes) - let rec parseFromFormatSpecifier (prefix: string) (s: string) (funcTy: Type) (i: int) (caps: obj[]) = + let rec parseFromFormatSpecifier (prefix: string) (s: string) (funcTy: Type) (i: int) (cTy: Type[]) = if i >= s.Length then 0 else @@ -1491,18 +1501,12 @@ module internal PrintfImpl = let n = if isImm then n - 1 else n System.Diagnostics.Debug.Assert(n >= 0, "n >= 0") - let argTys = extractCurriedArguments funcTy n - if isImm - // insert captured value type back into argTys - then Array.ofSeq <| seq { - if argTys.Length > 1 then yield! argTys.[0..argTys.Length-2] - yield caps.[imm].GetType() - yield argTys.[argTys.Length-1] } - else argTys + extractCurriedArguments funcTy n + // curry on let retTy = argTys.[argTys.Length - 1] - let numberOfArgs = parseFromFormatSpecifier suffix s retTy next caps + let numberOfArgs = parseFromFormatSpecifier suffix s retTy next cTy if spec.TypeChar = 'a' || spec.TypeChar = 't' || spec.IsStarWidth || spec.IsStarPrecision then if numberOfArgs = ContinuationOnStack then @@ -1546,11 +1550,18 @@ module internal PrintfImpl = ContinuationOnStack else + // n = 0 || n = 1 if numberOfArgs = ContinuationOnStack then let idx = argTys.Length - 2 builderStack.PushArgument suffix builderStack.PushArgumentWithType((getValueConverter argTys.[idx] spec), argTys.[idx]) 1 + elif spec.HasCapture then + let capture = spec.Capture.Value + builderStack.PushArgument suffix + builderStack.PushArgumentWithType(getValueConverter cTy.[capture] spec, cTy.[capture]) + // TODO figure out how exactly the build stack works... + 0 else builderStack.PushArgument suffix builderStack.PushArgumentWithType((getValueConverter argTys.[0] spec), argTys.[0]) @@ -1562,7 +1573,7 @@ module internal PrintfImpl = else numberOfArgs + 1 - let parseFormatString (s: string) (funcTy: System.Type) (caps: obj[]): obj = + let parseFormatString (s: string) (funcTy: System.Type) (cTy: System.Type[]) : obj = optimizedArgCount <- 0 let prefixPos, prefix = FormatString.findNextFormatSpecifier s 0 if prefixPos = s.Length then @@ -1572,17 +1583,15 @@ module internal PrintfImpl = env.Finish() ) else - let n = parseFromFormatSpecifier prefix s funcTy prefixPos caps + let n = parseFromFormatSpecifier prefix s funcTy prefixPos cTy if n = ContinuationOnStack || n = 0 then builderStack.PopValueUnsafe() else buildPlain n prefix - member __.Build<'T>(s: string) : PrintfFactory<'S, 'Re, 'Res, 'T> * int = - parseFormatString s (typeof<'T>) (Unchecked.defaultof) :?> _, (2 * count + 1) - optimizedArgCount // second component is used in SprintfEnv as value for internal buffer - member __.Build<'T>(s: string, caps: obj[]) : PrintfFactory<'S, 'Re, 'Res, 'T> * int = - parseFormatString s typeof<'T> caps :?> _, (2 * count + 1) - optimizedArgCount + member __.Build<'T>(s: string, cTy: Type[]) : PrintfFactory<'S, 'Re, 'Res, 'T> * int = + parseFormatString s (typeof<'T>) cTy :?> _, (2 * count + 1) - optimizedArgCount // second component is used in SprintfEnv as value for internal buffer /// Type of element that is stored in cache /// Pair: factory for the printer + number of text blocks that printer will produce (used to preallocate buffers) @@ -1593,10 +1602,10 @@ module internal PrintfImpl = /// printf is called in tight loop /// 2nd level is global dictionary that maps format string to the corresponding PrintfFactory type Cache<'T, 'State, 'Residue, 'Result>() = - static let generate fmt = PrintfBuilder<'State, 'Residue, 'Result>().Build<'T>(fmt) - static let mutable map = System.Collections.Concurrent.ConcurrentDictionary>() + static let generate(fmt, capTypes) = PrintfBuilder<'State, 'Residue, 'Result>().Build<'T>(fmt, capTypes) + static let mutable map = System.Collections.Concurrent.ConcurrentDictionary>() static let getOrAddFunc = Func<_, _>(generate) - static let get (key: string) = map.GetOrAdd(key, getOrAddFunc) + static let get(key: string*Type[]) = map.GetOrAdd(key, getOrAddFunc) [] [] @@ -1607,7 +1616,7 @@ module internal PrintfImpl = && key.Value.Equals (fst Cache<'T, 'State, 'Residue, 'Result>.last) then snd Cache<'T, 'State, 'Residue, 'Result>.last else - let v = get key.Value + let v = get(key.Value, key.GetCaptureTypes()) Cache<'T, 'State, 'Residue, 'Result>.last <- (key.Value, v) v From a66933037a05e42000ecc568258ad40bde2b77c5 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Tue, 18 Jun 2019 20:20:54 +0800 Subject: [PATCH 07/19] checkpoint. --- Session.vim | 277 ++++++++++++++++++ src/fsharp/.vim/coc-settings.json | 3 - src/fsharp/FSharp.Core/.vim/coc-settings.json | 2 +- src/fsharp/FSharp.Core/printf.fs | 232 ++++++++++++--- 4 files changed, 466 insertions(+), 48 deletions(-) create mode 100644 Session.vim delete mode 100644 src/fsharp/.vim/coc-settings.json diff --git a/Session.vim b/Session.vim new file mode 100644 index 00000000000..269a5ec030f --- /dev/null +++ b/Session.vim @@ -0,0 +1,277 @@ +let SessionLoad = 1 +let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 +let v:this_session=expand(":p") +silent only +cd ~\git\visualfsharp +if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' + let s:wipebuf = bufnr('%') +endif +set shortmess=aoO +badd +1579 src\fsharp\FSharp.Core\printf.fs +argglobal +silent! argdel * +edit src\fsharp\FSharp.Core\printf.fs +set splitbelow splitright +wincmd _ | wincmd | +split +1wincmd k +wincmd w +set nosplitbelow +set nosplitright +wincmd t +set winminheight=0 +set winheight=1 +set winminwidth=0 +set winwidth=1 +exe '1resize ' . ((&lines * 23 + 25) / 50) +exe '2resize ' . ((&lines * 23 + 25) / 50) +argglobal +setlocal fdm=indent +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=10 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +7 +normal! zo +7 +normal! zo +29 +normal! zo +228 +normal! zo +278 +normal! zo +327 +normal! zo +332 +normal! zo +333 +normal! zo +342 +normal! zo +347 +normal! zo +348 +normal! zo +358 +normal! zo +909 +normal! zo +909 +normal! zc +996 +normal! zo +996 +normal! zc +1006 +normal! zo +1006 +normal! zc +1122 +normal! zo +1122 +normal! zc +1147 +normal! zo +1147 +normal! zc +1162 +normal! zc +1195 +normal! zo +1195 +normal! zc +1245 +normal! zo +1245 +normal! zc +1273 +normal! zc +1283 +normal! zo +1283 +normal! zc +1314 +normal! zo +1314 +normal! zc +1391 +normal! zo +1400 +normal! zo +1418 +normal! zo +1440 +normal! zo +1456 +normal! zo +1479 +normal! zo +1504 +normal! zo +1522 +normal! zo +1541 +normal! zo +1565 +normal! zo +1568 +normal! zo +1597 +normal! zo +1607 +normal! zo +1627 +normal! zo +1754 +normal! zo +1796 +normal! zo +let s:l = 380 - ((22 * winheight(0) + 11) / 23) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +380 +normal! 0 +wincmd w +argglobal +if bufexists("src\fsharp\FSharp.Core\printf.fs") | buffer src\fsharp\FSharp.Core\printf.fs | else | edit src\fsharp\FSharp.Core\printf.fs | endif +setlocal fdm=indent +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=10 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +7 +normal! zo +7 +normal! zo +29 +normal! zo +228 +normal! zo +278 +normal! zo +327 +normal! zo +332 +normal! zo +333 +normal! zo +342 +normal! zo +347 +normal! zo +348 +normal! zo +358 +normal! zo +909 +normal! zo +909 +normal! zc +996 +normal! zo +996 +normal! zc +1006 +normal! zo +1006 +normal! zc +1122 +normal! zo +1122 +normal! zc +1147 +normal! zo +1147 +normal! zc +1162 +normal! zc +1195 +normal! zo +1195 +normal! zc +1245 +normal! zo +1245 +normal! zc +1273 +normal! zc +1283 +normal! zo +1283 +normal! zc +1314 +normal! zo +1314 +normal! zc +1391 +normal! zo +1400 +normal! zo +1418 +normal! zo +1440 +normal! zo +1456 +normal! zo +1479 +normal! zo +1504 +normal! zo +1522 +normal! zo +1541 +normal! zo +1544 +normal! zo +1544 +normal! zc +1541 +normal! zc +1565 +normal! zo +1568 +normal! zo +1565 +normal! zc +1597 +normal! zo +1607 +normal! zo +1627 +normal! zo +1754 +normal! zo +1796 +normal! zo +let s:l = 1643 - ((6 * winheight(0) + 11) / 23) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +1643 +normal! 0 +wincmd w +2wincmd w +exe '1resize ' . ((&lines * 23 + 25) / 50) +exe '2resize ' . ((&lines * 23 + 25) / 50) +tabnext 1 +if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' + silent exe 'bwipe ' . s:wipebuf +endif +unlet! s:wipebuf +set winheight=1 winwidth=20 winminheight=1 winminwidth=1 shortmess=filnxtToOF +let s:sx = expand(":p:r")."x.vim" +if file_readable(s:sx) + exe "source " . fnameescape(s:sx) +endif +let &so = s:so_save | let &siso = s:siso_save +doautoall SessionLoadPost +unlet SessionLoad +" vim: set ft=vim : diff --git a/src/fsharp/.vim/coc-settings.json b/src/fsharp/.vim/coc-settings.json deleted file mode 100644 index 3e75c72cc7a..00000000000 --- a/src/fsharp/.vim/coc-settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "fsharp.project.objdirectory": "../../artifacts/obj/" -} diff --git a/src/fsharp/FSharp.Core/.vim/coc-settings.json b/src/fsharp/FSharp.Core/.vim/coc-settings.json index 7b3d6c3985b..ceb25c96d59 100644 --- a/src/fsharp/FSharp.Core/.vim/coc-settings.json +++ b/src/fsharp/FSharp.Core/.vim/coc-settings.json @@ -1,5 +1,5 @@ { - "fsharp.codelens.references": true, + "fsharp.codelens.references": false, "fsharp.project.otherFlags": [ "--warnon:1182", "--compiling-fslib", diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index ba89234d37d..b61bc14eadb 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -8,7 +8,7 @@ type PrintfFormat<'Printer,'State,'Residue,'Result>(value:string) = PrintfFormat<_,_,_,_>(value) then this.Captures <- caps - member x.Value = value + member __.Value = value member val internal Captures: obj[] = Unchecked.defaultof with get, set member x.GetCaptureTypes() = if System.Object.ReferenceEquals(x.Captures, null) then [||] @@ -47,10 +47,10 @@ module internal PrintfImpl = /// with just one reflection call /// 2. we can make combinable parts independent from particular printf implementation. Thus final result can be cached and shared. /// i.e when first call to printf "%s %s" will trigger creation of the specialization. Subsequent calls will pick existing specialization - /// Note, immediate specifiers will break the aggregation of arguments. For example: - /// - function that corresponds to %s%s%{123}%s%s%s (string -> string -> string -> string -> string -> T) will have to be broken into - /// three parts: chained3 -> chainedImm1 -> final2 - /// TODO shall we also aggregate the immediates? + /// Note, immediate specifiers will interrupt the aggregation of arguments. For example: + /// - function that corresponds to %s%s%{123}%s%s%s (string -> string -> string -> string -> string -> T) will have to be broken as: + /// chained2 -> finalCapture4 + /// The captures should always appear at the beginning of a chained group. open System open System.IO open System.Text @@ -275,27 +275,94 @@ module internal PrintfImpl = /// basic shape of the signature of specialization /// + + + ... + type Specializations<'State, 'Residue, 'Result> private ()= - - static member Final1<'A> + + static member FinalCapture<'A> ( - s0, conv1, s1 + s0, cap1, conv1, s1 ) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (a: 'A) -> + (fun () -> let env = env() - Utils.Write(env, s0, (conv1 a), s1) + Utils.Write(env, s0, (conv1 env.Captures.[cap1]), s1) env.Finish() ) ) - static member Final1C<'A> + static member FinalFastEndCapture<'A> ( - s0, cap1: int, conv1, s1 + s0, cap1, conv1 ) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun () -> let env = env() - Utils.Write(env, s0, (conv1 env.Captures.[cap1]), s1) + Utils.Write(env, s0, (conv1 env.Captures.[cap1])) + env.Finish() + ) + ) + + static member FinalFastStartCapture<'A> + ( + cap1, conv1, s1 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun () -> + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap1]), s1) + env.Finish() + ) + ) + + static member FinalFastCapture<'A> + ( + cap1, conv1 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun () -> + let env = env() + env.Write (conv1 env.Captures.[cap1]) + env.Finish() + ) + ) + + static member ChainedCapture<'A, 'Tail> + ( + s0, cap1, conv1, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun () -> + let env() = + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap1])) + env + next env : 'Tail + ) + ) + + static member ChainedFastStartCapture<'A, 'Tail> + ( + cap1, conv1, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun () -> + let env() = + let env = env() + env.Write(conv1 env.Captures.[cap1]) + env + next env : 'Tail + ) + ) + + + static member Final1<'A> + ( + s0, conv1, s1 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (a: 'A) -> + let env = env() + Utils.Write(env, s0, (conv1 a), s1) env.Finish() ) ) @@ -1282,14 +1349,13 @@ module internal PrintfImpl = member __.PopContinuationWithType() = System.Diagnostics.Debug.Assert(args.Count = 1, "args.Count = 1") System.Diagnostics.Debug.Assert(types.Count = 1, "types.Count = 1") - // XXX ContinuationOnStack not updated here? let cont = args.Pop() let contTy = types.Pop() cont, contTy - member __.PopValueUnsafe() = args.Pop() + member __.popValueUnsafe() = args.Pop() member this.PushContinuationWithType (cont: obj, contTy: Type) = System.Diagnostics.Debug.Assert(this.IsEmpty, "this.IsEmpty") @@ -1301,7 +1367,6 @@ module internal PrintfImpl = "incorrect type" ) - // XXX ContinuationOnStack not updated here? this.PushArgumentWithType(cont, contTy) member __.PushArgument(value: obj) = @@ -1454,11 +1519,6 @@ module internal PrintfImpl = let builderStack = PrintfBuilderStack() - // XXX currently ContinuationOnStack is not updated anywhere. - // marking it a constant. - [] - let ContinuationOnStack = -1 - let buildPlain numberOfArgs prefix = let n = numberOfArgs * 2 let hasCont = builderStack.HasContinuationOnStack numberOfArgs @@ -1478,15 +1538,85 @@ module internal PrintfImpl = else buildPlainFinal(plainArgs, plainTypes) + let buildCaptureFinal(spec, prefix, suffix, cTy) = + // TODO 0~5 pending args, currently only 0 + let capture = box(spec.Capture.Value) + let conv = getValueConverter cTy spec + let methodName, args = + match prefix, suffix with + | "", "" -> + optimizedArgCount <- optimizedArgCount + 2 + "FinalFastCapture", [|capture; conv|] + | "", _ -> + optimizedArgCount <- optimizedArgCount + 1 + "FinalFastStartCapture", [|capture; conv; suffix|] + | _, "" -> + optimizedArgCount <- optimizedArgCount + 1 + "FinalFastEndCapture", [|prefix; capture; conv|] + | _, _ -> + "FinalCapture",[|prefix; capture; conv; suffix|] + + let mi = typeof>.GetMethod(methodName, NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + let mi = mi.MakeGenericMethod [| cTy |] + mi.Invoke(null, args) + + let buildCaptureChained(spec, prefix, cTy, cont, contTy) = + // TODO 0~5 pending args, currently only 0 + let capture = box(spec.Capture.Value) + let conv = getValueConverter cTy spec + let methodName,args = + if prefix = "" then + optimizedArgCount <- optimizedArgCount + 1 + "ChainedFastStartCapture", [|capture; conv; cont|] + else + "ChainedCapture", [|prefix; capture; conv; cont|] + + let mi = typeof>.GetMethod(methodName, NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + let mi = mi.MakeGenericMethod [| cTy; contTy |] + mi.Invoke(null, args) + + let buildCapture(spec, prefix, suffix, cTy, numberOfArgs) = + // TODO pending args are ignored. + let hasCont = builderStack.HasContinuationOnStack numberOfArgs + if hasCont then + let n = numberOfArgs * 2 + let extra = if hasCont then 1 else 0 + let cont, contTy = builderStack.PopContinuationWithType() + + buildCaptureChained(spec, prefix, cTy, cont, contTy) + else + buildCaptureFinal(spec, prefix, suffix, cTy) + + + /// + /// A sentinel value for parseFromFormatSpecifier return value, + /// indicating that a continuation is at the stack top. + /// + [] + let ContinuationOnStack = -1 + /// + /// A sentinel value for parseFromFormatSpecifier return value, + /// indicating that the format string completes scanning and + /// no more specifiers are found. + /// + [] + let EndOfString = 0 + let rec parseFromFormatSpecifier (prefix: string) (s: string) (funcTy: Type) (i: int) (cTy: Type[]) = - if i >= s.Length then 0 + if i >= s.Length then EndOfString else count <- count + 1 let spec, i = FormatString.parseFormatSpecifier s i - let isImm, imm = spec.Capture.IsSome, Option.defaultValue -1 spec.Capture + let isImm, _ = spec.Capture.IsSome, Option.defaultValue -1 spec.Capture let next, suffix = FormatString.findNextFormatSpecifier s i let argTys = @@ -1507,8 +1637,29 @@ module internal PrintfImpl = let retTy = argTys.[argTys.Length - 1] let numberOfArgs = parseFromFormatSpecifier suffix s retTy next cTy + let specialForm = spec.TypeChar = 'a' || spec.TypeChar = 't' || spec.IsStarWidth || spec.IsStarPrecision - if spec.TypeChar = 'a' || spec.TypeChar = 't' || spec.IsStarWidth || spec.IsStarPrecision then + if spec.HasCapture then + if specialForm then raise <| exn "TODO" + let capture = spec.Capture.Value + if numberOfArgs = ContinuationOnStack then + let cont, contTy = builderStack.PopContinuationWithType() + let currentCont = buildCaptureChained(spec, prefix, cTy.[capture], cont, contTy) + builderStack.PushContinuationWithType(currentCont, funcTy) + + elif numberOfArgs = EndOfString then + // a "final" starting with a "capture" must not have pending args + System.Diagnostics.Debug.Assert(builderStack.IsEmpty, "builderStack.IsEmpty") + let currentCont = buildCaptureFinal(spec, prefix, suffix, cTy.[capture]) + builderStack.PushContinuationWithType(currentCont, funcTy) + else + //build a "capture-starting" continuation with the pending params + let cont = buildCapture(spec, prefix, suffix, cTy.[capture], numberOfArgs) + builderStack.PushContinuationWithType(cont, funcTy) + + ContinuationOnStack + + elif specialForm then if numberOfArgs = ContinuationOnStack then let cont, contTy = builderStack.PopContinuationWithType() @@ -1517,7 +1668,7 @@ module internal PrintfImpl = ContinuationOnStack else - if numberOfArgs = 0 then + if numberOfArgs = EndOfString then System.Diagnostics.Debug.Assert(builderStack.IsEmpty, "builderStack.IsEmpty") let currentCont = buildSpecialFinal(spec, argTys, prefix, suffix) @@ -1550,18 +1701,11 @@ module internal PrintfImpl = ContinuationOnStack else - // n = 0 || n = 1 if numberOfArgs = ContinuationOnStack then let idx = argTys.Length - 2 builderStack.PushArgument suffix builderStack.PushArgumentWithType((getValueConverter argTys.[idx] spec), argTys.[idx]) 1 - elif spec.HasCapture then - let capture = spec.Capture.Value - builderStack.PushArgument suffix - builderStack.PushArgumentWithType(getValueConverter cTy.[capture] spec, cTy.[capture]) - // TODO figure out how exactly the build stack works... - 0 else builderStack.PushArgument suffix builderStack.PushArgumentWithType((getValueConverter argTys.[0] spec), argTys.[0]) @@ -1586,7 +1730,7 @@ module internal PrintfImpl = let n = parseFromFormatSpecifier prefix s funcTy prefixPos cTy if n = ContinuationOnStack || n = 0 then - builderStack.PopValueUnsafe() + builderStack.popValueUnsafe() else buildPlain n prefix @@ -1657,7 +1801,7 @@ module internal PrintfImpl = let inline doPrintf fmt f = let formatter, n = Cache<_, _, _, _>.Get fmt - let env() = f n fmt.Captures + let env() = f n formatter env [] @@ -1677,20 +1821,20 @@ module Printf = [] let ksprintf continuation (format: StringFormat<'T, 'Result>) : 'T = - doPrintf format (fun n caps -> + doPrintf format (fun n -> if n <= 2 then - SmallStringPrintfEnv(continuation, caps) :> PrintfEnv<_, _, _> + SmallStringPrintfEnv(continuation, format.Captures) :> PrintfEnv<_, _, _> else - StringPrintfEnv(continuation, n, caps) :> PrintfEnv<_, _, _> + StringPrintfEnv(continuation, n, format.Captures) :> PrintfEnv<_, _, _> ) [] let sprintf (format: StringFormat<'T>) = - doPrintf format (fun n caps -> + doPrintf format (fun n -> if n <= 2 then - SmallStringPrintfEnv(id, caps) :> PrintfEnv<_, _, _> + SmallStringPrintfEnv(id, format.Captures) :> PrintfEnv<_, _, _> else - StringPrintfEnv(id, n, caps) :> PrintfEnv<_, _, _> + StringPrintfEnv(id, n, format.Captures) :> PrintfEnv<_, _, _> ) [] @@ -1698,14 +1842,14 @@ module Printf = [] let kbprintf continuation (builder: StringBuilder) format = - doPrintf format (fun _ caps -> - StringBuilderPrintfEnv(continuation, builder, caps) :> PrintfEnv<_, _, _> + doPrintf format (fun _ -> + StringBuilderPrintfEnv(continuation, builder, format.Captures) :> PrintfEnv<_, _, _> ) [] let kfprintf continuation textWriter format = - doPrintf format (fun _ caps -> - TextWriterPrintfEnv(continuation, textWriter, caps) :> PrintfEnv<_, _, _> + doPrintf format (fun _ -> + TextWriterPrintfEnv(continuation, textWriter, format.Captures) :> PrintfEnv<_, _, _> ) [] From b293dcdfc4bca3dd0585056767570eed5fbe0d6c Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Wed, 19 Jun 2019 00:14:27 +0800 Subject: [PATCH 08/19] Final/Chain specializers for n>1 --- Session.vim | 230 +----------- src/fsharp/FSharp.Core/.vim/coc-settings.json | 6 +- src/fsharp/FSharp.Core/printf.fs | 347 +++++++++++++++++- 3 files changed, 350 insertions(+), 233 deletions(-) diff --git a/Session.vim b/Session.vim index 269a5ec030f..d560fa36145 100644 --- a/Session.vim +++ b/Session.vim @@ -2,20 +2,17 @@ let SessionLoad = 1 let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 let v:this_session=expand(":p") silent only -cd ~\git\visualfsharp +cd ~\git\visualfsharp\src\fsharp\FSharp.Core if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' let s:wipebuf = bufnr('%') endif set shortmess=aoO -badd +1579 src\fsharp\FSharp.Core\printf.fs +badd +1509 printf.fs +badd +346 ~\AppData\Local\nvim\vsim.vim argglobal silent! argdel * -edit src\fsharp\FSharp.Core\printf.fs +edit printf.fs set splitbelow splitright -wincmd _ | wincmd | -split -1wincmd k -wincmd w set nosplitbelow set nosplitright wincmd t @@ -23,8 +20,6 @@ set winminheight=0 set winheight=1 set winminwidth=0 set winwidth=1 -exe '1resize ' . ((&lines * 23 + 25) / 50) -exe '2resize ' . ((&lines * 23 + 25) / 50) argglobal setlocal fdm=indent setlocal fde=0 @@ -40,227 +35,42 @@ normal! zo normal! zo 29 normal! zo -228 +279 normal! zo -278 -normal! zo -327 -normal! zo -332 -normal! zo -333 -normal! zo -342 -normal! zo -347 -normal! zo -348 -normal! zo -358 -normal! zo -909 -normal! zo -909 -normal! zc -996 -normal! zo -996 -normal! zc -1006 -normal! zo -1006 -normal! zc -1122 -normal! zo -1122 -normal! zc -1147 -normal! zo -1147 -normal! zc -1162 -normal! zc -1195 -normal! zo -1195 -normal! zc -1245 -normal! zo -1245 -normal! zc -1273 -normal! zc -1283 -normal! zo -1283 -normal! zc -1314 -normal! zo -1314 -normal! zc -1391 -normal! zo -1400 -normal! zo -1418 -normal! zo -1440 -normal! zo -1456 -normal! zo -1479 -normal! zo -1504 -normal! zo -1522 -normal! zo -1541 -normal! zo -1565 -normal! zo -1568 -normal! zo -1597 -normal! zo -1607 -normal! zo -1627 -normal! zo -1754 -normal! zo -1796 -normal! zo -let s:l = 380 - ((22 * winheight(0) + 11) / 23) -if s:l < 1 | let s:l = 1 | endif -exe s:l -normal! zt -380 -normal! 0 -wincmd w -argglobal -if bufexists("src\fsharp\FSharp.Core\printf.fs") | buffer src\fsharp\FSharp.Core\printf.fs | else | edit src\fsharp\FSharp.Core\printf.fs | endif -setlocal fdm=indent -setlocal fde=0 -setlocal fmr={{{,}}} -setlocal fdi=# -setlocal fdl=10 -setlocal fml=1 -setlocal fdn=20 -setlocal fen -7 -normal! zo -7 -normal! zo -29 -normal! zo -228 -normal! zo -278 -normal! zo -327 -normal! zo -332 +328 normal! zo 333 normal! zo -342 -normal! zo -347 +343 normal! zo 348 normal! zo -358 -normal! zo -909 -normal! zo -909 -normal! zc -996 -normal! zo -996 -normal! zc -1006 -normal! zo -1006 -normal! zc -1122 -normal! zo -1122 -normal! zc -1147 -normal! zo -1147 -normal! zc -1162 -normal! zc -1195 -normal! zo -1195 -normal! zc -1245 -normal! zo -1245 -normal! zc -1273 -normal! zc -1283 -normal! zo -1283 -normal! zc -1314 -normal! zo -1314 -normal! zc -1391 -normal! zo -1400 -normal! zo -1418 -normal! zo -1440 -normal! zo -1456 -normal! zo -1479 -normal! zo -1504 -normal! zo -1522 +1392 normal! zo -1541 +1401 normal! zo -1544 +1441 normal! zo -1544 -normal! zc -1541 -normal! zc -1565 +1542 normal! zo -1568 +1567 normal! zo -1565 -normal! zc -1597 +1585 normal! zo -1607 +1613 normal! zo -1627 +1623 normal! zo -1754 +1624 normal! zo -1796 +1749 normal! zo -let s:l = 1643 - ((6 * winheight(0) + 11) / 23) +let s:l = 1489 - ((28 * winheight(0) + 29) / 58) if s:l < 1 | let s:l = 1 | endif exe s:l normal! zt -1643 -normal! 0 -wincmd w -2wincmd w -exe '1resize ' . ((&lines * 23 + 25) / 50) -exe '2resize ' . ((&lines * 23 + 25) / 50) +1489 +normal! 016| tabnext 1 if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' silent exe 'bwipe ' . s:wipebuf diff --git a/src/fsharp/FSharp.Core/.vim/coc-settings.json b/src/fsharp/FSharp.Core/.vim/coc-settings.json index ceb25c96d59..866efb83a6d 100644 --- a/src/fsharp/FSharp.Core/.vim/coc-settings.json +++ b/src/fsharp/FSharp.Core/.vim/coc-settings.json @@ -1,5 +1,4 @@ { - "fsharp.codelens.references": false, "fsharp.project.otherFlags": [ "--warnon:1182", "--compiling-fslib", @@ -55,10 +54,7 @@ "--define:FX_RESHAPED_MSBUILD", "--define:NETSTANDARD", "--define:NETSTANDARD1_6", - //"--keyfile:C:\Users\Yatao\.nuget\packages\microsoft.dotnet.arcade.sdk\1.0.0-beta.19264.13\tools\snk/MSFT.snk - //"--publicsign+ - "--optimize-", - //"--resource:C:\Users\Yatao\git\visualfsharp\artifacts\obj\FSharp.Core\Debug\netstandard1.6\FSCore.resources + "--optimize-" ], "fsharp.project.includeCompileBefore": true } diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index b61bc14eadb..fdb2190390f 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -276,84 +276,395 @@ module internal PrintfImpl = /// + + + ... + type Specializations<'State, 'Residue, 'Result> private ()= - static member FinalCapture<'A> + static member FinalCapture1<'A> ( - s0, cap1, conv1, s1 + s0, cap, conv1, s1 ) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun () -> let env = env() - Utils.Write(env, s0, (conv1 env.Captures.[cap1]), s1) + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1) env.Finish() ) ) - static member FinalFastEndCapture<'A> + static member FinalFastEndCapture1<'A> ( - s0, cap1, conv1 + s0, cap, conv1 ) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun () -> let env = env() - Utils.Write(env, s0, (conv1 env.Captures.[cap1])) + Utils.Write(env, s0, (conv1 env.Captures.[cap])) env.Finish() ) ) - static member FinalFastStartCapture<'A> + static member FinalFastStartCapture1<'A> ( - cap1, conv1, s1 + cap, conv1, s1 ) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun () -> let env = env() - Utils.Write(env, (conv1 env.Captures.[cap1]), s1) + Utils.Write(env, (conv1 env.Captures.[cap]), s1) env.Finish() ) ) - static member FinalFastCapture<'A> + static member FinalFastCapture1<'A> ( - cap1, conv1 + cap, conv1 ) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun () -> let env = env() - env.Write (conv1 env.Captures.[cap1]) + env.Write (conv1 env.Captures.[cap]) env.Finish() ) ) - static member ChainedCapture<'A, 'Tail> + static member FinalCapture2<'A, 'B> ( - s0, cap1, conv1, + s0, cap, conv1, s1, conv2, s2 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) -> + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2) + env.Finish() + ) + ) + + static member FinalFastEndCapture2<'A, 'B> + ( + s0, cap, conv1, s1, conv2 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) -> + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b)) + env.Finish() + ) + ) + + static member FinalFastStartCapture2<'A, 'B> + ( + cap, conv1, s1, conv2, s2 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) -> + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2) + env.Finish() + ) + ) + + static member FinalFastCapture2<'A, 'B> + ( + cap, conv1, s1, conv2 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) -> + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b)) + env.Finish() + ) + ) + + static member FinalCapture3<'A, 'B, 'C> + ( + s0, cap, conv1, s1, conv2, s2, conv3, s3 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) -> + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3) + env.Finish() + ) + ) + + static member FinalFastEndCapture3<'A, 'B, 'C> + ( + s0, cap, conv1, s1, conv2, s2, conv3 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) -> + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c)) + env.Finish() + ) + ) + + static member FinalFastStartCapture3<'A, 'B, 'C> + ( + cap, conv1, s1, conv2, s2, conv3, s3 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) -> + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3) + env.Finish() + ) + ) + + static member FinalFastCapture3<'A, 'B, 'C> + ( + cap, conv1, s1, conv2, s2, conv3 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) -> + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c)) + env.Finish() + ) + ) + + static member FinalCapture4<'A, 'B, 'C, 'D> + ( + s0, cap, conv1, s1, conv2, s2, conv3, s3, conv4, s4 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D)-> + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d), s4) + env.Finish() + ) + ) + + static member FinalFastEndCapture4<'A, 'B, 'C, 'D> + ( + s0, cap, conv1, s1, conv2, s2, conv3, s3, conv4 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D) -> + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d)) + env.Finish() + ) + ) + + static member FinalFastStartCapture4<'A, 'B, 'C, 'D> + ( + cap, conv1, s1, conv2, s2, conv3, s3, conv4, s4 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D) -> + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d), s4) + env.Finish() + ) + ) + + static member FinalFastCapture4<'A, 'B, 'C, 'D> + ( + cap, conv1, s1, conv2, s2, conv3, s3, conv4 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D) -> + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d)) + env.Finish() + ) + ) + + static member FinalCapture5<'A, 'B, 'C, 'D, 'E> + ( + s0, cap, conv1, s1, conv2, s2, conv3, s3, conv4, s4, conv5, s5 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D) (e: 'E) -> + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d), s4, (conv5 e), s5) + env.Finish() + ) + ) + + static member FinalFastEndCapture5<'A, 'B, 'C, 'D, 'E> + ( + s0, cap, conv1, s1, conv2, s2, conv3, s3, conv4, s4, conv5 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D) (e: 'E) -> + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d), s4, (conv5 e)) + env.Finish() + ) + ) + + static member FinalFastStartCapture5<'A, 'B, 'C, 'D, 'E> + ( + cap, conv1, s1, conv2, s2, conv3, s3, conv4, s4, conv5, s5 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D) (e: 'E) -> + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d), s4, (conv5 e), s5) + env.Finish() + ) + ) + + static member FinalFastCapture5<'A, 'B, 'C, 'D, 'E> + ( + cap, conv1, s1, conv2, s2, conv3, s3, conv4, s4, conv5 + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D) (e: 'E) -> + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d), s4, (conv5 e)) + env.Finish() + ) + ) + + static member ChainedCapture1<'A, 'Tail> + ( + s0, cap, conv1, next ) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun () -> let env() = let env = env() - Utils.Write(env, s0, (conv1 env.Captures.[cap1])) + Utils.Write(env, s0, (conv1 env.Captures.[cap])) env next env : 'Tail ) ) - static member ChainedFastStartCapture<'A, 'Tail> + static member ChainedFastStartCapture1<'A, 'Tail> ( - cap1, conv1, + cap, conv1, next ) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun () -> let env() = let env = env() - env.Write(conv1 env.Captures.[cap1]) + env.Write(conv1 env.Captures.[cap]) + env + next env : 'Tail + ) + ) + + static member ChainedCapture2<'A, 'B, 'Tail> + ( + s0, cap, conv1, s1, conv2, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) -> + let env() = + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b)) env next env : 'Tail ) ) + static member ChainedFastStartCapture2<'A, 'B, 'Tail> + ( + cap, conv1, s1, conv2, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) -> + let env() = + let env = env() + Utils.Write(env, conv1 env.Captures.[cap], s1, (conv2 b)) + env + next env : 'Tail + ) + ) + + static member ChainedCapture3<'A, 'B, 'C, 'Tail> + ( + s0, cap, conv1, s1, conv2, s2, conv3, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) -> + let env() = + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c)) + env + next env : 'Tail + ) + ) + + static member ChainedCaptureFastStart3<'A, 'B, 'C, 'Tail> + ( + cap, conv1, s1, conv2, s2, conv3, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) -> + let env() = + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c)) + env + next env : 'Tail + ) + ) + + static member ChainedCapture4<'A, 'B, 'C, 'D, 'Tail> + ( + s0, cap, conv1, s1, conv2, s2, conv3, s3, conv4, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D)-> + let env() = + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d)) + env + next env : 'Tail + ) + ) + + static member ChainedCaptureFastStart4<'A, 'B, 'C, 'D, 'Tail> + ( + cap, conv1, s1, conv2, s2, conv3, s3, conv4, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D)-> + let env() = + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d)) + env + next env : 'Tail + ) + ) + + static member ChainedCapture5<'A, 'B, 'C, 'D, 'E, 'Tail> + ( + s0, cap, conv1, s1, conv2, s2, conv3, s3, conv4, s4, conv5, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D) (e: 'E)-> + let env() = + let env = env() + Utils.Write(env, s0, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d), s4, (conv5 e)) + env + next env : 'Tail + ) + ) + + static member ChainedCaptureFastStart5<'A, 'B, 'C, 'D, 'E, 'Tail> + ( + cap, conv1, s1, conv2, s2, conv3, s3, conv4, s4, conv5, + next + ) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (b: 'B) (c: 'C) (d: 'D) (e: 'E)-> + let env() = + let env = env() + Utils.Write(env, (conv1 env.Captures.[cap]), s1, (conv2 b), s2, (conv3 c), s3, (conv4 d), s4, (conv5 e)) + env + next env : 'Tail + ) + ) static member Final1<'A> ( From fcc1adccc3873e3d5fbd41e4ef4337dc9f448d89 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Wed, 19 Jun 2019 00:23:38 +0800 Subject: [PATCH 09/19] (temp) vim session file for the folds.. --- src/fsharp/FSharp.Core/Session.vim | 85 ++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/fsharp/FSharp.Core/Session.vim diff --git a/src/fsharp/FSharp.Core/Session.vim b/src/fsharp/FSharp.Core/Session.vim new file mode 100644 index 00000000000..b5c4f6cb96a --- /dev/null +++ b/src/fsharp/FSharp.Core/Session.vim @@ -0,0 +1,85 @@ +let SessionLoad = 1 +let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 +let v:this_session=expand(":p") +silent only +cd ~\git\visualfsharp\src\fsharp\FSharp.Core +if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' + let s:wipebuf = bufnr('%') +endif +set shortmess=aoO +badd +682 printf.fs +badd +1 .vim\coc-settings.json +badd +79 ~\git\visualfsharp\Session.vim +argglobal +silent! argdel * +edit printf.fs +set splitbelow splitright +set nosplitbelow +set nosplitright +wincmd t +set winminheight=0 +set winheight=1 +set winminwidth=0 +set winwidth=1 +argglobal +setlocal fdm=indent +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=10 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +29 +normal! zo +1221 +normal! zo +1221 +normal! zc +1318 +normal! zo +1318 +normal! zc +1434 +normal! zo +1434 +normal! zc +1507 +normal! zo +1507 +normal! zc +1557 +normal! zo +1557 +normal! zc +1585 +normal! zc +1595 +normal! zo +1595 +normal! zc +1626 +normal! zo +1626 +normal! zc +let s:l = 1686 - ((94 * winheight(0) + 29) / 58) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +1686 +normal! 016| +lcd ~\git\visualfsharp\src\fsharp\FSharp.Core +tabnext 1 +if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' + silent exe 'bwipe ' . s:wipebuf +endif +unlet! s:wipebuf +set winheight=1 winwidth=20 winminheight=1 winminwidth=1 shortmess=filnxtToOFI +let s:sx = expand(":p:r")."x.vim" +if file_readable(s:sx) + exe "source " . fnameescape(s:sx) +endif +let &so = s:so_save | let &siso = s:siso_save +doautoall SessionLoadPost +unlet SessionLoad +" vim: set ft=vim : From 17f8788bd1df53ed2786b0267453fb4f958e35db Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Wed, 19 Jun 2019 01:40:34 +0800 Subject: [PATCH 10/19] checkpoint. --- src/fsharp/FSharp.Core/Session.vim | 140 ++++++++++++++++++++++++++++- src/fsharp/FSharp.Core/printf.fs | 63 ++++++++----- 2 files changed, 178 insertions(+), 25 deletions(-) diff --git a/src/fsharp/FSharp.Core/Session.vim b/src/fsharp/FSharp.Core/Session.vim index b5c4f6cb96a..99edc914f8c 100644 --- a/src/fsharp/FSharp.Core/Session.vim +++ b/src/fsharp/FSharp.Core/Session.vim @@ -7,13 +7,17 @@ if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' let s:wipebuf = bufnr('%') endif set shortmess=aoO -badd +682 printf.fs +badd +1903 printf.fs badd +1 .vim\coc-settings.json badd +79 ~\git\visualfsharp\Session.vim argglobal silent! argdel * edit printf.fs set splitbelow splitright +wincmd _ | wincmd | +split +1wincmd k +wincmd w set nosplitbelow set nosplitright wincmd t @@ -21,6 +25,8 @@ set winminheight=0 set winheight=1 set winminwidth=0 set winwidth=1 +exe '1resize ' . ((&lines * 29 + 30) / 61) +exe '2resize ' . ((&lines * 28 + 30) / 61) argglobal setlocal fdm=indent setlocal fde=0 @@ -32,6 +38,8 @@ setlocal fdn=20 setlocal fen 29 normal! zo +279 +normal! zo 1221 normal! zo 1221 @@ -62,13 +70,137 @@ normal! zc normal! zo 1626 normal! zc -let s:l = 1686 - ((94 * winheight(0) + 29) / 58) +1642 +normal! zo +1703 +normal! zo +1712 +normal! zo +1752 +normal! zo +1752 +normal! zc +1791 +normal! zo +1791 +normal! zc +1816 +normal! zo +1816 +normal! zc +1834 +normal! zo +1834 +normal! zc +1878 +normal! zo +1882 +normal! zo +1896 +normal! zo +1925 +normal! zo +1955 +normal! zo +1975 +normal! zo +let s:l = 1894 - ((16 * winheight(0) + 14) / 29) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +1894 +normal! 0 +lcd ~\git\visualfsharp\src\fsharp\FSharp.Core +wincmd w +argglobal +if bufexists("~\git\visualfsharp\src\fsharp\FSharp.Core\printf.fs") | buffer ~\git\visualfsharp\src\fsharp\FSharp.Core\printf.fs | else | edit ~\git\visualfsharp\src\fsharp\FSharp.Core\printf.fs | endif +setlocal fdm=indent +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=10 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +29 +normal! zo +279 +normal! zo +1221 +normal! zo +1221 +normal! zc +1318 +normal! zo +1318 +normal! zc +1434 +normal! zo +1434 +normal! zc +1507 +normal! zo +1507 +normal! zc +1557 +normal! zo +1557 +normal! zc +1585 +normal! zc +1595 +normal! zo +1595 +normal! zc +1626 +normal! zo +1626 +normal! zc +1642 +normal! zo +1703 +normal! zo +1712 +normal! zo +1712 +normal! zc +1752 +normal! zo +1752 +normal! zc +1791 +normal! zo +1791 +normal! zc +1816 +normal! zo +1834 +normal! zo +1834 +normal! zc +1878 +normal! zo +1882 +normal! zo +1896 +normal! zo +1925 +normal! zo +1955 +normal! zo +1975 +normal! zo +let s:l = 1817 - ((122 * winheight(0) + 14) / 28) if s:l < 1 | let s:l = 1 | endif exe s:l normal! zt -1686 -normal! 016| +1817 +normal! 021| lcd ~\git\visualfsharp\src\fsharp\FSharp.Core +wincmd w +2wincmd w +exe '1resize ' . ((&lines * 29 + 30) / 61) +exe '2resize ' . ((&lines * 28 + 30) / 61) tabnext 1 if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' silent exe 'bwipe ' . s:wipebuf diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index fdb2190390f..5e4199f7411 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -591,7 +591,7 @@ module internal PrintfImpl = ) ) - static member ChainedCaptureFastStart3<'A, 'B, 'C, 'Tail> + static member ChainedFastStartCapture3<'A, 'B, 'C, 'Tail> ( cap, conv1, s1, conv2, s2, conv3, next @@ -621,7 +621,7 @@ module internal PrintfImpl = ) ) - static member ChainedCaptureFastStart4<'A, 'B, 'C, 'D, 'Tail> + static member ChainedFastStartCapture4<'A, 'B, 'C, 'D, 'Tail> ( cap, conv1, s1, conv2, s2, conv3, s3, conv4, next @@ -651,7 +651,7 @@ module internal PrintfImpl = ) ) - static member ChainedCaptureFastStart5<'A, 'B, 'C, 'D, 'E, 'Tail> + static member ChainedFastStartCapture5<'A, 'B, 'C, 'D, 'E, 'Tail> ( cap, conv1, s1, conv2, s2, conv3, s3, conv4, s4, conv5, next @@ -1849,15 +1849,18 @@ module internal PrintfImpl = else buildPlainFinal(plainArgs, plainTypes) - let buildCaptureFinal(spec, prefix, suffix, cTy) = - // TODO 0~5 pending args, currently only 0 + let buildCaptureFinal(spec, prefix, suffix, cTy, pendingArgs: obj[], pendingTypes) = let capture = box(spec.Capture.Value) let conv = getValueConverter cTy spec + let argsCount = pendingArgs.Length + let suffix' = if argsCount > 0 then pendingArgs.[argsCount - 1].ToString() else suffix + + // TODO maybe push some to stack? let methodName, args = - match prefix, suffix with + match prefix, suffix' with | "", "" -> optimizedArgCount <- optimizedArgCount + 2 - "FinalFastCapture", [|capture; conv|] + "FinalFastCapture", Array.append [|capture; conv|] pendingTypes | "", _ -> optimizedArgCount <- optimizedArgCount + 1 "FinalFastStartCapture", [|capture; conv; suffix|] @@ -1874,35 +1877,51 @@ module internal PrintfImpl = let mi = mi.MakeGenericMethod [| cTy |] mi.Invoke(null, args) - let buildCaptureChained(spec, prefix, cTy, cont, contTy) = - // TODO 0~5 pending args, currently only 0 + let buildCaptureChained(spec, prefix, cTy, tail, retTy, pendingArgs, pendingTypes: Type[]) = let capture = box(spec.Capture.Value) let conv = getValueConverter cTy spec let methodName,args = if prefix = "" then optimizedArgCount <- optimizedArgCount + 1 - "ChainedFastStartCapture", [|capture; conv; cont|] + "ChainedFastStartCapture", seq { + yield capture + yield conv + yield! pendingArgs + yield tail + } else - "ChainedCapture", [|prefix; capture; conv; cont|] - - let mi = typeof>.GetMethod(methodName, NonPublicStatics) + "ChainedCapture", seq { + yield prefix + yield capture + yield conv + yield! pendingArgs + yield tail + } + + let mi = typeof>.GetMethod(methodName + (pendingTypes.Length + 1).ToString(), NonPublicStatics) #if DEBUG verifyMethodInfoWasTaken mi #endif - let mi = mi.MakeGenericMethod [| cTy; contTy |] - mi.Invoke(null, args) + let mi = mi.MakeGenericMethod(Array.ofSeq <| seq { + yield cTy + yield! pendingTypes + yield retTy + }) + mi.Invoke(null, Array.ofSeq args) let buildCapture(spec, prefix, suffix, cTy, numberOfArgs) = - // TODO pending args are ignored. + let n = numberOfArgs * 2 let hasCont = builderStack.HasContinuationOnStack numberOfArgs + let plainArgs, plainTypes = + builderStack.GetArgumentAndTypesAsArrays(n, 0, n, numberOfArgs, 0, numberOfArgs) + if hasCont then let n = numberOfArgs * 2 - let extra = if hasCont then 1 else 0 let cont, contTy = builderStack.PopContinuationWithType() - buildCaptureChained(spec, prefix, cTy, cont, contTy) + buildCaptureChained(spec, prefix, cTy, cont, contTy, plainArgs, plainTypes) else - buildCaptureFinal(spec, prefix, suffix, cTy) + buildCaptureFinal(spec, prefix, suffix, cTy, plainArgs, plainTypes) /// @@ -1919,6 +1938,7 @@ module internal PrintfImpl = [] let EndOfString = 0 + /// The number of pending arguments on the builder stack let rec parseFromFormatSpecifier (prefix: string) (s: string) (funcTy: Type) (i: int) (cTy: Type[]) = if i >= s.Length then EndOfString @@ -1954,14 +1974,15 @@ module internal PrintfImpl = if specialForm then raise <| exn "TODO" let capture = spec.Capture.Value if numberOfArgs = ContinuationOnStack then + // no pending args between capture and cont let cont, contTy = builderStack.PopContinuationWithType() - let currentCont = buildCaptureChained(spec, prefix, cTy.[capture], cont, contTy) + let currentCont = buildCaptureChained(spec, prefix, cTy.[capture], cont, contTy, [||], [||]) builderStack.PushContinuationWithType(currentCont, funcTy) elif numberOfArgs = EndOfString then // a "final" starting with a "capture" must not have pending args System.Diagnostics.Debug.Assert(builderStack.IsEmpty, "builderStack.IsEmpty") - let currentCont = buildCaptureFinal(spec, prefix, suffix, cTy.[capture]) + let currentCont = buildCaptureFinal(spec, prefix, suffix, cTy.[capture], [||], [||]) builderStack.PushContinuationWithType(currentCont, funcTy) else //build a "capture-starting" continuation with the pending params From fa3301d300e8f68c931e6184d9144c781c4a4571 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Wed, 19 Jun 2019 20:22:28 +0800 Subject: [PATCH 11/19] checkpoint. --- src/fsharp/FSharp.Core/printf.fs | 248 +++++++++++++++++++++++++++++-- 1 file changed, 235 insertions(+), 13 deletions(-) diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 5e4199f7411..48a62adc384 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -665,8 +665,127 @@ module internal PrintfImpl = next env : 'Tail ) ) + + static member LittleAFinalCapture<'A>(s1: string, cap: int, s2: string) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (f: 'State -> 'A ->'Residue) (a: 'A) -> + let env = env() + env.Write s1 + env.WriteT(f env.State a) + env.Write s2 + env.Finish() + ) + ) + + static member LittleAChainedCapture<'A, 'Tail>(s1: string, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (f: 'State -> 'A ->'Residue) (a: 'A) -> + let env() = + let env = env() + env.Write s1 + env.WriteT(f env.State a) + env + next env: 'Tail + ) + ) + + static member StarFinal1Capture<'A>(s1: string, conv, s2: string) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (star1: int) (a: 'A) -> + let env = env() + env.Write s1 + env.Write (conv a star1: string) + env.Write s2 + env.Finish() + ) + ) + + static member PercentStarFinal1Capture(s1: string, s2: string) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (_star1 : int) -> + let env = env() + env.Write s1 + env.Write("%") + env.Write s2 + env.Finish() + ) + ) + + static member StarFinal2Capture<'A>(s1: string, conv, s2: string) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (star1: int) (star2: int) (a: 'A) -> + let env = env() + env.Write s1 + env.Write (conv a star1 star2: string) + env.Write s2 + env.Finish() + ) + ) + + /// Handles case when '%*.*%' is used at the end of string + static member PercentStarFinal2Capture(s1: string, s2: string) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (_star1 : int) (_star2 : int) -> + let env = env() + env.Write s1 + env.Write("%") + env.Write s2 + env.Finish() + ) + ) + + static member StarChained1Capture<'A, 'Tail>(s1: string, conv, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (star1: int) (a: 'A) -> + let env() = + let env = env() + env.Write s1 + env.Write(conv a star1 : string) + env + next env : 'Tail + ) + ) + + /// Handles case when '%*%' is used in the middle of the string so it needs to be chained to another printing block + static member PercentStarChained1Capture<'Tail>(s1: string, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (_star1 : int) -> + let env() = + let env = env() + env.Write s1 + env.Write("%") + env + next env: 'Tail + ) + ) + + static member StarChained2Capture<'A, 'Tail>(s1: string, conv, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (star1: int) (star2: int) (a: 'A) -> + let env() = + let env = env() + env.Write s1 + env.Write(conv a star1 star2 : string) + env + next env : 'Tail + ) + ) + + /// Handles case when '%*.*%' is used in the middle of the string so it needs to be chained to another printing block + static member PercentStarChained2Capture<'Tail>(s1: string, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = + (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> + (fun (_star1 : int) (_star2 : int) -> + let env() = + let env = env() + env.Write s1 + env.Write("%") + env + next env : 'Tail + ) + ) + - static member Final1<'A> + static member Final1Capture<'A> ( s0, conv1, s1 ) = @@ -1066,6 +1185,7 @@ module internal PrintfImpl = env.Finish() ) ) + static member TChained<'Tail>(s1: string, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun (f: 'State -> 'Residue) -> @@ -1088,6 +1208,7 @@ module internal PrintfImpl = env.Finish() ) ) + static member LittleAChained<'A, 'Tail>(s1: string, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> (fun (f: 'State -> 'A ->'Residue) (a: 'A) -> @@ -1700,6 +1821,7 @@ module internal PrintfImpl = // or grab the content of stack, build intermediate printer and push it back to stack (so it can later be consumed by as argument) type private PrintfBuilder<'S, 'Re, 'Res>() = + let builderStack = PrintfBuilderStack() let mutable count = 0 let mutable optimizedArgCount = 0 #if DEBUG @@ -1828,8 +1950,6 @@ module internal PrintfImpl = let mi = mi.MakeGenericMethod argTypes mi.Invoke(null, args) - let builderStack = PrintfBuilderStack() - let buildPlain numberOfArgs prefix = let n = numberOfArgs * 2 let hasCont = builderStack.HasContinuationOnStack numberOfArgs @@ -1849,33 +1969,56 @@ module internal PrintfImpl = else buildPlainFinal(plainArgs, plainTypes) - let buildCaptureFinal(spec, prefix, suffix, cTy, pendingArgs: obj[], pendingTypes) = + let buildCaptureFinal(spec, prefix, suffix, cTy, pendingArgs: obj[], pendingTypes: Type[]) = let capture = box(spec.Capture.Value) let conv = getValueConverter cTy spec let argsCount = pendingArgs.Length let suffix' = if argsCount > 0 then pendingArgs.[argsCount - 1].ToString() else suffix - // TODO maybe push some to stack? - let methodName, args = + let methodName, (args: obj seq) = match prefix, suffix' with | "", "" -> optimizedArgCount <- optimizedArgCount + 2 - "FinalFastCapture", Array.append [|capture; conv|] pendingTypes + "FinalFastCapture", seq { + yield capture + yield conv + if argsCount > 0 then + yield box suffix + yield! Seq.take (argsCount-1) pendingArgs + } | "", _ -> optimizedArgCount <- optimizedArgCount + 1 - "FinalFastStartCapture", [|capture; conv; suffix|] + "FinalFastStartCapture", seq { + yield capture + yield conv + yield box suffix + yield! pendingArgs + } | _, "" -> optimizedArgCount <- optimizedArgCount + 1 - "FinalFastEndCapture", [|prefix; capture; conv|] + "FinalFastEndCapture", seq { + yield prefix + yield capture + yield conv + if argsCount > 0 then + yield box suffix + yield! Seq.take (argsCount-1) pendingArgs + } | _, _ -> - "FinalCapture",[|prefix; capture; conv; suffix|] + "FinalCapture", seq { + yield prefix + yield capture + yield conv + yield suffix + yield! pendingArgs + } - let mi = typeof>.GetMethod(methodName, NonPublicStatics) + let mi = typeof>.GetMethod(methodName + (pendingTypes.Length + 1).ToString(), NonPublicStatics) #if DEBUG verifyMethodInfoWasTaken mi #endif - let mi = mi.MakeGenericMethod [| cTy |] - mi.Invoke(null, args) + let mi = mi.MakeGenericMethod(Array.append [| cTy |] pendingTypes) + mi.Invoke(null, Array.ofSeq args) let buildCaptureChained(spec, prefix, cTy, tail, retTy, pendingArgs, pendingTypes: Type[]) = let capture = box(spec.Capture.Value) @@ -1923,6 +2066,85 @@ module internal PrintfImpl = else buildCaptureFinal(spec, prefix, suffix, cTy, plainArgs, plainTypes) + let buildSpecialCaptureChained(spec: FormatSpecifier, argTys: Type[], prefix: string, tail: obj, retTy) = + if spec.TypeChar = 'a' then + let mi = typeof>.GetMethod("LittleAChained", NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + + let mi = mi.MakeGenericMethod([| argTys.[1]; retTy |]) + let args = [| box prefix; tail |] + mi.Invoke(null, args) + elif spec.TypeChar = 't' then + let mi = typeof>.GetMethod("TChained", NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + let mi = mi.MakeGenericMethod([| retTy |]) + let args = [| box prefix; tail |] + mi.Invoke(null, args) + else + System.Diagnostics.Debug.Assert(spec.IsStarPrecision || spec.IsStarWidth, "spec.IsStarPrecision || spec.IsStarWidth ") + + let mi = + let n = if spec.IsStarWidth = spec.IsStarPrecision then 2 else 1 + let prefix = if spec.TypeChar = '%' then "PercentStarChained" else "StarChained" + let name = prefix + (string n) + typeof>.GetMethod(name, NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + let argTypes, args = + if spec.TypeChar = '%' then + [| retTy |], [| box prefix; tail |] + else + let argTy = argTys.[argTys.Length - 2] + let conv = getValueConverter argTy spec + [| argTy; retTy |], [| box prefix; box conv; tail |] + + let mi = mi.MakeGenericMethod argTypes + mi.Invoke(null, args) + + let buildSpecialCaptureFinal(spec: FormatSpecifier, argTys: Type[], prefix: string, suffix: string) = + if spec.TypeChar = 'a' then + let mi = typeof>.GetMethod("LittleAFinal", NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + let mi = mi.MakeGenericMethod(argTys.[1] : Type) + let args = [| box prefix; box suffix |] + mi.Invoke(null, args) + elif spec.TypeChar = 't' then + let mi = typeof>.GetMethod("TFinal", NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + let args = [| box prefix; box suffix |] + mi.Invoke(null, args) + else + System.Diagnostics.Debug.Assert(spec.IsStarPrecision || spec.IsStarWidth, "spec.IsStarPrecision || spec.IsStarWidth ") + + let mi = + let n = if spec.IsStarWidth = spec.IsStarPrecision then 2 else 1 + let prefix = if spec.TypeChar = '%' then "PercentStarFinal" else "StarFinal" + let name = prefix + (string n) + typeof>.GetMethod(name, NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + + let mi, args = + if spec.TypeChar = '%' then + mi, [| box prefix; box suffix |] + else + let argTy = argTys.[argTys.Length - 2] + let mi = mi.MakeGenericMethod argTy + let conv = getValueConverter argTy spec + mi, [| box prefix; box conv; box suffix |] + + mi.Invoke(null, args) + /// /// A sentinel value for parseFromFormatSpecifier return value, From eec41290e1a58a376fb4ab79141cc2d0dea14a1a Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Thu, 20 Jun 2019 18:04:01 +0800 Subject: [PATCH 12/19] printf.fs: capture-related code complete --- src/fsharp/FSharp.Core/printf.fs | 285 ++++++++++++------------------- 1 file changed, 109 insertions(+), 176 deletions(-) diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 48a62adc384..c7cf39da3cc 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -666,126 +666,76 @@ module internal PrintfImpl = ) ) - static member LittleAFinalCapture<'A>(s1: string, cap: int, s2: string) = + static member LittleAFinalCapture<'A>(s1: string, cap, s2: string) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (f: 'State -> 'A ->'Residue) (a: 'A) -> + (fun (f: 'State -> 'A ->'Residue) -> let env = env() env.Write s1 - env.WriteT(f env.State a) + env.WriteT(f env.State (env.Captures.[cap] :?> 'A)) env.Write s2 env.Finish() ) ) - static member LittleAChainedCapture<'A, 'Tail>(s1: string, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = + static member LittleAChainedCapture<'A, 'Tail>(s1: string, cap, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (f: 'State -> 'A ->'Residue) (a: 'A) -> + (fun (f: 'State -> 'A ->'Residue) -> let env() = let env = env() env.Write s1 - env.WriteT(f env.State a) + env.WriteT(f env.State (env.Captures.[cap] :?> 'A)) env next env: 'Tail ) ) - static member StarFinal1Capture<'A>(s1: string, conv, s2: string) = + static member StarFinalCapture1<'A>(s1: string, cap, conv, s2: string) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (star1: int) (a: 'A) -> + (fun (star1: int) -> let env = env() env.Write s1 - env.Write (conv a star1: string) + env.Write (conv (env.Captures.[cap] :?> 'A) star1: string) env.Write s2 env.Finish() ) ) - static member PercentStarFinal1Capture(s1: string, s2: string) = + static member StarFinalCapture2<'A>(s1: string, cap, conv, s2: string) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (_star1 : int) -> + (fun (star1: int) (star2: int) -> let env = env() env.Write s1 - env.Write("%") + env.Write (conv (env.Captures.[cap] :?> 'A) star1 star2: string) env.Write s2 env.Finish() ) ) - static member StarFinal2Capture<'A>(s1: string, conv, s2: string) = + static member StarChainedCapture1<'A, 'Tail>(s1: string, cap, conv, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (star1: int) (star2: int) (a: 'A) -> - let env = env() - env.Write s1 - env.Write (conv a star1 star2: string) - env.Write s2 - env.Finish() - ) - ) - - /// Handles case when '%*.*%' is used at the end of string - static member PercentStarFinal2Capture(s1: string, s2: string) = - (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (_star1 : int) (_star2 : int) -> - let env = env() - env.Write s1 - env.Write("%") - env.Write s2 - env.Finish() - ) - ) - - static member StarChained1Capture<'A, 'Tail>(s1: string, conv, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = - (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (star1: int) (a: 'A) -> + (fun (star1: int) -> let env() = let env = env() env.Write s1 - env.Write(conv a star1 : string) + env.Write(conv (env.Captures.[cap] :?> 'A) star1 : string) env next env : 'Tail ) ) - /// Handles case when '%*%' is used in the middle of the string so it needs to be chained to another printing block - static member PercentStarChained1Capture<'Tail>(s1: string, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = - (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (_star1 : int) -> - let env() = - let env = env() - env.Write s1 - env.Write("%") - env - next env: 'Tail - ) - ) - - static member StarChained2Capture<'A, 'Tail>(s1: string, conv, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = + static member StarChainedCapture2<'A, 'Tail>(s1: string, cap, conv, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (star1: int) (star2: int) (a: 'A) -> + (fun (star1: int) (star2: int) -> let env() = let env = env() env.Write s1 - env.Write(conv a star1 star2 : string) + env.Write(conv (env.Captures.[cap] :?> 'A) star1 star2 : string) env next env : 'Tail ) ) - /// Handles case when '%*.*%' is used in the middle of the string so it needs to be chained to another printing block - static member PercentStarChained2Capture<'Tail>(s1: string, next: PrintfFactory<'State, 'Residue, 'Result,'Tail>) = - (fun (env: unit -> PrintfEnv<'State, 'Residue, 'Result>) -> - (fun (_star1 : int) (_star2 : int) -> - let env() = - let env = env() - env.Write s1 - env.Write("%") - env - next env : 'Tail - ) - ) - - - static member Final1Capture<'A> + static member Final1<'A> ( s0, conv1, s1 ) = @@ -1969,6 +1919,62 @@ module internal PrintfImpl = else buildPlainFinal(plainArgs, plainTypes) + let buildCaptureSpecialChained(spec: FormatSpecifier, cTy: Type, prefix: string, tail: obj, retTy) = + let capture = box spec.Capture.Value + if spec.TypeChar = 'a' then + let mi = typeof>.GetMethod("LittleAChainedCapture", NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + + let mi = mi.MakeGenericMethod([| cTy; retTy |]) + let args = [| box prefix; capture; tail |] + mi.Invoke(null, args) + elif spec.TypeChar = 't' then raise (ArgumentException("format specifier '%t' may not be used with immediate captures")) + else + System.Diagnostics.Debug.Assert(spec.IsStarPrecision || spec.IsStarWidth, "spec.IsStarPrecision || spec.IsStarWidth ") + System.Diagnostics.Debug.Assert(spec.TypeChar <> '%', "spec.TypeChar <> '%'") + + let mi = + let n = if spec.IsStarWidth = spec.IsStarPrecision then 2 else 1 + let name = "StarChainedCapture" + (string n) + typeof>.GetMethod(name, NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + let conv = getValueConverter cTy spec + let args = [| box prefix; capture; box conv; tail |] + let mi = mi.MakeGenericMethod([| cTy; retTy |]) + mi.Invoke(null, args) + + let buildCaptureSpecialFinal(spec: FormatSpecifier, cTy: Type, prefix: string, suffix: string) = + let capture = box spec.Capture.Value + if spec.TypeChar = 'a' then + let mi = typeof>.GetMethod("LittleAFinalCapture", NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + let mi = mi.MakeGenericMethod(cTy) + let args = [| box prefix; capture; box suffix |] + mi.Invoke(null, args) + elif spec.TypeChar = 't' then raise (ArgumentException("format specifier '%t' may not be used with immediate captures")) + else + System.Diagnostics.Debug.Assert(spec.IsStarPrecision || spec.IsStarWidth, "spec.IsStarPrecision || spec.IsStarWidth ") + System.Diagnostics.Debug.Assert(spec.TypeChar <> '%', "spec.TypeChar <> '%'") + + let mi = + let n = if spec.IsStarWidth = spec.IsStarPrecision then 2 else 1 + let name = "StarFinalCapture" + (string n) + typeof>.GetMethod(name, NonPublicStatics) +#if DEBUG + verifyMethodInfoWasTaken mi +#endif + + let conv = getValueConverter cTy spec + let args = [| box prefix; capture; box conv; box suffix |] + let mi = mi.MakeGenericMethod(cTy) + mi.Invoke(null, args) + let buildCaptureFinal(spec, prefix, suffix, cTy, pendingArgs: obj[], pendingTypes: Type[]) = let capture = box(spec.Capture.Value) let conv = getValueConverter cTy spec @@ -2059,93 +2065,12 @@ module internal PrintfImpl = builderStack.GetArgumentAndTypesAsArrays(n, 0, n, numberOfArgs, 0, numberOfArgs) if hasCont then - let n = numberOfArgs * 2 let cont, contTy = builderStack.PopContinuationWithType() buildCaptureChained(spec, prefix, cTy, cont, contTy, plainArgs, plainTypes) else buildCaptureFinal(spec, prefix, suffix, cTy, plainArgs, plainTypes) - let buildSpecialCaptureChained(spec: FormatSpecifier, argTys: Type[], prefix: string, tail: obj, retTy) = - if spec.TypeChar = 'a' then - let mi = typeof>.GetMethod("LittleAChained", NonPublicStatics) -#if DEBUG - verifyMethodInfoWasTaken mi -#endif - - let mi = mi.MakeGenericMethod([| argTys.[1]; retTy |]) - let args = [| box prefix; tail |] - mi.Invoke(null, args) - elif spec.TypeChar = 't' then - let mi = typeof>.GetMethod("TChained", NonPublicStatics) -#if DEBUG - verifyMethodInfoWasTaken mi -#endif - let mi = mi.MakeGenericMethod([| retTy |]) - let args = [| box prefix; tail |] - mi.Invoke(null, args) - else - System.Diagnostics.Debug.Assert(spec.IsStarPrecision || spec.IsStarWidth, "spec.IsStarPrecision || spec.IsStarWidth ") - - let mi = - let n = if spec.IsStarWidth = spec.IsStarPrecision then 2 else 1 - let prefix = if spec.TypeChar = '%' then "PercentStarChained" else "StarChained" - let name = prefix + (string n) - typeof>.GetMethod(name, NonPublicStatics) -#if DEBUG - verifyMethodInfoWasTaken mi -#endif - let argTypes, args = - if spec.TypeChar = '%' then - [| retTy |], [| box prefix; tail |] - else - let argTy = argTys.[argTys.Length - 2] - let conv = getValueConverter argTy spec - [| argTy; retTy |], [| box prefix; box conv; tail |] - - let mi = mi.MakeGenericMethod argTypes - mi.Invoke(null, args) - - let buildSpecialCaptureFinal(spec: FormatSpecifier, argTys: Type[], prefix: string, suffix: string) = - if spec.TypeChar = 'a' then - let mi = typeof>.GetMethod("LittleAFinal", NonPublicStatics) -#if DEBUG - verifyMethodInfoWasTaken mi -#endif - let mi = mi.MakeGenericMethod(argTys.[1] : Type) - let args = [| box prefix; box suffix |] - mi.Invoke(null, args) - elif spec.TypeChar = 't' then - let mi = typeof>.GetMethod("TFinal", NonPublicStatics) -#if DEBUG - verifyMethodInfoWasTaken mi -#endif - let args = [| box prefix; box suffix |] - mi.Invoke(null, args) - else - System.Diagnostics.Debug.Assert(spec.IsStarPrecision || spec.IsStarWidth, "spec.IsStarPrecision || spec.IsStarWidth ") - - let mi = - let n = if spec.IsStarWidth = spec.IsStarPrecision then 2 else 1 - let prefix = if spec.TypeChar = '%' then "PercentStarFinal" else "StarFinal" - let name = prefix + (string n) - typeof>.GetMethod(name, NonPublicStatics) -#if DEBUG - verifyMethodInfoWasTaken mi -#endif - - let mi, args = - if spec.TypeChar = '%' then - mi, [| box prefix; box suffix |] - else - let argTy = argTys.[argTys.Length - 2] - let mi = mi.MakeGenericMethod argTy - let conv = getValueConverter argTy spec - mi, [| box prefix; box conv; box suffix |] - - mi.Invoke(null, args) - - /// /// A sentinel value for parseFromFormatSpecifier return value, /// indicating that a continuation is at the stack top. @@ -2190,34 +2115,17 @@ module internal PrintfImpl = let retTy = argTys.[argTys.Length - 1] let numberOfArgs = parseFromFormatSpecifier suffix s retTy next cTy - let specialForm = spec.TypeChar = 'a' || spec.TypeChar = 't' || spec.IsStarWidth || spec.IsStarPrecision - - if spec.HasCapture then - if specialForm then raise <| exn "TODO" - let capture = spec.Capture.Value - if numberOfArgs = ContinuationOnStack then - // no pending args between capture and cont - let cont, contTy = builderStack.PopContinuationWithType() - let currentCont = buildCaptureChained(spec, prefix, cTy.[capture], cont, contTy, [||], [||]) - builderStack.PushContinuationWithType(currentCont, funcTy) - - elif numberOfArgs = EndOfString then - // a "final" starting with a "capture" must not have pending args - System.Diagnostics.Debug.Assert(builderStack.IsEmpty, "builderStack.IsEmpty") - let currentCont = buildCaptureFinal(spec, prefix, suffix, cTy.[capture], [||], [||]) - builderStack.PushContinuationWithType(currentCont, funcTy) - else - //build a "capture-starting" continuation with the pending params - let cont = buildCapture(spec, prefix, suffix, cTy.[capture], numberOfArgs) - builderStack.PushContinuationWithType(cont, funcTy) + if spec.TypeChar = 'a' || spec.TypeChar = 't' || spec.IsStarWidth || spec.IsStarPrecision then + let cTy = + if spec.HasCapture then Some cTy.[spec.Capture.Value] + else None - ContinuationOnStack - - elif specialForm then if numberOfArgs = ContinuationOnStack then let cont, contTy = builderStack.PopContinuationWithType() - let currentCont = buildSpecialChained(spec, argTys, prefix, cont, contTy) + let currentCont = + if spec.HasCapture then buildCaptureSpecialChained(spec, cTy.Value, prefix, cont, contTy) + else buildSpecialChained(spec, argTys, prefix, cont, contTy) builderStack.PushContinuationWithType(currentCont, funcTy) ContinuationOnStack @@ -2225,7 +2133,9 @@ module internal PrintfImpl = if numberOfArgs = EndOfString then System.Diagnostics.Debug.Assert(builderStack.IsEmpty, "builderStack.IsEmpty") - let currentCont = buildSpecialFinal(spec, argTys, prefix, suffix) + let currentCont = + if spec.HasCapture then buildCaptureSpecialFinal(spec, cTy.Value, prefix, suffix) + else buildSpecialFinal(spec, argTys, prefix, suffix) builderStack.PushContinuationWithType(currentCont, funcTy) ContinuationOnStack else @@ -2250,10 +2160,33 @@ module internal PrintfImpl = else buildPlainFinal(plainArgs, plainTypes) - let next = buildSpecialChained(spec, argTys, prefix, next, retTy) + let next = + if spec.HasCapture then buildCaptureSpecialChained(spec, cTy.Value, prefix, next, retTy) + else buildSpecialChained(spec, argTys, prefix, next, retTy) builderStack.PushContinuationWithType(next, funcTy) ContinuationOnStack + + elif spec.HasCapture then + let capture = spec.Capture.Value + if numberOfArgs = ContinuationOnStack then + // no pending args between capture and cont + let cont, contTy = builderStack.PopContinuationWithType() + let currentCont = buildCaptureChained(spec, prefix, cTy.[capture], cont, contTy, [||], [||]) + builderStack.PushContinuationWithType(currentCont, funcTy) + + elif numberOfArgs = EndOfString then + // a "final" starting with a "capture" must not have pending args + System.Diagnostics.Debug.Assert(builderStack.IsEmpty, "builderStack.IsEmpty") + let currentCont = buildCaptureFinal(spec, prefix, suffix, cTy.[capture], [||], [||]) + builderStack.PushContinuationWithType(currentCont, funcTy) + else + //build a "capture-starting" continuation with the pending params + let cont = buildCapture(spec, prefix, suffix, cTy.[capture], numberOfArgs) + builderStack.PushContinuationWithType(cont, funcTy) + + ContinuationOnStack + else if numberOfArgs = ContinuationOnStack then let idx = argTys.Length - 2 From 075619f61f8073597a95863e1b43ebb7824e2bbe Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Thu, 20 Jun 2019 18:59:06 +0800 Subject: [PATCH 13/19] expect Types from codegen, not runtime --- src/fsharp/FSharp.Core/printf.fs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index c7cf39da3cc..9712032612b 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -4,15 +4,14 @@ namespace Microsoft.FSharp.Core type PrintfFormat<'Printer,'State,'Residue,'Result>(value:string) = - internal new(value, caps) as this = + internal new(value, caps, types) as this = PrintfFormat<_,_,_,_>(value) then this.Captures <- caps + this.Types <- types member __.Value = value member val internal Captures: obj[] = Unchecked.defaultof with get, set - member x.GetCaptureTypes() = - if System.Object.ReferenceEquals(x.Captures, null) then [||] - else Microsoft.FSharp.Collections.Array.map (fun (c: obj) -> c.GetType()) x.Captures + member val internal Types: System.Type[] = Unchecked.defaultof with get, set override __.ToString() = value type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>(value:string) = @@ -2247,7 +2246,7 @@ module internal PrintfImpl = && key.Value.Equals (fst Cache<'T, 'State, 'Residue, 'Result>.last) then snd Cache<'T, 'State, 'Residue, 'Result>.last else - let v = get(key.Value, key.GetCaptureTypes()) + let v = get(key.Value, key.Types) Cache<'T, 'State, 'Residue, 'Result>.last <- (key.Value, v) v From 5c6fe9ef4a76899eeee8f14b30596be4309a2606 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Fri, 21 Jun 2019 18:38:37 +0800 Subject: [PATCH 14/19] prepare to work on lexer/parser --- src/Session.vim | 96 +++++++++++++++ src/fsharp/FSharp.Core/Session.vim | 183 ++--------------------------- src/fsharp/ast.fs | 9 +- src/fsharp/pars.fsy | 5 +- 4 files changed, 118 insertions(+), 175 deletions(-) create mode 100644 src/Session.vim diff --git a/src/Session.vim b/src/Session.vim new file mode 100644 index 00000000000..341c1264eb2 --- /dev/null +++ b/src/Session.vim @@ -0,0 +1,96 @@ +let SessionLoad = 1 +let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 +let v:this_session=expand(":p") +silent only +cd D:\git\visualfsharp\src +if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' + let s:wipebuf = bufnr('%') +endif +set shortmess=aoO +badd +262 fsharp\pars.fsy +badd +738 fsharp\lex.fsl +badd +1 fsharp\ast.fs +argglobal +silent! argdel * +edit fsharp\ast.fs +set splitbelow splitright +wincmd _ | wincmd | +vsplit +1wincmd h +wincmd w +set nosplitbelow +set nosplitright +wincmd t +set winminheight=0 +set winheight=1 +set winminwidth=0 +set winwidth=1 +exe 'vert 1resize ' . ((&columns * 120 + 120) / 240) +exe 'vert 2resize ' . ((&columns * 119 + 120) / 240) +argglobal +setlocal fdm=indent +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=10 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +40 +normal! zo +165 +normal! zo +215 +normal! zo +477 +normal! zo +558 +normal! zo +1976 +normal! zo +1991 +normal! zo +2342 +normal! zo +let s:l = 559 - ((44 * winheight(0) + 23) / 47) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +559 +normal! 05| +wincmd w +argglobal +if bufexists("fsharp\ast.fs") | buffer fsharp\ast.fs | else | edit fsharp\ast.fs | endif +setlocal fdm=indent +setlocal fde=0 +setlocal fmr={{{,}}} +setlocal fdi=# +setlocal fdl=10 +setlocal fml=1 +setlocal fdn=20 +setlocal fen +2342 +normal! zo +let s:l = 2344 - ((11 * winheight(0) + 23) / 47) +if s:l < 1 | let s:l = 1 | endif +exe s:l +normal! zt +2344 +normal! 049| +wincmd w +exe 'vert 1resize ' . ((&columns * 120 + 120) / 240) +exe 'vert 2resize ' . ((&columns * 119 + 120) / 240) +tabnext 1 +if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' + silent exe 'bwipe ' . s:wipebuf +endif +unlet! s:wipebuf +set winheight=1 winwidth=20 winminheight=1 winminwidth=1 shortmess=filnxtToOFI +let s:sx = expand(":p:r")."x.vim" +if file_readable(s:sx) + exe "source " . fnameescape(s:sx) +endif +let &so = s:so_save | let &siso = s:siso_save +doautoall SessionLoadPost +unlet SessionLoad +" vim: set ft=vim : diff --git a/src/fsharp/FSharp.Core/Session.vim b/src/fsharp/FSharp.Core/Session.vim index 99edc914f8c..2ab7029a3eb 100644 --- a/src/fsharp/FSharp.Core/Session.vim +++ b/src/fsharp/FSharp.Core/Session.vim @@ -2,22 +2,19 @@ let SessionLoad = 1 let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 let v:this_session=expand(":p") silent only -cd ~\git\visualfsharp\src\fsharp\FSharp.Core +cd D:\git\visualfsharp\src\fsharp\FSharp.Core if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' let s:wipebuf = bufnr('%') endif set shortmess=aoO -badd +1903 printf.fs -badd +1 .vim\coc-settings.json -badd +79 ~\git\visualfsharp\Session.vim +badd +669 printf.fs +badd +26 D:\git\visualfsharp\src\fsharp\lex.fsl +badd +307 D:\git\visualfsharp\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj +badd +0 D:\git\visualfsharp\src\fsharp\pplex.fsl argglobal silent! argdel * -edit printf.fs +edit D:\git\visualfsharp\src\fsharp\pplex.fsl set splitbelow splitright -wincmd _ | wincmd | -split -1wincmd k -wincmd w set nosplitbelow set nosplitright wincmd t @@ -25,8 +22,6 @@ set winminheight=0 set winheight=1 set winminwidth=0 set winwidth=1 -exe '1resize ' . ((&lines * 29 + 30) / 61) -exe '2resize ' . ((&lines * 28 + 30) / 61) argglobal setlocal fdm=indent setlocal fde=0 @@ -36,171 +31,13 @@ setlocal fdl=10 setlocal fml=1 setlocal fdn=20 setlocal fen -29 -normal! zo -279 -normal! zo -1221 -normal! zo -1221 -normal! zc -1318 -normal! zo -1318 -normal! zc -1434 -normal! zo -1434 -normal! zc -1507 -normal! zo -1507 -normal! zc -1557 -normal! zo -1557 -normal! zc -1585 -normal! zc -1595 -normal! zo -1595 -normal! zc -1626 -normal! zo -1626 -normal! zc -1642 -normal! zo -1703 -normal! zo -1712 -normal! zo -1752 -normal! zo -1752 -normal! zc -1791 -normal! zo -1791 -normal! zc -1816 -normal! zo -1816 -normal! zc -1834 -normal! zo -1834 -normal! zc -1878 -normal! zo -1882 -normal! zo -1896 -normal! zo -1925 -normal! zo -1955 -normal! zo -1975 -normal! zo -let s:l = 1894 - ((16 * winheight(0) + 14) / 29) +let s:l = 60 - ((37 * winheight(0) + 23) / 47) if s:l < 1 | let s:l = 1 | endif exe s:l normal! zt -1894 -normal! 0 -lcd ~\git\visualfsharp\src\fsharp\FSharp.Core -wincmd w -argglobal -if bufexists("~\git\visualfsharp\src\fsharp\FSharp.Core\printf.fs") | buffer ~\git\visualfsharp\src\fsharp\FSharp.Core\printf.fs | else | edit ~\git\visualfsharp\src\fsharp\FSharp.Core\printf.fs | endif -setlocal fdm=indent -setlocal fde=0 -setlocal fmr={{{,}}} -setlocal fdi=# -setlocal fdl=10 -setlocal fml=1 -setlocal fdn=20 -setlocal fen -29 -normal! zo -279 -normal! zo -1221 -normal! zo -1221 -normal! zc -1318 -normal! zo -1318 -normal! zc -1434 -normal! zo -1434 -normal! zc -1507 -normal! zo -1507 -normal! zc -1557 -normal! zo -1557 -normal! zc -1585 -normal! zc -1595 -normal! zo -1595 -normal! zc -1626 -normal! zo -1626 -normal! zc -1642 -normal! zo -1703 -normal! zo -1712 -normal! zo -1712 -normal! zc -1752 -normal! zo -1752 -normal! zc -1791 -normal! zo -1791 -normal! zc -1816 -normal! zo -1834 -normal! zo -1834 -normal! zc -1878 -normal! zo -1882 -normal! zo -1896 -normal! zo -1925 -normal! zo -1955 -normal! zo -1975 -normal! zo -let s:l = 1817 - ((122 * winheight(0) + 14) / 28) -if s:l < 1 | let s:l = 1 | endif -exe s:l -normal! zt -1817 -normal! 021| -lcd ~\git\visualfsharp\src\fsharp\FSharp.Core -wincmd w -2wincmd w -exe '1resize ' . ((&lines * 29 + 30) / 61) -exe '2resize ' . ((&lines * 28 + 30) / 61) +60 +normal! 03| +lcd D:\git\visualfsharp\src\fsharp\FSharp.Core tabnext 1 if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' silent exe 'bwipe ' . s:wipebuf diff --git a/src/fsharp/ast.fs b/src/fsharp/ast.fs index 94f40226214..23f0a9f7b65 100644 --- a/src/fsharp/ast.fs +++ b/src/fsharp/ast.fs @@ -801,6 +801,10 @@ and /// 'use x = fixed expr' | Fixed of expr: SynExpr * range: range + /// F# syntax: interpolated string, e.g. "abc%{123}" + | InterpolatedString of text: string * range: range * captures: SynExpr list + + /// Get the syntactic range of source code covered by this construct. member e.Range = match e with @@ -866,7 +870,8 @@ and | SynExpr.LetOrUseBang (range=m) | SynExpr.MatchBang (range=m) | SynExpr.DoBang (range=m) - | SynExpr.Fixed (range=m) -> m + | SynExpr.Fixed (range=m) + | SynExpr.InterpolatedString (range=m) -> m | SynExpr.Ident id -> id.idRange /// range ignoring any (parse error) extra trailing dots @@ -932,6 +937,7 @@ and | SynExpr.LongIdent (_, lidwd, _, _) -> lidwd.RangeSansAnyExtraDot | SynExpr.DiscardAfterMissingQualificationAfterDot (expr, _) -> expr.Range | SynExpr.Fixed (_, m) -> m + | SynExpr.InterpolatedString (range=m) -> m | SynExpr.Ident id -> id.idRange /// Attempt to get the range of the first token or initial portion only - this is extremely ad-hoc, just a cheap way to improve a certain 'query custom operation' error range @@ -993,6 +999,7 @@ and | SynExpr.LetOrUseBang (range=m) | SynExpr.MatchBang (range=m) | SynExpr.DoBang (range=m) -> m + | SynExpr.InterpolatedString (range=m) -> m // these are better than just .Range, and also commonly applicable inside queries | SynExpr.Paren (_, m, _, _) -> m | SynExpr.Sequential (_, _, e1, _, _) diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 4c19b7682d2..32848e0b465 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -156,6 +156,9 @@ let rangeOfLongIdent(lid:LongIdent) = %token BYTEARRAY %token STRING +%token STRING_INTEROP_LEFT +%token STRING_INTEROP_MID +%token STRING_INTEROP_RIGHT %token KEYWORD_STRING // Like __SOURCE_DIRECTORY__ %token IDENT %token INFIX_STAR_STAR_OP @@ -378,7 +381,7 @@ let rangeOfLongIdent(lid:LongIdent) = * - TRUE,FALSE */ %nonassoc prec_atompat_pathop -%nonassoc INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NATIVEINT UNATIVEINT IEEE32 IEEE64 CHAR KEYWORD_STRING STRING BYTEARRAY BIGNUM DECIMAL +%nonassoc INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NATIVEINT UNATIVEINT IEEE32 IEEE64 CHAR KEYWORD_STRING STRING STRING_INTEROP_LEFT STRING_INTEROP_MID STRING_INTEROP_RIGHT BYTEARRAY BIGNUM DECIMAL %nonassoc LPAREN LBRACE LBRACK_BAR %nonassoc TRUE FALSE UNDERSCORE NULL From 41abd26265638830f01aff160c019a3d628242ff Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Tue, 2 Jul 2019 21:35:31 +0800 Subject: [PATCH 15/19] cleanup, ignore vim session files --- .gitignore | 3 ++ Session.vim | 87 ------------------------------ src/fsharp/FSharp.Core/Session.vim | 54 ------------------- 3 files changed, 3 insertions(+), 141 deletions(-) delete mode 100644 Session.vim delete mode 100644 src/fsharp/FSharp.Core/Session.vim diff --git a/.gitignore b/.gitignore index cbf6773ddd1..afba898aa0a 100644 --- a/.gitignore +++ b/.gitignore @@ -125,3 +125,6 @@ tests/fsharpqa/testenv/bin/System.ValueTuple.dll msbuild.binlog /fcs/FSharp.Compiler.Service.netstandard/*.fs /fcs/FSharp.Compiler.Service.netstandard/*.fsi + +# Vim session files +Session.vim diff --git a/Session.vim b/Session.vim deleted file mode 100644 index d560fa36145..00000000000 --- a/Session.vim +++ /dev/null @@ -1,87 +0,0 @@ -let SessionLoad = 1 -let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 -let v:this_session=expand(":p") -silent only -cd ~\git\visualfsharp\src\fsharp\FSharp.Core -if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' - let s:wipebuf = bufnr('%') -endif -set shortmess=aoO -badd +1509 printf.fs -badd +346 ~\AppData\Local\nvim\vsim.vim -argglobal -silent! argdel * -edit printf.fs -set splitbelow splitright -set nosplitbelow -set nosplitright -wincmd t -set winminheight=0 -set winheight=1 -set winminwidth=0 -set winwidth=1 -argglobal -setlocal fdm=indent -setlocal fde=0 -setlocal fmr={{{,}}} -setlocal fdi=# -setlocal fdl=10 -setlocal fml=1 -setlocal fdn=20 -setlocal fen -7 -normal! zo -7 -normal! zo -29 -normal! zo -279 -normal! zo -328 -normal! zo -333 -normal! zo -343 -normal! zo -348 -normal! zo -1392 -normal! zo -1401 -normal! zo -1441 -normal! zo -1542 -normal! zo -1567 -normal! zo -1585 -normal! zo -1613 -normal! zo -1623 -normal! zo -1624 -normal! zo -1749 -normal! zo -let s:l = 1489 - ((28 * winheight(0) + 29) / 58) -if s:l < 1 | let s:l = 1 | endif -exe s:l -normal! zt -1489 -normal! 016| -tabnext 1 -if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' - silent exe 'bwipe ' . s:wipebuf -endif -unlet! s:wipebuf -set winheight=1 winwidth=20 winminheight=1 winminwidth=1 shortmess=filnxtToOF -let s:sx = expand(":p:r")."x.vim" -if file_readable(s:sx) - exe "source " . fnameescape(s:sx) -endif -let &so = s:so_save | let &siso = s:siso_save -doautoall SessionLoadPost -unlet SessionLoad -" vim: set ft=vim : diff --git a/src/fsharp/FSharp.Core/Session.vim b/src/fsharp/FSharp.Core/Session.vim deleted file mode 100644 index 2ab7029a3eb..00000000000 --- a/src/fsharp/FSharp.Core/Session.vim +++ /dev/null @@ -1,54 +0,0 @@ -let SessionLoad = 1 -let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 -let v:this_session=expand(":p") -silent only -cd D:\git\visualfsharp\src\fsharp\FSharp.Core -if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' - let s:wipebuf = bufnr('%') -endif -set shortmess=aoO -badd +669 printf.fs -badd +26 D:\git\visualfsharp\src\fsharp\lex.fsl -badd +307 D:\git\visualfsharp\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj -badd +0 D:\git\visualfsharp\src\fsharp\pplex.fsl -argglobal -silent! argdel * -edit D:\git\visualfsharp\src\fsharp\pplex.fsl -set splitbelow splitright -set nosplitbelow -set nosplitright -wincmd t -set winminheight=0 -set winheight=1 -set winminwidth=0 -set winwidth=1 -argglobal -setlocal fdm=indent -setlocal fde=0 -setlocal fmr={{{,}}} -setlocal fdi=# -setlocal fdl=10 -setlocal fml=1 -setlocal fdn=20 -setlocal fen -let s:l = 60 - ((37 * winheight(0) + 23) / 47) -if s:l < 1 | let s:l = 1 | endif -exe s:l -normal! zt -60 -normal! 03| -lcd D:\git\visualfsharp\src\fsharp\FSharp.Core -tabnext 1 -if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' - silent exe 'bwipe ' . s:wipebuf -endif -unlet! s:wipebuf -set winheight=1 winwidth=20 winminheight=1 winminwidth=1 shortmess=filnxtToOFI -let s:sx = expand(":p:r")."x.vim" -if file_readable(s:sx) - exe "source " . fnameescape(s:sx) -endif -let &so = s:so_save | let &siso = s:siso_save -doautoall SessionLoadPost -unlet SessionLoad -" vim: set ft=vim : From 6e23c9c7f57fe766a1a816dff5a1ab90e5f5bdc1 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Wed, 3 Jul 2019 21:07:27 +0800 Subject: [PATCH 16/19] cleanup, ignore editor config files --- .gitignore | 3 +- src/Session.vim | 96 ------------------- src/fsharp/FSharp.Core/.vim/coc-settings.json | 60 ------------ 3 files changed, 1 insertion(+), 158 deletions(-) delete mode 100644 src/Session.vim delete mode 100644 src/fsharp/FSharp.Core/.vim/coc-settings.json diff --git a/.gitignore b/.gitignore index b504c250345..d3e1c08bf0c 100644 --- a/.gitignore +++ b/.gitignore @@ -127,6 +127,5 @@ msbuild.binlog /fcs/FSharp.Compiler.Service.netstandard/*.fs /fcs/FSharp.Compiler.Service.netstandard/*.fsi /.ionide/ - -# Vim session files Session.vim +coc-settings.json diff --git a/src/Session.vim b/src/Session.vim deleted file mode 100644 index 341c1264eb2..00000000000 --- a/src/Session.vim +++ /dev/null @@ -1,96 +0,0 @@ -let SessionLoad = 1 -let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 -let v:this_session=expand(":p") -silent only -cd D:\git\visualfsharp\src -if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' - let s:wipebuf = bufnr('%') -endif -set shortmess=aoO -badd +262 fsharp\pars.fsy -badd +738 fsharp\lex.fsl -badd +1 fsharp\ast.fs -argglobal -silent! argdel * -edit fsharp\ast.fs -set splitbelow splitright -wincmd _ | wincmd | -vsplit -1wincmd h -wincmd w -set nosplitbelow -set nosplitright -wincmd t -set winminheight=0 -set winheight=1 -set winminwidth=0 -set winwidth=1 -exe 'vert 1resize ' . ((&columns * 120 + 120) / 240) -exe 'vert 2resize ' . ((&columns * 119 + 120) / 240) -argglobal -setlocal fdm=indent -setlocal fde=0 -setlocal fmr={{{,}}} -setlocal fdi=# -setlocal fdl=10 -setlocal fml=1 -setlocal fdn=20 -setlocal fen -40 -normal! zo -165 -normal! zo -215 -normal! zo -477 -normal! zo -558 -normal! zo -1976 -normal! zo -1991 -normal! zo -2342 -normal! zo -let s:l = 559 - ((44 * winheight(0) + 23) / 47) -if s:l < 1 | let s:l = 1 | endif -exe s:l -normal! zt -559 -normal! 05| -wincmd w -argglobal -if bufexists("fsharp\ast.fs") | buffer fsharp\ast.fs | else | edit fsharp\ast.fs | endif -setlocal fdm=indent -setlocal fde=0 -setlocal fmr={{{,}}} -setlocal fdi=# -setlocal fdl=10 -setlocal fml=1 -setlocal fdn=20 -setlocal fen -2342 -normal! zo -let s:l = 2344 - ((11 * winheight(0) + 23) / 47) -if s:l < 1 | let s:l = 1 | endif -exe s:l -normal! zt -2344 -normal! 049| -wincmd w -exe 'vert 1resize ' . ((&columns * 120 + 120) / 240) -exe 'vert 2resize ' . ((&columns * 119 + 120) / 240) -tabnext 1 -if exists('s:wipebuf') && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' - silent exe 'bwipe ' . s:wipebuf -endif -unlet! s:wipebuf -set winheight=1 winwidth=20 winminheight=1 winminwidth=1 shortmess=filnxtToOFI -let s:sx = expand(":p:r")."x.vim" -if file_readable(s:sx) - exe "source " . fnameescape(s:sx) -endif -let &so = s:so_save | let &siso = s:siso_save -doautoall SessionLoadPost -unlet SessionLoad -" vim: set ft=vim : diff --git a/src/fsharp/FSharp.Core/.vim/coc-settings.json b/src/fsharp/FSharp.Core/.vim/coc-settings.json deleted file mode 100644 index 866efb83a6d..00000000000 --- a/src/fsharp/FSharp.Core/.vim/coc-settings.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "fsharp.project.otherFlags": [ - "--warnon:1182", - "--compiling-fslib", - "--compiling-fslib-40", - "--maxerrors:20", - "--extraoptimizationloops:1", - "--tailcalls+", - "--deterministic+", - "--target:library", - "--fullpaths", - "--flaterrors", - "--highentropyva+", - "--targetprofile:netcore", - "--simpleresolution", - "-g", - "--debug:portable", - "--noframework", - "--define:TRACE", - "--define:FSHARP_CORE", - "--define:DEBUG", - "--define:NETSTANDARD", - "--define:FX_NO_APP_DOMAINS", - "--define:FX_NO_ARRAY_LONG_LENGTH", - "--define:FX_NO_BEGINEND_READWRITE", - "--define:FX_NO_BINARY_SERIALIZATION", - "--define:FX_NO_CONVERTER", - "--define:FX_NO_DEFAULT_DEPENDENCY_TYPE", - "--define:FX_NO_CORHOST_SIGNER", - "--define:FX_NO_EVENTWAITHANDLE_IDISPOSABLE", - "--define:FX_NO_EXIT_CONTEXT_FLAGS", - "--define:FX_NO_LINKEDRESOURCES", - "--define:FX_NO_PARAMETERIZED_THREAD_START", - "--define:FX_NO_PDB_READER", - "--define:FX_NO_PDB_WRITER", - "--define:FX_NO_REFLECTION_MODULE_HANDLES", - "--define:FX_NO_REFLECTION_ONLY", - "--define:FX_NO_RUNTIMEENVIRONMENT", - "--define:FX_NO_SECURITY_PERMISSIONS", - "--define:FX_NO_SERVERCODEPAGES", - "--define:FX_NO_SYMBOLSTORE", - "--define:FX_NO_SYSTEM_CONFIGURATION", - "--define:FX_NO_THREAD", - "--define:FX_NO_THREADABORT", - "--define:FX_NO_WAITONE_MILLISECONDS", - "--define:FX_NO_WEB_CLIENT", - "--define:FX_NO_WIN_REGISTRY", - "--define:FX_NO_WINFORMS", - "--define:FX_NO_INDENTED_TEXT_WRITER", - "--define:FX_REDUCED_EXCEPTIONS", - "--define:FX_RESHAPED_REFEMIT", - "--define:FX_RESHAPED_GLOBALIZATION", - "--define:FX_RESHAPED_REFLECTION", - "--define:FX_RESHAPED_MSBUILD", - "--define:NETSTANDARD", - "--define:NETSTANDARD1_6", - "--optimize-" - ], - "fsharp.project.includeCompileBefore": true -} From 07d0fd81506ff23911f99513d6589e63b60e76fd Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Wed, 3 Jul 2019 21:09:44 +0800 Subject: [PATCH 17/19] PopValueUnsafe uppercase --- src/fsharp/FSharp.Core/printf.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 9712032612b..188c96a0083 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -1736,7 +1736,7 @@ module internal PrintfImpl = cont, contTy - member __.popValueUnsafe() = args.Pop() + member __.PopValueUnsafe() = args.Pop() member this.PushContinuationWithType (cont: obj, contTy: Type) = System.Diagnostics.Debug.Assert(this.IsEmpty, "this.IsEmpty") @@ -2216,7 +2216,7 @@ module internal PrintfImpl = let n = parseFromFormatSpecifier prefix s funcTy prefixPos cTy if n = ContinuationOnStack || n = 0 then - builderStack.popValueUnsafe() + builderStack.PopValueUnsafe() else buildPlain n prefix From f75ab75e24c02cd395c57d8263c2fc0a12009603 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Wed, 3 Jul 2019 21:29:57 +0800 Subject: [PATCH 18/19] PrintFormat: capture fields should be immutable --- src/fsharp/FSharp.Core/printf.fs | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 188c96a0083..2ff1f304880 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -2,23 +2,16 @@ namespace Microsoft.FSharp.Core -type PrintfFormat<'Printer,'State,'Residue,'Result>(value:string) = - - internal new(value, caps, types) as this = - PrintfFormat<_,_,_,_>(value) - then this.Captures <- caps - this.Types <- types - - member __.Value = value - member val internal Captures: obj[] = Unchecked.defaultof with get, set - member val internal Types: System.Type[] = Unchecked.defaultof with get, set - override __.ToString() = value - -type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>(value:string) = - inherit PrintfFormat<'Printer,'State,'Residue,'Result>(value) - internal new(value, caps) as this = - PrintfFormat<_,_,_,_,_>(value) - then this.Captures <- caps +type PrintfFormat<'Printer,'State,'Residue,'Result>(value: string, captures: obj[], types: Type[]) = + new(value) = new PrintfFormat<'Printer,'State,'Residue,'Result>(value, null, null) + member __.Value = value + member __.Captures = captures + member __.Types = types + override __.ToString() = value + +type PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple>(value: string, captures: obj[], types: Type[]) = + inherit PrintfFormat<'Printer,'State,'Residue,'Result>(value, captures, types) + new(value) = new PrintfFormat<'Printer,'State,'Residue,'Result, 'Tuple>(value, null, null) type Format<'Printer,'State,'Residue,'Result> = PrintfFormat<'Printer,'State,'Residue,'Result> type Format<'Printer,'State,'Residue,'Result,'Tuple> = PrintfFormat<'Printer,'State,'Residue,'Result,'Tuple> From fadb047fc8947da8b80127ad19361996e6f52243 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Thu, 4 Jul 2019 15:43:23 +0800 Subject: [PATCH 19/19] printf: Type is in System namespace --- src/fsharp/FSharp.Core/printf.fs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 2ff1f304880..909144f7922 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -2,6 +2,8 @@ namespace Microsoft.FSharp.Core +open System + type PrintfFormat<'Printer,'State,'Residue,'Result>(value: string, captures: obj[], types: Type[]) = new(value) = new PrintfFormat<'Printer,'State,'Residue,'Result>(value, null, null) member __.Value = value