-
-
Save brianrourkeboll/c76c868ece9e512b427b6b708142450a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open System | |
open BenchmarkDotNet.Attributes | |
open BenchmarkDotNet.Running | |
type token = | |
| DOT_DOT | |
| DOT | |
| RBRACK | |
| MINUS | |
| QMARK_QMARK | |
| QMARK | |
| COLON_EQUALS | |
| COLON_COLON | |
| STAR | |
| START | |
| AMP | |
| RARROW | |
| LARROW | |
| EQUALS | |
| LESS of bool | |
| DOLLAR | |
| PERCENT_OP of string | |
| INFIX_COMPARE_OP of string | |
| INFIX_AMP_OP of string | |
| INFIX_BAR_OP of string | |
| PREFIX_OP of string | |
| INFIX_AT_HAT_OP of string | |
| PLUS_MINUS_OP of string | |
| INFIX_STAR_STAR_OP of string | |
| INFIX_STAR_DIV_MOD_OP of string | |
| GREATER of bool | |
module Option = | |
let (|TyparsCloseOp|_|) (txt: string) = | |
let angles = txt |> Seq.takeWhile (fun c -> c = '>') |> Seq.toList | |
let afterAngles = txt |> Seq.skipWhile (fun c -> c = '>') |> Seq.toList | |
if List.isEmpty angles then None else | |
let afterOp = | |
match (System.String(Array.ofSeq afterAngles)) with | |
| "." -> Some DOT | |
| "]" -> Some RBRACK | |
| "-" -> Some MINUS | |
| ".." -> Some DOT_DOT | |
| "?" -> Some QMARK | |
| "??" -> Some QMARK_QMARK | |
| ":=" -> Some COLON_EQUALS | |
| "::" -> Some COLON_COLON | |
| "*" -> Some STAR | |
| "&" -> Some AMP | |
| "->" -> Some RARROW | |
| "<-" -> Some LARROW | |
| "=" -> Some EQUALS | |
| "<" -> Some (LESS false) | |
| "$" -> Some DOLLAR | |
| "%" -> Some (PERCENT_OP("%") ) | |
| "%%" -> Some (PERCENT_OP("%%")) | |
| "" -> None | |
| s -> | |
match List.ofSeq afterAngles with | |
| '=' :: _ | |
| '!' :: '=' :: _ | |
| '<' :: _ | |
| '>' :: _ | |
| '$' :: _ -> Some (INFIX_COMPARE_OP s) | |
| '&' :: _ -> Some (INFIX_AMP_OP s) | |
| '|' :: _ -> Some (INFIX_BAR_OP s) | |
| '!' :: _ | |
| '?' :: _ | |
| '~' :: _ -> Some (PREFIX_OP s) | |
| '@' :: _ | |
| '^' :: _ -> Some (INFIX_AT_HAT_OP s) | |
| '+' :: _ | |
| '-' :: _ -> Some (PLUS_MINUS_OP s) | |
| '*' :: '*' :: _ -> Some (INFIX_STAR_STAR_OP s) | |
| '*' :: _ | |
| '/' :: _ | |
| '%' :: _ -> Some (INFIX_STAR_DIV_MOD_OP s) | |
| _ -> None | |
Some([| for _c in angles do yield GREATER |], afterOp) | |
module ValueOption = | |
[<return: Struct>] | |
let (|TyparsCloseOp|_|) (txt: string) = | |
let angles = txt |> Seq.takeWhile (fun c -> c = '>') |> Seq.toList | |
let afterAngles = txt |> Seq.skipWhile (fun c -> c = '>') |> Seq.toList | |
if List.isEmpty angles then ValueNone else | |
let afterOp = | |
match (System.String(Array.ofSeq afterAngles)) with | |
| "." -> ValueSome DOT | |
| "]" -> ValueSome RBRACK | |
| "-" -> ValueSome MINUS | |
| ".." -> ValueSome DOT_DOT | |
| "?" -> ValueSome QMARK | |
| "??" -> ValueSome QMARK_QMARK | |
| ":=" -> ValueSome COLON_EQUALS | |
| "::" -> ValueSome COLON_COLON | |
| "*" -> ValueSome STAR | |
| "&" -> ValueSome AMP | |
| "->" -> ValueSome RARROW | |
| "<-" -> ValueSome LARROW | |
| "=" -> ValueSome EQUALS | |
| "<" -> ValueSome (LESS false) | |
| "$" -> ValueSome DOLLAR | |
| "%" -> ValueSome (PERCENT_OP("%") ) | |
| "%%" -> ValueSome (PERCENT_OP("%%")) | |
| "" -> ValueNone | |
| s -> | |
match List.ofSeq afterAngles with | |
| '=' :: _ | |
| '!' :: '=' :: _ | |
| '<' :: _ | |
| '>' :: _ | |
| '$' :: _ -> ValueSome (INFIX_COMPARE_OP s) | |
| '&' :: _ -> ValueSome (INFIX_AMP_OP s) | |
| '|' :: _ -> ValueSome (INFIX_BAR_OP s) | |
| '!' :: _ | |
| '?' :: _ | |
| '~' :: _ -> ValueSome (PREFIX_OP s) | |
| '@' :: _ | |
| '^' :: _ -> ValueSome (INFIX_AT_HAT_OP s) | |
| '+' :: _ | |
| '-' :: _ -> ValueSome (PLUS_MINUS_OP s) | |
| '*' :: '*' :: _ -> ValueSome (INFIX_STAR_STAR_OP s) | |
| '*' :: _ | |
| '/' :: _ | |
| '%' :: _ -> ValueSome (INFIX_STAR_DIV_MOD_OP s) | |
| _ -> ValueNone | |
ValueSome([| for _c in angles do yield GREATER |], afterOp) | |
module Simplified = | |
[<return: Struct>] | |
let (|Equals|_|) (s: string) (span: ReadOnlySpan<char>) = | |
if span.SequenceEqual(s.AsSpan()) then ValueSome Equals | |
else ValueNone | |
[<return: Struct>] | |
let (|StartsWith|_|) (s: string) (span: ReadOnlySpan<char>) = | |
if span.StartsWith(s.AsSpan()) then ValueSome StartsWith | |
else ValueNone | |
[<return: Struct>] | |
let (|TyparsCloseOp|_|) (txt: string) = | |
let angles = txt.AsSpan().IndexOfAnyExcept '>' | |
if angles < 0 then ValueNone else | |
let afterAngles = txt.AsSpan angles | |
let afterOp = | |
match afterAngles with | |
| Equals "." -> ValueSome DOT | |
| Equals "]" -> ValueSome RBRACK | |
| Equals "-" -> ValueSome MINUS | |
| Equals ".." -> ValueSome DOT_DOT | |
| Equals "?" -> ValueSome QMARK | |
| Equals "??" -> ValueSome QMARK_QMARK | |
| Equals ":=" -> ValueSome COLON_EQUALS | |
| Equals "::" -> ValueSome COLON_COLON | |
| Equals "*" -> ValueSome STAR | |
| Equals "&" -> ValueSome AMP | |
| Equals "->" -> ValueSome RARROW | |
| Equals "<-" -> ValueSome LARROW | |
| Equals "=" -> ValueSome EQUALS | |
| Equals "<" -> ValueSome (LESS false) | |
| Equals "$" -> ValueSome DOLLAR | |
| Equals "%" -> ValueSome (PERCENT_OP "%") | |
| Equals "%%" -> ValueSome (PERCENT_OP "%%") | |
| StartsWith "=" | |
| StartsWith "!=" | |
| StartsWith "<" | |
| StartsWith ">" | |
| StartsWith "$" -> ValueSome (INFIX_COMPARE_OP (afterAngles.ToString())) | |
| StartsWith "&" -> ValueSome (INFIX_AMP_OP (afterAngles.ToString())) | |
| StartsWith "|" -> ValueSome (INFIX_BAR_OP (afterAngles.ToString())) | |
| StartsWith "!" | |
| StartsWith "?" | |
| StartsWith "~" -> ValueSome (PREFIX_OP (afterAngles.ToString())) | |
| StartsWith "@" | |
| StartsWith "^" -> ValueSome (INFIX_AT_HAT_OP (afterAngles.ToString())) | |
| StartsWith "+" | |
| StartsWith "-" -> ValueSome (PLUS_MINUS_OP (afterAngles.ToString())) | |
| StartsWith "**" -> ValueSome (INFIX_STAR_STAR_OP (afterAngles.ToString())) | |
| StartsWith "*" | |
| StartsWith "/" | |
| StartsWith "%" -> ValueSome (INFIX_STAR_DIV_MOD_OP (afterAngles.ToString())) | |
| _ -> ValueNone | |
ValueSome(Array.init angles (fun _ -> GREATER), afterOp) | |
[<MemoryDiagnoser>] | |
type Benchmarks () = | |
[<Params(">=", ">>>>>>>>>>>>>>:=", ">>>!=*+-%^@@@@.........")>] | |
member val Input : string = null with get, set | |
[<Benchmark(Baseline = true)>] | |
member this.Option () = match this.Input with Option.TyparsCloseOp _ | _ -> () | |
[<Benchmark>] | |
member this.ValueOption () = match this.Input with ValueOption.TyparsCloseOp _ | _ -> () | |
[<Benchmark>] | |
member this.Simplified () = match this.Input with Simplified.TyparsCloseOp _ | _ -> () | |
ignore (BenchmarkRunner.Run<Benchmarks> ()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment