[e-lang] Quasiliteral syntax for cycle-safe printing
Kevin Reid
kpreid at attglobal.net
Wed Aug 11 18:37:32 EDT 2004
In <http://www.eros-os.org/pipermail/e-lang/1999-January/002487.html> :
...
> to printOn(oo) {
> oo print("<", x, ", ", y, ">")
> }
...
> When you know (ha!) that you aren't in danger of a cycle, the more
> pleasant
...
> to printOn(oo) {
> oo print(`<$x, $y>`)
> }
...
> works as expected. Unfortunately, I see no explainable way to
> reconcile
> the notational convenience of quasiLiteral string expressions with
> cycle
> breaking.
Here's a quasiliteral parser which solves this problem.
(I tried a version that did not eval but instead iterated over a list
at print time - it was about three times slower.)
pragma.enable("easy-return")
pragma.disable("explicit-result-guard")
def makeLiteralExpr := <elang:evm.LiteralExpr>
def makeSeqExpr := <elang:evm.SeqExpr>
def valueMakerCacheFlex := [].asMap().diverge()
def lit(x) { return makeLiteralExpr(null, x, null) }
def w__quasiParser {
to valueMaker(template :Twine) {
return valueMakerCacheFlex.fetch(template, thunk{
var tparse := template
var exprs := []
while (tparse != "") {
switch (tparse) {
match rx`(@str[^$$@@]+)(@rest.*)` {
tparse := rest
exprs with= e`out.print(${lit(str)})`
}
match rx`\$$\{(@holeStr[0-9]+)}(@rest.*)` {
tparse := rest
exprs with= e`out.print(holes[${lit(__makeInt(holeStr,
10))}])`
}
}
}
def valueMaker := e`
pragma.enable("easy-return")
pragma.disable("explicit-result-guard")
def valueMaker {
to substitute(holes :List) {
def quasiTwinePrinter {
to __printOn(out :TextWriter) {
${makeSeqExpr(null, exprs, null)}
}
to run(out) {
quasiTwinePrinter.__printOn(out)
}
}
return quasiTwinePrinter
}
}
`.eval(safeScope.withPrefix(meta.context().getFQNPrefix()))
valueMakerCacheFlex[template] := valueMaker # return value
})
}
}
? pragma.enable("easy-return")
? pragma.disable("explicit-result-guard")
? def w__quasiParser := <import:w__quasiParser>
# value: <w__quasiParser>
? def x := w`x is $x and nothing else`
# value: x is ***CYCLE*** and nothing else
? def makePoint(x, y) {
> def point {
> to getX() { return x }
> to getY() { return y }
> to __printOn(out :TextWriter) {
> out.print(w`<$x, $y>`)
> }
> }
> return point
> }
# value: <makePoint>
? def p := makePoint(1, 2)
# value: <1, 2>
? def q := makePoint(43, q)
# value: <43, ***CYCLE***>
--
Kevin Reid <http://homepage.mac.com/kpreid/>
More information about the e-lang
mailing list