-
Notifications
You must be signed in to change notification settings - Fork 790
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
[RFC FS-1001 POC] String Interpolation [WIP] #6770
Conversation
Status
ScratchpadLine 2641 in 8397008
Looks like this is the master entry for "r-values"?
|
Anything I should do at the moment? |
I've signed the CLA. Working on |
cool stuff :) |
Tagging @dsyme for design review |
@realvictorprm @forki I'm wondering if we could team up on this? |
@yatli convinced, are you on the F# Slack? |
@realvictorprm yeah, I've just joined |
Well, that was long time ago ;-)
Any concrete questions or things you want me to do?
Yatao Li <notifications@github.com> schrieb am Do., 20. Juni 2019, 13:18:
… @realvictorprm <https://github.com/realvictorprm> yeah, I've just joined
FSF FSSF :D
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#6770?email_source=notifications&email_token=AAAOANBEPBMCJSA4U5ENGCTP3NRRDA5CNFSM4HNZ2MP2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODYFDSZY#issuecomment-503986535>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAAOANHF5LWWHP5PJT4LJYLP3NRRDANCNFSM4HNZ2MPQ>
.
|
@forki no worry, one question for now: |
There are a lot of design discussions going on here. Can we capture some of this in an RFC? I think I generally agree with the direction and @dsyme suggestions here. But there are some sub-points that would need a separate design discussion. For example, for verbatim interoplated strings, what about both Additionally we'd have to adjust tooling to account for understanding when we're in an interoplated context (and complete the |
@cartermp yes I agree. There are details that are not covered in FS-1001, some of these points are already well-aligned, and some needs further convergence. I'm listing some of the well aligned points here (may have missed something):
The thing that still doesn't come to its fixed-point in my head is, whether the interpolated form should be a The former incorporates well with the printf family, while the latter is more of the "embracing the C# way" style. I prefer the former because, it implies that we plant our support for Some complexities in extending the printf family: |
@cartermp I will rewrite FS-1001 today |
@dsyme shall we split out the proposal to extend |
It would be great to get it all in together, as a complete package, but I think it depends on whether you feel it fits into the implementation and testing reasonably. |
I'd love to do it altogether -- just want to make sure that this is indeed the plan :) |
Could we make it that both interpolated and non-interpolated strings are considered compatible with all of these, depending on the known type from type checking?
I think it would just really surprise people if non-interoplated strings could ever have interpolation fills when used as printf-style format strings. Also not backwards compatible is it, if the format for interpolation is
Yes, I agree with this
My thinking was that
So you could have
yes
I think pretty much no one uses BTW you can find me on F# Software Foundation Slack and we can chat there if you like |
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.
Just adding a few comments
@yatli Have you been able to make more progress here? Is there anything we can help with? |
@dsyme thanks for getting back :) |
it'll be great if we can do some coding together :) |
Can you msg me on FSSF Slack? Maybe late August |
Now is 2020, Is there any new progress on string interpolation? It's quite a practical feature😀 |
Hi @yatli, I'm thinking of taking another look at this. Would you like to still work on it with me for the next iteration? |
(I'm starting with prototyping the lexer and parser changes) |
@yatli I'm going to close this PR and start a new one coming from a feature branch |
Replaced by #8907 |
sounds great! |
Continued at #8907 |
Planning
This is the beginning of my take on FS-1001 (fsharp/fslang-design#6, fsharp/fslang-design#368) -- I have just started to code it, but I'd like to know what you think.
In this thread, I will interchangeably call the original formatting specifiers "deferred specifier", and inline interpolations "immediate specifier".
New Tokens and Types
We'll have to introduce new tokens & non-terminals in the parser to accommodate the interpolated string information. Given a string:
We want to tokenize the string into:
When we parse the token stream:
In the parser, we can deduce with the following rules:
Tokenizer Challenges
If we let the hierarchy of nested interpolation slip from the lexer to the parser, we will have to construct ad-hoc parser and start over again. This is not desirable. However, to get a clean token stream considering all the syntax/semantics is a bit challenging. Here's how it's done in Roslyn
https://github.com/dotnet/roslyn/blob/14e0068d9d529ade86c0ed1544477a221809d0e0/src/Compilers/CSharp/Portable/Parser/Lexer_StringLiteral.cs#L222
So basically they hoist a non-regular, mini parser that counts braces.
There are two approaches for us:
}
is encountered, either yieldRBRACE
, or resume the string lexer to yield eitherSIP_MID
orSIP_RIGHT
.Option 2 is perhaps more maintainable, because it does not drift away from the "real lexer".
Implementing FS-1001
Suppose we have the token stream properly parsed, and we have
STRING_INTEROP
nodes in the untyped AST. The string formatters are generated at a much later stage, in src/fsharp/CheckFormatStrings.fs, which is only called by the type checkerfsharp/src/fsharp/TypeChecker.fs
Line 6851 in 8397008
There are two situations here.
The interpolated string does not have a "deferred" specifier.Case 1
No deferred specifier means that we don't have to worry about string formatters. Simply move away from the path stringOrKeywordString -> rawConstant -> constant -...-> later picked up by the type checker, and translate our node as appropriate.After translation, we should get something like:edit: for the completeness of the feature we have to go for case 2.
Case 2
The harder case. We will have to make a closure to capture the interpolated expressions, and return a string formatter for the "deferred" parts.
fsharp/src/fsharp/FSharp.Core/printf.fs
Line 1519 in 8397008
The runtime support is here.
If we capture the immediate values in the format, we can translate the format string to indicate the index of the captured values -- for example,
%{s:1}
means to extract fromformat.Captures.[1]
Currently, in the front end (printf), I'm putting the captures in the
Format
objects, and I assume it will be populated by the backend-generated code.FormatSpecifier
now optionally holds the index of the capture target.The capture arrays are then forwarded to the ctor of PrintfEnv's.
The builder now handles "Begin-with-capture" arguments on the builder stack. (wip)
The
Printf.Specialization
class is updated with captured value builders. To prevent combinatorial explosion, we restrict that a capture must be the first argument in the argument pack.In the main builder, each time an immediate spec is encountered, the pack should be "flushed".
New builders in the families
FinalCaptureX
,FinalFastCaptureX
, ... ,ChainedCaptureX
, ... ,LittleAChainedCaptureX
, ... are added.Note that a format specifier can be both immediate capture and special, so we have to extend the main builder for the special form to consider captures.
Your input is much appreciated!