Skip to content

Commit 48487f9

Browse files
authored
Better hiding of internals in parsing (#445)
1 parent a5556b3 commit 48487f9

File tree

1 file changed

+104
-117
lines changed

1 file changed

+104
-117
lines changed

src/FSharpPlus/Parsing.fs

Lines changed: 104 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -2,135 +2,122 @@
22

33
#if !FABLE_COMPILER
44

5-
open FSharpPlus.Internals
6-
7-
85
[<AutoOpen>]
96
module Parsing =
107

11-
// From https://gist.github.com/gusty/2810b0cc7f8bf89f614facaf121fcaa4
12-
13-
/// [omit]
14-
module Internals =
15-
16-
open System
17-
open System.Text.RegularExpressions
18-
open FSharpPlus
19-
open FSharpPlus.Internals.Prelude
8+
open System
9+
open System.Text.RegularExpressions
10+
open FSharpPlus
11+
open FSharpPlus.Internals
12+
open FSharpPlus.Internals.Prelude
2013

14+
let inline private getGroups (pf: PrintfFormat<_,_,_,_,_>) s =
2115
let formatters = [|"%A"; "%b"; "%B"; "%c"; "%d"; "%e"; "%E"; "%f"; "%F"; "%g"; "%G"; "%i"; "%M"; "%o"; "%O"; "%s"; "%u"; "%x"; "%X"|]
22-
23-
let getGroups (pf: PrintfFormat<_,_,_,_,_>) s =
24-
let formatStr = replace "%%" "%" pf.Value
25-
let constants = split formatters formatStr
26-
let regex = Regex ("^" + String.Join ("(.*?)", constants |> Array.map Regex.Escape) + "$")
27-
let getGroup x =
28-
let groups =
16+
let formatStr = replace "%%" "%" pf.Value
17+
let constants = split formatters formatStr
18+
let regex = Regex ("^" + String.Join ("(.*?)", constants |> Array.map Regex.Escape) + "$")
19+
let getGroup x =
20+
let groups =
2921
regex.Match(x).Groups
3022
|> Seq.cast<Group>
3123
|> Seq.skip 1
32-
groups
24+
groups
3325
|> Seq.map (fun g -> g.Value)
3426
|> Seq.toArray
35-
(getGroup s, getGroup pf.Value) ||> Array.zipShortest
36-
37-
let conv (destType: System.Type) (b: int) (s: string) =
38-
match destType with
39-
| t when t = typeof<byte> -> Convert.ToByte (s, b) |> box
40-
| t when t = typeof<uint16> -> Convert.ToUInt16 (s, b) |> box
41-
| t when t = typeof<uint32> -> Convert.ToUInt32 (s, b) |> box
42-
| t when t = typeof<uint64> -> Convert.ToUInt64 (s, b) |> box
43-
| t when t = typeof<sbyte> -> Convert.ToSByte (s, b) |> box
44-
| t when t = typeof<int16> -> Convert.ToInt16 (s, b) |> box
45-
| t when t = typeof<int> -> Convert.ToInt32 (s, b) |> box
46-
| t when t = typeof<int64> -> Convert.ToInt64 (s, b) |> box
47-
| _ -> invalidOp (sprintf "Type conversion from string to type %A with base %i is not supported" destType b)
48-
27+
(getGroup s, getGroup pf.Value) ||> Array.zipShortest
28+
29+
let inline private conv (destType: System.Type) (b: int) (s: string) =
30+
match destType with
31+
| t when t = typeof<byte> -> Convert.ToByte (s, b) |> box
32+
| t when t = typeof<uint16> -> Convert.ToUInt16 (s, b) |> box
33+
| t when t = typeof<uint32> -> Convert.ToUInt32 (s, b) |> box
34+
| t when t = typeof<uint64> -> Convert.ToUInt64 (s, b) |> box
35+
| t when t = typeof<sbyte> -> Convert.ToSByte (s, b) |> box
36+
| t when t = typeof<int16> -> Convert.ToInt16 (s, b) |> box
37+
| t when t = typeof<int> -> Convert.ToInt32 (s, b) |> box
38+
| t when t = typeof<int64> -> Convert.ToInt64 (s, b) |> box
39+
| _ -> invalidOp (sprintf "Type conversion from string to type %A with base %i is not supported" destType b)
4940

50-
let inline parse (s: string, f: string) : 'r =
51-
match f with
52-
| "%B" -> conv typeof<'r> 2 s |> string |> parse
53-
| "%o" -> conv typeof<'r> 8 s |> string |> parse
54-
| "%x" | "%X" -> conv typeof<'r> 16 s |> string |> parse
55-
| _ -> parse s
56-
57-
let inline tryParse (s: string, f: string) : 'r option =
58-
match f with
59-
| "%B" -> Option.protect (conv typeof<'r> 2) s |> Option.map string |> Option.bind tryParse
60-
| "%o" -> Option.protect (conv typeof<'r> 8) s |> Option.map string |> Option.bind tryParse
61-
| "%x" | "%X" -> Option.protect (conv typeof<'r> 16) s |> Option.map string |> Option.bind tryParse
62-
| _ -> tryParse s
41+
let inline private parse (s: string, f: string) : 'r =
42+
match f with
43+
| "%B" -> conv typeof<'r> 2 s |> string |> parse
44+
| "%o" -> conv typeof<'r> 8 s |> string |> parse
45+
| "%x" | "%X" -> conv typeof<'r> 16 s |> string |> parse
46+
| _ -> parse s
47+
48+
let inline private tryParse (s: string, f: string) : 'r option =
49+
match f with
50+
| "%B" -> Option.protect (conv typeof<'r> 2) s |> Option.map string |> Option.bind tryParse
51+
| "%o" -> Option.protect (conv typeof<'r> 8) s |> Option.map string |> Option.bind tryParse
52+
| "%x" | "%X" -> Option.protect (conv typeof<'r> 16) s |> Option.map string |> Option.bind tryParse
53+
| _ -> tryParse s
6354

64-
type ParseArray =
65-
static member inline ParseArray (_: 't , _: obj) = fun (g: (string * string) []) -> (parse (g.[0])) : 't
66-
67-
static member inline Invoke (g: (string * string) []) =
68-
let inline call_2 (a: ^a, b: ^b) = ((^a or ^b) : (static member ParseArray: _*_ -> _) b, a) g
69-
let inline call (a: 'a) = call_2 (a, Unchecked.defaultof<'r>) : 'r
70-
call Unchecked.defaultof<ParseArray>
71-
72-
static member inline ParseArray (t: 't, _: ParseArray) = fun (g: (string * string) []) ->
73-
let _f _ = Constraints.whenNestedTuple t : ('t1*'t2*'t3*'t4*'t5*'t6*'t7*'tr)
74-
let (t1: 't1) = parse (g.[0])
75-
let (t2: 't2) = parse (g.[1])
76-
let (t3: 't3) = parse (g.[2])
77-
let (t4: 't4) = parse (g.[3])
78-
let (t5: 't5) = parse (g.[4])
79-
let (t6: 't6) = parse (g.[5])
80-
let (t7: 't7) = parse (g.[6])
81-
let (tr: 'tr) = ParseArray.Invoke (g.[7..])
82-
Tuple<_,_,_,_,_,_,_,_> (t1, t2, t3, t4, t5, t6, t7, tr) |> retype : 't
83-
84-
static member inline ParseArray (_: unit , _: ParseArray) = fun (_: (string * string) []) -> ()
85-
static member inline ParseArray (_: Tuple<'t1> , _: ParseArray) = fun (g: (string * string) []) -> Tuple<_> (parse g.[0]) : Tuple<'t1>
86-
static member inline ParseArray (_: Id<'t1> , _: ParseArray) = fun (g: (string * string) []) -> Id<_> (parse g.[0])
87-
static member inline ParseArray (_: 't1*'t2 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1]
88-
static member inline ParseArray (_: 't1*'t2'*'t3 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2]
89-
static member inline ParseArray (_: 't1*'t2'*'t3*'t4 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2], parse g.[3]
90-
static member inline ParseArray (_: 't1*'t2'*'t3*'t4*'t5 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2], parse g.[3], parse g.[4]
91-
static member inline ParseArray (_: 't1*'t2'*'t3*'t4*'t5*'t6 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2], parse g.[3], parse g.[4], parse g.[5]
92-
static member inline ParseArray (_: 't1*'t2'*'t3*'t4*'t5*'t6*'t7, _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2], parse g.[3], parse g.[4], parse g.[5], parse g.[6]
93-
94-
let inline tryParseElemAt i (g: (string * string) []) =
95-
if i < Array.length g then tryParse (g.[i])
96-
else None
97-
98-
type TryParseArray =
99-
static member inline TryParseArray (_:'t, _:obj) = fun (g: (string * string) []) -> tryParseElemAt 0 g : 't option
100-
101-
static member inline Invoke (g: (string * string) []) =
102-
let inline call_2 (a: ^a, b: ^b) = ((^a or ^b) : (static member TryParseArray: _*_ -> _) b, a) g
103-
let inline call (a: 'a) = call_2 (a, Unchecked.defaultof<'r>) : 'r option
104-
call Unchecked.defaultof<TryParseArray>
105-
106-
static member inline TryParseArray (t: 't, _: TryParseArray) = fun (g: (string * string) []) ->
107-
let _f _ = Constraints.whenNestedTuple t : ('t1*'t2*'t3*'t4*'t5*'t6*'t7*'tr)
108-
let (t1: 't1 option) = tryParseElemAt 0 g
109-
let (t2: 't2 option) = tryParseElemAt 1 g
110-
let (t3: 't3 option) = tryParseElemAt 2 g
111-
let (t4: 't4 option) = tryParseElemAt 3 g
112-
let (t5: 't5 option) = tryParseElemAt 4 g
113-
let (t6: 't6 option) = tryParseElemAt 5 g
114-
let (t7: 't7 option) = tryParseElemAt 6 g
115-
let (tr: 'tr option) = if g.Length > 7 then TryParseArray.Invoke (g.[7..]) else None
116-
match t1, t2, t3, t4, t5, t6, t7, tr with
117-
| Some t1, Some t2, Some t3, Some t4, Some t5, Some t6, Some t7, Some tr -> Some (Tuple<_,_,_,_,_,_,_,_> (t1, t2, t3, t4, t5, t6, t7, tr) |> retype : 't)
118-
| _ -> None
119-
120-
static member inline TryParseArray (_: unit , _: TryParseArray) = fun (_: (string * string) []) -> ()
121-
122-
static member inline TryParseArray (_: Tuple<'t1> , _: TryParseArray) = fun (g: (string * string) []) -> Tuple<_> <!> tryParseElemAt 0 g : Tuple<'t1> option
123-
static member inline TryParseArray (_: Id<'t1> , _: TryParseArray) = fun (g: (string * string) []) -> Id<_> <!> tryParseElemAt 0 g
124-
static member inline TryParseArray (_: 't1*'t2 , _: TryParseArray) = fun (g: (string * string) []) -> tuple2 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g
125-
static member inline TryParseArray (_: 't1*'t2'*'t3 , _: TryParseArray) = fun (g: (string * string) []) -> tuple3 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g
126-
static member inline TryParseArray (_: 't1*'t2'*'t3*'t4 , _: TryParseArray) = fun (g: (string * string) []) -> tuple4 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g <*> tryParseElemAt 3 g
127-
static member inline TryParseArray (_: 't1*'t2'*'t3*'t4*'t5 , _: TryParseArray) = fun (g: (string * string) []) -> tuple5 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g <*> tryParseElemAt 3 g <*> tryParseElemAt 4 g
128-
static member inline TryParseArray (_: 't1*'t2'*'t3*'t4*'t5*'t6 , _: TryParseArray) = fun (g: (string * string) []) -> tuple6 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g <*> tryParseElemAt 3 g <*> tryParseElemAt 4 g <*> tryParseElemAt 5 g
129-
static member inline TryParseArray (_: 't1*'t2'*'t3*'t4*'t5*'t6*'t7, _: TryParseArray) = fun (g: (string * string) []) -> tuple7 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g <*> tryParseElemAt 3 g <*> tryParseElemAt 4 g <*> tryParseElemAt 5 g <*> tryParseElemAt 6 g
130-
131-
132-
open Internals
133-
open System
55+
type ParseArray =
56+
static member inline ParseArray (_: 't , _: obj) = fun (g: (string * string) []) -> (parse (g.[0])) : 't
57+
58+
static member inline Invoke (g: (string * string) []) =
59+
let inline call_2 (a: ^a, b: ^b) = ((^a or ^b) : (static member ParseArray: _*_ -> _) b, a) g
60+
let inline call (a: 'a) = call_2 (a, Unchecked.defaultof<'r>) : 'r
61+
call Unchecked.defaultof<ParseArray>
62+
63+
static member inline ParseArray (t: 't, _: ParseArray) = fun (g: (string * string) []) ->
64+
let _f _ = Constraints.whenNestedTuple t : ('t1*'t2*'t3*'t4*'t5*'t6*'t7*'tr)
65+
let (t1: 't1) = parse (g.[0])
66+
let (t2: 't2) = parse (g.[1])
67+
let (t3: 't3) = parse (g.[2])
68+
let (t4: 't4) = parse (g.[3])
69+
let (t5: 't5) = parse (g.[4])
70+
let (t6: 't6) = parse (g.[5])
71+
let (t7: 't7) = parse (g.[6])
72+
let (tr: 'tr) = ParseArray.Invoke (g.[7..])
73+
Tuple<_,_,_,_,_,_,_,_> (t1, t2, t3, t4, t5, t6, t7, tr) |> retype : 't
74+
75+
static member inline ParseArray (_: unit , _: ParseArray) = fun (_: (string * string) []) -> ()
76+
static member inline ParseArray (_: Tuple<'t1> , _: ParseArray) = fun (g: (string * string) []) -> Tuple<_> (parse g.[0]) : Tuple<'t1>
77+
static member inline ParseArray (_: Id<'t1> , _: ParseArray) = fun (g: (string * string) []) -> Id<_> (parse g.[0])
78+
static member inline ParseArray (_: 't1*'t2 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1]
79+
static member inline ParseArray (_: 't1*'t2'*'t3 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2]
80+
static member inline ParseArray (_: 't1*'t2'*'t3*'t4 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2], parse g.[3]
81+
static member inline ParseArray (_: 't1*'t2'*'t3*'t4*'t5 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2], parse g.[3], parse g.[4]
82+
static member inline ParseArray (_: 't1*'t2'*'t3*'t4*'t5*'t6 , _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2], parse g.[3], parse g.[4], parse g.[5]
83+
static member inline ParseArray (_: 't1*'t2'*'t3*'t4*'t5*'t6*'t7, _: ParseArray) = fun (g: (string * string) []) -> parse g.[0], parse g.[1], parse g.[2], parse g.[3], parse g.[4], parse g.[5], parse g.[6]
84+
85+
let inline private tryParseElemAt i (g: (string * string) []) =
86+
if i < Array.length g then tryParse (g.[i])
87+
else None
88+
89+
type TryParseArray =
90+
static member inline TryParseArray (_:'t, _:obj) = fun (g: (string * string) []) -> tryParseElemAt 0 g : 't option
91+
92+
static member inline Invoke (g: (string * string) []) =
93+
let inline call_2 (a: ^a, b: ^b) = ((^a or ^b) : (static member TryParseArray: _*_ -> _) b, a) g
94+
let inline call (a: 'a) = call_2 (a, Unchecked.defaultof<'r>) : 'r option
95+
call Unchecked.defaultof<TryParseArray>
96+
97+
static member inline TryParseArray (t: 't, _: TryParseArray) = fun (g: (string * string) []) ->
98+
let _f _ = Constraints.whenNestedTuple t : ('t1*'t2*'t3*'t4*'t5*'t6*'t7*'tr)
99+
let (t1: 't1 option) = tryParseElemAt 0 g
100+
let (t2: 't2 option) = tryParseElemAt 1 g
101+
let (t3: 't3 option) = tryParseElemAt 2 g
102+
let (t4: 't4 option) = tryParseElemAt 3 g
103+
let (t5: 't5 option) = tryParseElemAt 4 g
104+
let (t6: 't6 option) = tryParseElemAt 5 g
105+
let (t7: 't7 option) = tryParseElemAt 6 g
106+
let (tr: 'tr option) = if g.Length > 7 then TryParseArray.Invoke (g.[7..]) else None
107+
match t1, t2, t3, t4, t5, t6, t7, tr with
108+
| Some t1, Some t2, Some t3, Some t4, Some t5, Some t6, Some t7, Some tr -> Some (Tuple<_,_,_,_,_,_,_,_> (t1, t2, t3, t4, t5, t6, t7, tr) |> retype : 't)
109+
| _ -> None
110+
111+
static member inline TryParseArray (_: unit , _: TryParseArray) = fun (_: (string * string) []) -> ()
112+
static member inline TryParseArray (_: Tuple<'t1> , _: TryParseArray) = fun (g: (string * string) []) -> Tuple<_> <!> tryParseElemAt 0 g : Tuple<'t1> option
113+
static member inline TryParseArray (_: Id<'t1> , _: TryParseArray) = fun (g: (string * string) []) -> Id<_> <!> tryParseElemAt 0 g
114+
static member inline TryParseArray (_: 't1*'t2 , _: TryParseArray) = fun (g: (string * string) []) -> tuple2 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g
115+
static member inline TryParseArray (_: 't1*'t2'*'t3 , _: TryParseArray) = fun (g: (string * string) []) -> tuple3 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g
116+
static member inline TryParseArray (_: 't1*'t2'*'t3*'t4 , _: TryParseArray) = fun (g: (string * string) []) -> tuple4 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g <*> tryParseElemAt 3 g
117+
static member inline TryParseArray (_: 't1*'t2'*'t3*'t4*'t5 , _: TryParseArray) = fun (g: (string * string) []) -> tuple5 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g <*> tryParseElemAt 3 g <*> tryParseElemAt 4 g
118+
static member inline TryParseArray (_: 't1*'t2'*'t3*'t4*'t5*'t6 , _: TryParseArray) = fun (g: (string * string) []) -> tuple6 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g <*> tryParseElemAt 3 g <*> tryParseElemAt 4 g <*> tryParseElemAt 5 g
119+
static member inline TryParseArray (_: 't1*'t2'*'t3*'t4*'t5*'t6*'t7, _: TryParseArray) = fun (g: (string * string) []) -> tuple7 <!> tryParseElemAt 0 g <*> tryParseElemAt 1 g <*> tryParseElemAt 2 g <*> tryParseElemAt 3 g <*> tryParseElemAt 4 g <*> tryParseElemAt 5 g <*> tryParseElemAt 6 g
120+
134121

135122
/// Gets a tuple with the result of parsing each element of a string array.
136123
let inline parseArray (source: string []) : '``(T1 * T2 * ... * Tn)`` = ParseArray.Invoke (Array.map (fun x -> (x, "")) source)

0 commit comments

Comments
 (0)