silo:std.format

Source src/silo:std.format

1##! Compile-time string formatting via the `format` macro.
2##!
3##! Expands `"{}"`-template strings into a sequence of `.show` calls
4##! and `+` concatenations.
5
6:use
7  :open core AnyInt Vec Str
8  :open traits Add Sub Ord Display Default
9  :open ast Expr StrLit FieldAccess Binding WordCall
10:end
11
12# si[impl string.format]
13## Expands a `"{}"`-interpolated string literal into a Vec of AST nodes that
14## concatenate the template pieces with `.show`-formatted interpolated values.
15## ( Expr -> (Vec Expr) )
16:macro(pub) format ( Expr -> (Vec Expr) )
17  pop-> fmt-expr
18  fmt-expr :match
19    | StrLit s => s
20    | _ => ""
21  :end pop-> template
22  "{}" template str-split pop-> parts
23  parts .len pop-> num-parts
24  num-parts 1 - pop-> num-placeholders
25  (Vec .default) pop-> code
26  num-placeholders 1 - pop-> idx
27  :loop
28    idx 0 < :if :break :end
29    "fmt" FieldAccess code swap .push pop-> code
30    "_f" idx .fmt + Binding code swap .push pop-> code
31    idx 1 - pop-> idx
32  :end
33  0 parts .get StrLit code swap .push pop-> code
34  0 pop-> j
35  :loop
36    j num-placeholders:if :break :end
37    "_f" j .fmt + WordCall code swap .push pop-> code
38    "+" WordCall code swap .push pop-> code
39    j 1 + parts .get StrLit code swap .push pop-> code
40    "+" WordCall code swap .push pop-> code
41    j 1 + pop-> j
42  :end
43  code
44:end