[Pharo-dev] String Interpolation

Denis Kudriashov dionisiydk at gmail.com
Wed Oct 4 05:46:09 EDT 2017


Hi Igor.

Did you see that we have now #asMethodConstant?

DateAndTime now asMethodConst


It is not compiled time but behaviour is very close to it.
The trick is that first time execution will replace full expression with
the result as literal (the receiver of #asMethodConst). So at second time
it will be just literal reading.

2017-10-04 11:36 GMT+02:00 Igor Stasenko <siguctua at gmail.com>:

> IMO, best would be to make it via compiler plugin.
>
> Same, as i proposed for object literals,
> a compiler could detect a pattern  <string literal> interpolate
> and replace it  at compile time to produce/expand it into proper
> context-aware semantic, something like this:
>
> {'a' . x . 'b' . y. 'c' .z } gather: #asString
>
> That will allow to eliminate run-time security risk(due to #evaluate:), as
> well as run-time execution cost,
> and allows a nice and convenient and clean syntax.
>
> Without compiler modification, it's hard to reach best security &
> performance & convenience ideals.
>
>
>
> On 4 October 2017 at 11:06, Thierry Goubier <thierry.goubier at gmail.com>
> wrote:
>
>>
>>
>> 2017-10-04 9:50 GMT+02:00 Guillermo Polito <guillermopolito at gmail.com>:
>>
>>> if the compiler plugin correctly models such special syntax with special
>>> AST nodes, that could be even possible without much effort
>>>
>>
>> Interesting. Would that imply that by having those special ast nodes, we
>> would get the decompilation working for the debugger?
>>
>> Thierry
>>
>>
>>
>>
>>>
>>> On Tue, Oct 3, 2017 at 5:42 PM, Denis Kudriashov <dionisiydk at gmail.com>
>>> wrote:
>>>
>>>>
>>>> 2017-10-03 17:39 GMT+02:00 Denis Kudriashov <dionisiydk at gmail.com>:
>>>>
>>>>> Hi.
>>>>>
>>>>> While idea looks cool it will require a lot of tool support. Senders,
>>>>> var/class references, rename refactorings should be aware of it
>>>>>
>>>>
>>>> And I forgot debugger. It should be possible to step over "interpolated
>>>> expressions"
>>>>
>>>>
>>>>>
>>>>> 2017-10-03 17:29 GMT+02:00 Damien Pollet <damien.pollet at gmail.com>:
>>>>>
>>>>>> On 3 October 2017 at 14:07, Guillermo Polito <
>>>>>> guillermopolito at gmail.com> wrote:
>>>>>>
>>>>>>> Why not having an opal plugin?
>>>>>>>
>>>>>>> The opal plugin may read strings in the form:
>>>>>>>
>>>>>>> "lalala {some expression} lololo"
>>>>>>>
>>>>>>> and replace at compile time that by:
>>>>>>>
>>>>>>> "lalala {1} lololo" format { some expression }
>>>>>>>
>>>>>>
>>>>>> If we're going to extend the compiler, we might as avoid parsing at
>>>>>> runtime by desugaring more like:
>>>>>>
>>>>>> String streamContents: [:str |
>>>>>>     str
>>>>>>         nextPutAll: 'lalala ';
>>>>>>         nextPutAll: (some expression) printString;
>>>>>>         nextPutAll: ' lololo' ]
>>>>>>
>>>>>> The thing to think about is what is the delimiter for {some
>>>>>>> expression}.
>>>>>>>  - a too used one may break lots of existing code.
>>>>>>>
>>>>>>
>>>>>> …or we could change the string quotes to mean "dynamic string in
>>>>>> which interpolations can be used" and keep single quotes for literal
>>>>>> strings only.
>>>>>>
>>>>>>  - and we should escape it
>>>>>>>
>>>>>>
>>>>>> indeed
>>>>>>
>>>>>>
>>>>>>> On Fri, Sep 29, 2017 at 5:40 AM, Sven Van Caekenberghe <sven at stfx.eu
>>>>>>> > wrote:
>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> > On 29 Sep 2017, at 08:54, Pavel Krivanek <
>>>>>>>> pavel.krivanek at gmail.com> wrote:
>>>>>>>> >
>>>>>>>> > This solution will not work for environments without sources too
>>>>>>>> where names like t1, t2 are used for temporary variables.
>>>>>>>>
>>>>>>>> That is true.
>>>>>>>>
>>>>>>>> I often wonder why we can't keep at least the variables names, it
>>>>>>>> would not be that expensive. There was this problem with FFI that needed
>>>>>>>> source code access as well. It would also help the debugger and make the
>>>>>>>> decompiler more powerful.
>>>>>>>>
>>>>>>>> > Anyway, nice idea.
>>>>>>>> >
>>>>>>>> > -- Pavel
>>>>>>>> >
>>>>>>>> > Dne čtvrtek 28. září 2017 Sven Van Caekenberghe <sven at stfx.eu>
>>>>>>>> napsal(a):
>>>>>>>> > Hi,
>>>>>>>> >
>>>>>>>> > I got into a little office discussion about string interpolation
>>>>>>>> as it is done in different programming languages.
>>>>>>>> >
>>>>>>>> > In Pharo we have String>>#format: which is pretty nice. It works
>>>>>>>> as follows:
>>>>>>>> >
>>>>>>>> > | x y |
>>>>>>>> > x := 123.
>>>>>>>> > y := #foo.
>>>>>>>> > 'x={1} and y={2}' format: { x. y }.
>>>>>>>> >
>>>>>>>> > It is also possible to use a dictionary with keys, like this:
>>>>>>>> >
>>>>>>>> > | x y |
>>>>>>>> > x := 123.
>>>>>>>> > y := #foo.
>>>>>>>> > 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>>>>>>>> >
>>>>>>>> > But this is not true string interpolation as described in [
>>>>>>>> https://en.wikipedia.org/wiki/String_interpolation ]. The idea is
>>>>>>>> to write the value generating expressions directly inside the strings.
>>>>>>>> >
>>>>>>>> > Since in Pharo we add features not by extending the syntax but by
>>>>>>>> adding messages I wondered if it could be done for string interpolation.
>>>>>>>> The goal is to make the following work:
>>>>>>>> >
>>>>>>>> > | x y |
>>>>>>>> > x := 123.
>>>>>>>> > y := #foo.
>>>>>>>> > 'It seems x equals {x} and y equals {y} while Pi is still {Float
>>>>>>>> pi}' interpolate.
>>>>>>>> >
>>>>>>>> >  => 'It seems x equals 123 and y equals foo while Pi is still
>>>>>>>> 3.141592653589793'
>>>>>>>> >
>>>>>>>> > Here is the implementation I came up with:
>>>>>>>> >
>>>>>>>> > String>>#interpolate
>>>>>>>> >   "Format the receiver by interpolating the evaluation of
>>>>>>>> expressions
>>>>>>>> >   in between curly brackets in the context of the sender as in
>>>>>>>> the following 3 oneline examples.
>>>>>>>> >   'Today is {Date today}' interpolate.
>>>>>>>> >   | x | x := 123. 'x equals {x} and pi equals {Float pi}'
>>>>>>>> interpolate.
>>>>>>>> >   'In {#strings} you can escape \{ by prefixing it with \\'
>>>>>>>> interpolate."
>>>>>>>> >
>>>>>>>> >   | senderContext |
>>>>>>>> >   senderContext := thisContext sender.
>>>>>>>> >   ^ self class new: self size streamContents: [ :out | | stream |
>>>>>>>> >       stream := self readStream.
>>>>>>>> >       [ stream atEnd ] whileFalse: [ | currentChar |
>>>>>>>> >         (currentChar := stream next) == ${
>>>>>>>> >           ifTrue: [ | expression result |
>>>>>>>> >             expression := stream upTo: $}.
>>>>>>>> >             result := Compiler new
>>>>>>>> >               evaluate: expression in: senderContext to: nil
>>>>>>>> notifying: nil ifFail: [ ^ nil ] logged: false.
>>>>>>>> >             out nextPutAll: result asString ]
>>>>>>>> >           ifFalse: [
>>>>>>>> >             currentChar == $\
>>>>>>>> >               ifTrue: [ stream atEnd ifFalse: [ out nextPut:
>>>>>>>> stream next ] ]
>>>>>>>> >               ifFalse: [ out nextPut: currentChar ] ] ] ]
>>>>>>>> >
>>>>>>>> > It is a hack that could certainly be improved. And there is of
>>>>>>>> course an obvious security problem.
>>>>>>>> >
>>>>>>>> > Thoughts ?
>>>>>>>> >
>>>>>>>> > Sven
>>>>>>>> >
>>>>>>>> >
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Guille Polito
>>>>>>>
>>>>>>> Research Engineer
>>>>>>>
>>>>>>> Centre de Recherche en Informatique, Signal et Automatique de Lille
>>>>>>>
>>>>>>> CRIStAL - UMR 9189
>>>>>>>
>>>>>>> French National Center for Scientific Research - *http://www.cnrs.fr
>>>>>>> <http://www.cnrs.fr>*
>>>>>>>
>>>>>>>
>>>>>>> *Web:* *http://guillep.github.io* <http://guillep.github.io>
>>>>>>>
>>>>>>> *Phone: *+33 06 52 70 66 13 <+33%206%2052%2070%2066%2013>
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Damien Pollet
>>>>>> type less, do more [ | ] http://people.untyped.org/damien.pollet
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>> --
>>>
>>>
>>>
>>> Guille Polito
>>>
>>> Research Engineer
>>>
>>> Centre de Recherche en Informatique, Signal et Automatique de Lille
>>>
>>> CRIStAL - UMR 9189
>>>
>>> French National Center for Scientific Research - *http://www.cnrs.fr
>>> <http://www.cnrs.fr>*
>>>
>>>
>>> *Web:* *http://guillep.github.io* <http://guillep.github.io>
>>>
>>> *Phone: *+33 06 52 70 66 13 <+33%206%2052%2070%2066%2013>
>>>
>>
>>
>
>
> --
> Best regards,
> Igor Stasenko.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.pharo.org/pipermail/pharo-dev_lists.pharo.org/attachments/20171004/376c5baa/attachment-0002.html>


More information about the Pharo-dev mailing list