# Copyright 2005-2007 Kevin Reid, under the terms of the MIT X license # found at http://www.opensource.org/licenses/mit-license.html ................ ? def dumpENodes := ; null --- ePrinter --- ? def ePrinter := # value: Doc comments ? ePrinter.printDocComment(stdout, null) ? ePrinter.printDocComment(stdout, "") # stdout: /** */ # ? ePrinter.printDocComment(stdout, "foo") # stdout: /** foo */ # ? ePrinter.printDocComment(stdout, "*/*") # problem: doc comment containing "*/" cannot be printed: "*/*" ? ePrinter.printDocComment(stdout, 40) # problem: the int 40 doesn't coerce to a DocComment ? ePrinter.printDocComment(stdout, def _{to __conformTo(_) :any {return "foo"}}) # stdout: /** foo */ # ? { var i := -1; ePrinter.printDocComment(stdout, def _{to __conformTo(_) :any {return ["innocent", "*/"][i += 1]}}) } # stdout: /** innocent */ # XXX should left-column asterisks be in the print? ? ePrinter.printDocComment(stdout, "\nfoo\nbar\n") # stdout: /** # foo # bar # */ # ? ePrinter.printDocComment(stdout, " ") # stdout: /** */ # printVerb ? ePrinter.printVerb(stdout, "xor") # stdout: xor ? ePrinter.printVerb(stdout, "") # stdout: "" ? ePrinter.printVerb(stdout, "^") # stdout: "^" ? ePrinter.printVerb(stdout, "\"") # stdout: "\"" ? ePrinter.printVerb(stdout, def _{to __conformTo(_) :any {return "foo"}}) # stdout: foo printNoun ? ePrinter.printNoun(stdout, "xor") # stdout: xor ? ePrinter.printNoun(stdout, "") # stdout: ::"" ? ePrinter.printNoun(stdout, "^") # stdout: ::"^" ? ePrinter.printNoun(stdout, "\"") # stdout: ::"\"" ? ePrinter.printNoun(stdout, def _{to __conformTo(_) :any {return "foo"}}) # stdout: foo printPropertySlot ? ePrinter.printPropertySlot(stdout, "xor") # stdout: _::&xor ? ePrinter.printPropertySlot(stdout, "a1") # stdout: _::&a1 ? ePrinter.printPropertySlot(stdout, "1a") # stdout: _::&"1a" ? ePrinter.printPropertySlot(stdout, "") # stdout: _::&"" ? ePrinter.printPropertySlot(stdout, "^") # stdout: _::&"^" ? ePrinter.printPropertySlot(stdout, "\"") # stdout: _::&"\"" ? ePrinter.printPropertySlot(stdout, def _{to __conformTo(_) :any {return "foo"}}) # stdout: _::&foo printString ? ePrinter.printString(stdout, "") # stdout: "" ? ePrinter.printString(stdout, "foo") # stdout: "foo" ? ePrinter.printString(stdout, "string-with-\t-inside") # stdout: "string-with-\t-inside" ? ePrinter.printString(stdout, " \n\"\\\\\"\" ") # stdout: " # \"\\\\\"\" " ? ePrinter.printString(stdout, "\n\r\t") # stdout: " # \r\t" ? ePrinter.printString(stdout, def _{to __conformTo(_) :any {return "foo"}}) # stdout: "foo" printCharacter ? ePrinter.printCharacter(stdout, 'a') # stdout: 'a' ? ePrinter.printCharacter(stdout, '$') # stdout: '$' ? ePrinter.printCharacter(stdout, ' ') # stdout: ' ' ? ePrinter.printCharacter(stdout, '\\') # stdout: '\\' ? ePrinter.printCharacter(stdout, '\'') # stdout: '\'' ? ePrinter.printCharacter(stdout, '\t') # stdout: '\t' x ? ePrinter.printCharacter(stdout, '•') x # stdout: '•' ? ePrinter.printCharacter(stdout, def _{to __conformTo(_) :any {return 'f'}}) # stdout: 'f' printList ? ePrinter.printList(stdout, [], false) # stdout: [] ? ePrinter.printList(stdout, [1], false) # stdout: [1] ? ePrinter.printList(stdout, [1, "2", 3], true) # stdout: [1, "2", 3] ? ePrinter.printList(stdout, [1, "2", 3], false) # stdout: [1, 2, 3] ? ePrinter.printList(stdout, "123", true) # stdout: ['1', '2', '3'] ? ePrinter.printList(stdout, def _{to __conformTo(_) :any {return [4]}}, true) # stdout: [4] printMethodHeader ? ePrinter.printMethodHeader(stdout, false, "doc", "verb!", ["param"], "org") # stdout: /** doc */ # to "verb!"(param) :org ? ePrinter.printMethodHeader(stdout, true, null, "verb", [], null) # stdout: method verb() ? ePrinter.printMethodHeader(stdout, > def a{to __conformTo(_) :any {return false}}, > def b{to __conformTo(_) :any {return "dc"}}, > def c{to __conformTo(_) :any {return ""}}, > def d{to __conformTo(_) :any {return [def da{to __conformTo(_) :any {return "p"}}]}}, > def e{to __conformTo(_) :any {return null}}) # stdout: /** dc */ # to ""() : printGuardedNounPattern ? ePrinter.printGuardedNounPattern(stdout, "foo", "bar") # stdout: foo :bar ? ePrinter.printGuardedNounPattern(stdout, null, null) # stdout: _ ? ePrinter.printGuardedNounPattern(stdout, > def a{to __conformTo(_) :any {return "a"}}, > def b{to __conformTo(_) :any {return "b"}}) # stdout: a : node visitor ? def visitor := ePrinter.makePrintENodeVisitor(stdout) # value: > ? e`1 + 1`.asKernelE().welcome(visitor) # stdout: 1.add(1) XXX further print visitor tests --- Node printing --- XXX move print tests to here from mixed up in enode.updoc XXX print tests for all nodes BindingExpr ? e`&&a` # value: e`&&a` Catch ? e`try { a } catch b { c }`.asKernelE() # value: e`try { # a # } catch b { # c # }` Finally ? e`try { a } finally { b }`.asKernelE() # value: e`try { # a # } finally { # b # }` Hide ? e`{ a }` # value: e`{ # a # }` If ? e`if (a) { b } else { c }` # value: e`if (a) { # b # } else { # c # }` MetaContext ? e`meta.context()` # value: e`meta.context()` MetaState ? e`meta.getState()` # value: e`meta.getState()` MatchBInd x ? e`a =~ b` x # value: e`a =~ b` XXX once we have nonkernel node printing, reenable this SlotExpr ? e`&a` # value: e`&a` ListPattern ? epatt`[a, b]` # value: epatt`[a, b]` ? epatt`[]` # value: epatt`[]` SlotPattern ? epatt`&foo` # value: epatt`&foo` ? epatt`&state :Lamport` # value: epatt`&state :Lamport` xTesting printing of nodes with no specific print code yet: x x ? .run("{[a.run()]}") x # value: e`{ x # $$ x # }` x XXX these dollar signs are inappropriate x xxx this test is broken now that ListExpr gets appropriate printing Precedence parenthesization tests XXX this test is inapplicable until nonkernel printing is implemented x ? e`((a) =~ b ? ((c) =~ d))` x # value: e`a =~ b ? (c =~ d)` ? epatt`a :(b; c)` # value: epatt`a :(b # c)` ? e`a := (b; c)` # value: e`a := (b # c)` XXX nonkernel quasiquote/printing x ? e`(a := b) =~ c` x # value: e`(a := b) =~ c` x ? e`a := (b =~ c)` x # value: e`a := b =~ c` ? e`a := (b := c)` # value: e`a := b := c` x ? e`(a =~ b) =~ c` x # value: e`(a =~ b) =~ c` Universal precedence-proper print-parenthesization tester: ? def vm__uriGetter := > > def SeqExpr := .asType() > > def innerNodes := [ > e`a := b`.asKernelE(), > e`a.b(c)`.asKernelE(), > e`try {a} catch b {c}`.asKernelE(), > e`def a := b`.asKernelE(), > e`escape a {b}`.asKernelE(), > e`try {a} finally {b}`.asKernelE(), > e`{a}`.asKernelE(), > e`if (a) {b}`.asKernelE(), > e`if (a) {b} else {c}`.asKernelE(), > e`1`.asKernelE(), > e`meta.context()`.asKernelE(), > e`meta.getState()`.asKernelE(), > # e`a =~ b`.asKernelE(), > e`a`.asKernelE(), > e`def o {}`.asKernelE(), > e`a; b`.asKernelE(), > e`&&a`.asKernelE(), > ]; null ? for inner in innerNodes { > for whole in [ > e`aa := $inner`.asKernelE(), > e`aa($inner)`.asKernelE(), > e`$inner(aa)`.asKernelE(), > e`def aa := $inner`.asKernelE(), > # e`$inner =~ aa`.asKernelE(), > e`$inner; aa`.asKernelE(), > e`aa; $inner`.asKernelE(), > e`def aa { method bb() :$inner {} }`.asKernelE(), > e`def aa :$inner := bb`.asKernelE(), > ] { > # Special case: SeqExpr may merge harmlessly with nested SeqExprs > # XXX make this test more precise > if ([whole, inner] =~ x :List[SeqExpr]) { continue } > > def [tw, sb] := .makeBufferingPair() > whole.welcome(ePrinter.makePrintENodeVisitor(tw)) > tw.close() > escape fail { > def result := e__quasiParser.xTryParse(sb.snapshot(), fail).asKernelE() > if (result != whole) { > println("difference: ") > dumpENodes(whole, stdout) > println("===>") > dumpENodes(result, stdout) > } > } catch p { > println("parse error: ") > println(` ===> ${sb.snapshot()} ($p)`) > } > } > } XXX extend the printer to print non-kernel nodes, then update the above to test printing of them --- Parsing --- e__quasiParser ? e__quasiParser # value: ? e`1 + 1` # value: e`1 + 1` ? e__quasiParser("hi") # value: e`hi` XXX other methods makeEParser ? def makeEParser := # value: xTryParse is an unofficial interface designed when I needed to add the syntax ejector. ? escape fail { makeEParser.xTryParse("hi", fail) } catch p { print(p) } # value: e`hi` ? escape fail { makeEParser.xTryParse("try", fail) } catch p { print(p) } # stdout: problem: (line 1)@4: expecting "{", found 'null' XXX "found 'null'" is a bizarre error; fix Pragma effect preservation ? def p := makeEParser.make(null, .make("pragma.enable(\"dot-props\"); a::b", false, false), stderr, false, false) > p.parse() # value: e`$$` ? p.setSource("c::d") ? p.parse() # value: e`$$` ? p.setSource("pragma.disable(\"dot-props\"); null") ? p.parse() # value: e`null` ? p.setSource("e::f") ? p.parse() # problem: (line 1)@2: The optional "dot-props" syntax is currently off. Quasi-E-source issues ? e`"$$@@"`.eval(safeScope) # value: "$@" this syntax *could* be defined to mean something, but doesn't right now ' ? makeEParser.run("$a") # problem: XXX wording to change ? makeEParser.run("${0}") # problem: ? e__quasiParser.valueMaker("${0}") # value: e`${0}` ? e__quasiParser.matchMaker("${0}") # value: e`${0}` ? e__quasiParser.matchMaker("@{0}") # value: e`@{0}` ? {def a := e`"a"`; e`$a + "$$b"`}.eval(safeScope) # value: "a$b" Substitution ? e`[${e`a`}]` # value: e`[a]` ? epatt`[${epatt`a`}]` # value: epatt`[a]` XXX specific tests for e`` and epatt`` XXX printing all nodes, parens, precedence XXX test proper quoting as source is delivered to the Java parser - e.g. right now sending source containing a tab kills the connection because it's misquoted a the REPL-input level. XXX test parsing of (a ** b) %% c vs. a ** b %% c