- Smalltalk 100%
| src | ||
| .gitignore | ||
| .project | ||
| .properties | ||
| README.md | ||
Pharo String Interpolation
An experimental Pharo 14 implementation of explicitly prefixed interpolated strings.
name := 'Pharo'.
f'Hello [ name ]!'
The f prefix opts into interpolation. Ordinary strings keep exactly their
current syntax and semantics. Interpolated regions use square brackets because
their contents are Pharo expressions and the brackets visually relate them to
normal Pharo blocks.
Current semantics
- Any single Pharo expression is accepted between
[and]. - Expressions are evaluated once, from left to right.
- Each result receives
asString. \[emits a literal[.- Backslashes are counted before
[: an odd count escapes the bracket and an even count starts interpolation. Each pair emits one backslash. - A missing
], an empty interpolation, or invalid Pharo code is a syntax error. - Quotes, comments, character literals, and nested blocks inside an expression do not terminate it.
For example:
f'1 + 2 = [ 1 + 2 ]'. "1 + 2 = 3"
f'Literal \[brackets]'. "Literal [brackets]"
f'A block: [ [ :x | x + 1 ] value: 2 ]'. "A block: 3"
Activation
The project deliberately does not replace the image compiler when it is loaded. A class can opt in on each side:
MyClass class >> compilerClass
^ OCFStringCompiler
MyClass class >> classSideCompilerClass
^ OCFStringCompiler
For experiments in a Playground:
OCFStringEvaluator new evaluate: 'f''1 + 2 = [ 1 + 2 ]'''
The compiler can also be installed image-wide and restored afterwards:
OCFStringCompiler installAsDefault.
OCFStringCompiler restoreDefault.
Runnable examples
OCFStringExamples enables the compiler on both its instance and class sides.
After loading the Examples group, try:
OCFStringExamples arithmeticExample.
OCFStringExamples hello: 'Pharo'.
OCFStringExamples new describe: 42.
OCFStringExamples new conversationFor: 'Pharo' unreadCount: 3.
The last method uses three separate f-string literals in one method.
Design
This is not a textual rewrite hidden from the tools. OCFStringScanner emits a
dedicated token, OCFStringParser builds an OCFStringNode, and every embedded
expression remains a normal AST subtree with positions in the original method.
AST visitors therefore see variable references and message sends inside the
string. OCASTTranslator translates the node directly to IR equivalent to:
OCFStringRuntime interpolate: { 'Hello '. name. '!' }
Direct translation also preserves the source structure in Opal's IR map.
Bytecodes that evaluate an embedded expression map to that expression's
original AST nodes; array construction and the final interpolate: send map to
the enclosing OCFStringNode. Consequently, sourceNodeForPC: and the Pharo
debugger highlight the original f-string source rather than a synthetic AST.
With several interpolations, debugger stepping visits their normal expression nodes from left to right and then the complete f-string for its final assembly. The final assembly is currently still a real send bytecode and therefore a debugger stop. Hiding that implementation-level stop is intentionally left as a separate refinement.
This separation leaves space for other literal prefixes, such as r'...',
without changing ordinary strings or conflating their semantics with
interpolation.
Syntax highlighting
The StringInterpolation-Highlighting package integrates the custom AST node
with Pharo 14's Shout styler. The f'...' shell and interpolation brackets use
the normal string style, while each embedded expression receives ordinary
Pharo highlighting for variables, selectors, literals, blocks, and comments.
Browsers obtain the custom parser through the class's compilerClass, so no
separate highlighter plugin needs to be configured.
Loading
Metacello new
baseline: 'StringInterpolation';
repository: 'github://estebanlm/pharo-string-interpolation:main/src';
load: 'Core'
The Core group loads the compiler implementation and syntax highlighting.
Examples adds the runnable example class. Use the Tests group as well, or
load the default group, to install everything.