1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  * 
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  * 
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  * 
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  * 
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * Nashorn parser API - Basic TreeVisitor tests.
  26  *
  27  * @test
  28  * @option -scripting
  29  * @run
  30  */
  31 
  32 // Java types used
  33 var SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1");
  34 var Parser = Java.type("jdk.nashorn.api.tree.Parser");
  35 
  36 function parse(name, script, visitor) {
  37     var parser = Parser.create("--empty-statements");
  38     var tree = parser.parse(name, script, null);
  39     return tree.accept(visitor, print);
  40 }
  41 
  42 parse("arrayaccess.js", "this['eval']",
  43     new (Java.extend(SimpleTreeVisitor))() {
  44         visitArrayAccess: function(aa) {
  45             print("in visitArrayAccess " +
  46               aa.expression.name + " " + aa.index.value);
  47         }
  48     });
  49 
  50 parse("arrayliteral.js", "[2, 3, 22]",
  51     new (Java.extend(SimpleTreeVisitor))() {
  52         visitArrayLiteral: function(al) {
  53             print("in visitArrayLiteral");
  54             for each (var e in al.elements) {
  55                print(e.value);
  56             }
  57         }
  58     });
  59 
  60 parse("assign.js", "x = 33",
  61     new (Java.extend(SimpleTreeVisitor))() {
  62         visitAssignment: function(an) {
  63             print("in visitAssignment " +
  64                 an.variable.name + " " + an.expression.value);
  65         }
  66     });
  67 
  68 function binaryExpr(name, code) {
  69     parse(name, code, 
  70         new (Java.extend(SimpleTreeVisitor))() {
  71             visitBinary: function(bn) {
  72                 print("in visitBinary " + bn.kind + " " +
  73                     bn.leftOperand.value + ", " + bn.rightOperand.value);
  74             }
  75         });
  76 }
  77 
  78 binaryExpr("add.js", "3 + 4");
  79 binaryExpr("sub.js", "3 - 4");
  80 binaryExpr("mul.js", "3 * 4");
  81 binaryExpr("div.js", "3 / 4");
  82 binaryExpr("rem.js", "3 % 4");
  83 binaryExpr("rshift.js", "3 >> 4");
  84 binaryExpr("rshift.js", "3 >>> 4");
  85 binaryExpr("lshift.js", "3 << 4");
  86 binaryExpr("less.js", "3 < 4");
  87 binaryExpr("lessOrEq.js", "3 <= 4");
  88 binaryExpr("greater.js", "3 > 4");
  89 binaryExpr("greaterOrEq.js", "3 >= 4");
  90 binaryExpr("in.js", "3 in this");
  91 binaryExpr("eq.js", "3 == 3");
  92 binaryExpr("ne.js", "3 != 2");
  93 binaryExpr("seq.js", "3 === 2");
  94 binaryExpr("sne.js", "3 !== 2");
  95 binaryExpr("and.js", "3 & 2");
  96 binaryExpr("or.js", "3 | 2");
  97 binaryExpr("xor.js", "3 ^ 2");
  98 binaryExpr("cond_and.js", "3 && 2");
  99 binaryExpr("cond_or.js", "3 || 2");
 100 binaryExpr("comma", "3, 2");
 101 
 102 parse("block.js", "{ print('hello'); }", 
 103     new (Java.extend(SimpleTreeVisitor))() {
 104         visitBlock: function() {
 105             print("in visitBlock");
 106         }
 107     });
 108 
 109 
 110 parse("break.js", "while(true) { break; }", 
 111     new (Java.extend(SimpleTreeVisitor))() {
 112         visitBreak: function() {
 113             print("in visitBreak");
 114         }
 115     });
 116 
 117 function compAssignExpr(name, code) {
 118     parse(name, code, 
 119         new (Java.extend(SimpleTreeVisitor))() {
 120             visitCompoundAssignment: function(bn) {
 121                 print("in visitCompoundAssignment " + bn.kind + " " +
 122                   bn.variable.name + " " + bn.expression.value);
 123             }
 124         });
 125 }
 126 
 127 compAssignExpr("mult_assign.js", "x *= 3");
 128 compAssignExpr("div_assign.js", "x /= 3");
 129 compAssignExpr("rem_assign.js", "x %= 3");
 130 compAssignExpr("add_assign.js", "x += 3");
 131 compAssignExpr("sub_assign.js", "x -= 3");
 132 compAssignExpr("lshift_assign.js", "x <<= 3");
 133 compAssignExpr("rshift_assign.js", "x >>= 3");
 134 compAssignExpr("urshift_assign.js", "x >>>= 3");
 135 compAssignExpr("and_assign.js", "x &= 3");
 136 compAssignExpr("xor_assign.js", "x ^= 3");
 137 compAssignExpr("or_assign.js", "x |= 3");
 138 
 139 parse("condexpr.js", "foo? x : y", 
 140     new (Java.extend(SimpleTreeVisitor))() {
 141         visitConditionalExpression: function() {
 142             print("in visitConditionalExpression");
 143         }
 144     });
 145 
 146 parse("continue.js", "while(true) { continue; }", 
 147     new (Java.extend(SimpleTreeVisitor))() {
 148         visitContinue: function() {
 149             print("in visitContinue");
 150         }
 151     });
 152 
 153 parse("debugger.js", "debugger;", 
 154     new (Java.extend(SimpleTreeVisitor))() {
 155         visitDebugger: function() {
 156             print("in visitDebugger");
 157         }
 158     });
 159 
 160 parse("dowhile.js", "do {} while(true)", 
 161     new (Java.extend(SimpleTreeVisitor))() {
 162         visitDoWhileLoop: function() {
 163             print("in visitDoWhileLoop");
 164         }
 165     });
 166 
 167 parse("empty.js", ";", 
 168     new (Java.extend(SimpleTreeVisitor))() {
 169         visitEmptyStatement: function() {
 170             print("in visitEmptyStatement");
 171         }
 172     });
 173 
 174 parse("exprstat.js", "2+3;", 
 175     new (Java.extend(SimpleTreeVisitor))() {
 176         visitExpressionStatement: function() {
 177             print("in visitExpressionStatement");
 178         }
 179     });
 180 
 181 parse("forin.js", "for(i in this) {}", 
 182     new (Java.extend(SimpleTreeVisitor))() {
 183         visitForInLoop: function() {
 184             print("in visitForInLoop");
 185         }
 186     });
 187 
 188 parse("for.js", "for(;;) {}", 
 189     new (Java.extend(SimpleTreeVisitor))() {
 190         visitForLoop: function() {
 191             print("in visitForLoop");
 192         }
 193     });
 194 
 195 parse("funccall.js", "func()", 
 196     new (Java.extend(SimpleTreeVisitor))() {
 197         visitFunctionCall: function(fc) {
 198             print("in visitFunctionCall " + fc.functionSelect.name);
 199         }
 200     });
 201 
 202 parse("funcdecl.js", "function func() {}", 
 203     new (Java.extend(SimpleTreeVisitor))() {
 204         visitFunctionDeclaration: function(fd) {
 205             print("in visitFunctionDeclaration " + fd.name);
 206         }
 207     });
 208 
 209 parse("funcexpr.js", "x = function() {}", 
 210     new (Java.extend(SimpleTreeVisitor))() {
 211         visitFunctionExpression: function() {
 212             print("in visitFunctionExpression");
 213         }
 214     });
 215 
 216 parse("ident.js", "this", 
 217     new (Java.extend(SimpleTreeVisitor))() {
 218         visitIdentifier: function(ident) {
 219             print("in visitIdentifier " + ident.name);
 220         }
 221     });
 222 
 223 parse("if.js", "if (true) {}", 
 224     new (Java.extend(SimpleTreeVisitor))() {
 225         visitIf: function() {
 226             print("in visitIf");
 227         }
 228     });
 229 
 230 parse("instanceof.js", "this instanceof Object", 
 231     new (Java.extend(SimpleTreeVisitor))() {
 232         visitInstanceOf: function() {
 233             print("in visitInstanceOf");
 234         }
 235     });
 236 
 237 parse("labeled.js", "foo: print('hello');", 
 238     new (Java.extend(SimpleTreeVisitor))() {
 239         visitLabeledStatement: function() {
 240             print("in visitLabeledStatement");
 241         }
 242     });
 243 
 244 function literalExpr(name, code) {
 245     parse(name, code, 
 246         new (Java.extend(SimpleTreeVisitor))() {
 247             visitLiteral: function(ln) {
 248                 print("in visitLiteral " + ln.kind + " " + ln.value);
 249             }
 250         });
 251 }
 252 
 253 literalExpr("bool.js", "true");
 254 literalExpr("num.js", "3.14");
 255 literalExpr("str.js", "'hello'");
 256 literalExpr("null.js", "null");
 257 
 258 parse("memselect.js", "this.foo", 
 259     new (Java.extend(SimpleTreeVisitor))() {
 260         visitMemberSelect: function(ms) {
 261             print("in visitMemberSelect " + ms.identifier);
 262         }
 263     });
 264 
 265 parse("new.js", "new Object()", 
 266     new (Java.extend(SimpleTreeVisitor))() {
 267         visitNew: function() {
 268             print("in visitNew");
 269         }
 270     });
 271 
 272 parse("obj_literal.js", "({ foo: 343 })", 
 273     visitor = new (Java.extend(SimpleTreeVisitor))() {
 274         visitObjectLiteral: function(ol) {
 275             print("in visitObjectLiteral");
 276             Java.super(visitor).visitObjectLiteral(ol, null);
 277         },
 278 
 279         visitProperty: function(pn) {
 280             print("in visitProperty " + pn.key.name);
 281         }
 282     });
 283 
 284 parse("regexp.js", "/[a-b]/i", 
 285     new (Java.extend(SimpleTreeVisitor))() {
 286         visitRegExpLiteral: function(re) {
 287             print("in visitRegExpLiteral " + re.pattern + " " + re.options);
 288         }
 289     });
 290 
 291 parse("ret.js", "function func() { return 33 }", 
 292     new (Java.extend(SimpleTreeVisitor))() {
 293         visitReturn: function(ret) {
 294             print("in visitReturn " + ret.expression.value);
 295         }
 296     });
 297 
 298 parse("switch.js", "switch(c) { case '1': break; default: }", 
 299     visitor = new (Java.extend(SimpleTreeVisitor))() {
 300         visitSwitch: function(sn) {
 301             print("in visitSwitch");
 302             Java.super(visitor).visitSwitch(sn, null);
 303         },
 304 
 305         visitCase: function(cn) {
 306             if (cn.expression) {
 307                 print("in visitCase");
 308             } else {
 309                 print("in visitCase (default)");
 310             }
 311         }
 312     });
 313 
 314 parse("throw.js", "throw 2", 
 315     new (Java.extend(SimpleTreeVisitor))() {
 316         visitThrow: function(tn) {
 317             print("in visitThrow " + tn.expression.value);
 318         }
 319     });
 320 
 321 parse("try.js", "try { func() } catch(e) {}", 
 322     visitor = new (Java.extend(SimpleTreeVisitor))() {
 323         visitTry: function(tn) {
 324             print("in visitTry");
 325             Java.super(visitor).visitTry(tn, null);
 326         },
 327         visitCatch: function(cn) {
 328             print("in visitCatch " + cn.parameter.name);
 329         }
 330     });
 331 
 332 function unaryExpr(name, code) {
 333     parse(name, code, 
 334         new (Java.extend(SimpleTreeVisitor))() {
 335             visitUnary: function(un) {
 336                 print("in visitUnary " + un.kind + " " + un.expression.name);
 337             }
 338         });
 339 }
 340 
 341 unaryExpr("postincr.js", "x++");
 342 unaryExpr("postdecr.js", "x--");
 343 unaryExpr("preincr.js", "++x");
 344 unaryExpr("predecr.js", "--x");
 345 unaryExpr("plus.js", "+x");
 346 unaryExpr("minus.js", "-x");
 347 unaryExpr("complement.js", "~x");
 348 unaryExpr("logical_compl.js", "!x");
 349 unaryExpr("delete.js", "delete x");
 350 unaryExpr("typeof.js", "typeof x");
 351 unaryExpr("void.js", "void x");
 352 
 353 parse("var.js", "var x = 34;", 
 354     new (Java.extend(SimpleTreeVisitor))() {
 355         visitVariable: function(vn) {
 356             print("in visitVariable " + vn.name + " = " + vn.initializer.value);
 357         }
 358     });
 359 
 360 parse("while.js", "while(true) {}", 
 361     new (Java.extend(SimpleTreeVisitor))() {
 362         visitWhileLoop: function() {
 363             print("in visitWhileLoop");
 364         }
 365     });
 366 
 367 parse("with.js", "with({}) {}", 
 368     new (Java.extend(SimpleTreeVisitor))() {
 369         visitWith: function() {
 370             print("in visitWith");
 371         }
 372     });