-
-
Notifications
You must be signed in to change notification settings - Fork 193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't crash with StackoverflowException when long triple-quoted strings are parsed #1838
Conversation
Thank you for the report of #1837 and this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I were being super nitpicky, I'd insist on a more efficient helper function that doesn't involve indexing three times into the same list. The following is completely untested and may not even type check:
let splitAt<'a> (n : int) (xs : 'a list) : ('a list * ('a * 'a list) option) option =
let rec go n heads rest =
if n = 0 then
match rest with
| [] -> Some (List.rev heads, None)
| x :: rest -> Some (List.rev heads, x, Some rest)
else
match rest with
| [] -> None
| x :: rest ->
go (n - 1) (x :: heads) rest
go n [] xs
Thanks @Smaug123. I'm an F# noob so nitpicky is good for my learning. I had the same concerns about indexing into an F# list and played around with a couple of things:
I'll play around with your suggestion over the weekend. |
Late to the party, but I suggest to simplify this to something along the lines: let private (|MultipleStringTextTokens|_|) tokens =
let f =
function
| StringTextToken _ -> true
| _ -> false
tokens
|> List.takeWhile f
|> fun xs ->
if List.isEmpty xs then
None
else
Some(xs, List.skipWhile f tokens)
let private (|EndOfInterpolatedString|_|) tokens =
match tokens with
| MultipleStringTextTokens (stringTokens, rest) ->
match rest with
| InterpStringEndOrPartToken endToken :: rest2 -> Some(stringTokens, endToken, rest2)
| _ -> None
| _ -> None Perf of above can be improved by some utility function that returns |
OK all, I've applied feedback. I tried both implementations. My latest commit takes the approach @jindraivanek and removes the |
Hi Kent, many thanks again for your time and patience to solve this issue. |
@nojaf Done! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
Many thanks @kentcb for this contribution! |
Modifies the algorithm for the
EndOfInterpolatedString
active pattern so that it is non-recursive. I do not see a way of keeping the recursion whilst attaining tail-call (nor do I like the fact that the compiler can't yet enforce tail-call recursion, so accidental breakage is too real a risk)Fixes #1837