[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