/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Rhino code, released
* May 6, 1999.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Norris Boyd
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
package com.google.gwt.dev.js.rhino;
/**
* This class allows the creation of nodes, and follows the Factory pattern.
*
* @see Node
*/
public class
IRFactory {
public
IRFactory(
TokenStream ts) {
this.
ts =
ts;
}
/**
* Script (for associating file/url names with toplevel scripts.)
*/
public
Node createScript(
Node body)
{
Node result = new
Node(
TokenStream.
SCRIPT);
Node children =
body.
getFirstChild();
if (
children != null)
result.
addChildrenToBack(
children);
return
result;
}
/**
* Leaf
*/
public
Node createLeaf(int
nodeType,
CodePosition location) {
return new
Node(
nodeType,
location);
}
public
Node createLeaf(int
nodeType, int
nodeOp,
CodePosition location) {
return new
Node(
nodeType,
nodeOp,
location);
}
public int
getLeafType(
Node leaf) {
return
leaf.
getType();
}
/**
* Statement leaf nodes.
*/
public
Node createSwitch(
CodePosition location) {
return new
Node(
TokenStream.
SWITCH,
location);
}
public
Node createVariables(
CodePosition location) {
return new
Node(
TokenStream.
VAR,
location);
}
public
Node createExprStatement(
Object expr,
CodePosition location) {
return new
Node(
TokenStream.
EXPRSTMT, (
Node)
expr,
location);
}
/**
* Name
*/
public
Node createName(
String name,
CodePosition location) {
return
Node.
newString(
TokenStream.
NAME,
name,
location);
}
/**
* String (for literals)
*/
public
Node createString(
String string,
CodePosition location) {
return
Node.
newString(
string,
location);
}
/**
* Number (for literals)
*/
public
Node createIntNumber(double
number,
CodePosition location) {
return
Node.
newIntNumber(
number,
location);
}
public
Node createNumber(double
number,
CodePosition location) {
return
Node.
newNumber(
number,
location);
}
/**
* Catch clause of try/catch/finally
* @param varName the name of the variable to bind to the exception
* @param catchCond the condition under which to catch the exception.
* May be null if no condition is given.
* @param stmts the statements in the catch clause
* @param lineno the starting line number of the catch clause
*/
public
Node createCatch(
Node varName,
Node catchCond,
Node stmts,
CodePosition location) {
if (
catchCond == null) {
catchCond = new
Node(
TokenStream.
PRIMARY,
TokenStream.
TRUE,
location);
}
return new
Node(
TokenStream.
CATCH,
varName,
catchCond,
stmts,
location);
}
/**
* Throw
*/
public
Node createThrow(
Node expr,
CodePosition location) {
return new
Node(
TokenStream.
THROW,
expr,
location);
}
/**
* Return
*/
public
Node createReturn(
Node expr,
CodePosition location) {
return
expr == null
? new
Node(
TokenStream.
RETURN,
location)
: new
Node(
TokenStream.
RETURN,
expr,
location);
}
/**
* Label
*/
public
Node createLabel(
Node label,
CodePosition location) {
Node result = new
Node(
TokenStream.
LABEL,
location);
result.
addChildToBack(
label);
return
result;
}
/**
* Break (possibly labeled)
*/
public
Node createBreak(
Node label,
CodePosition location) {
Node result = new
Node(
TokenStream.
BREAK,
location);
if (
label == null) {
return
result;
} else {
result.
addChildToBack(
label);
return
result;
}
}
/**
* Continue (possibly labeled)
*/
public
Node createContinue(
Node label,
CodePosition location) {
Node result = new
Node(
TokenStream.
CONTINUE,
location);
if (
label == null) {
return
result;
} else {
result.
addChildToBack(
label);
return
result;
}
}
/**
* debugger
*/
public
Node createDebugger(
CodePosition location) {
Node result = new
Node(
TokenStream.
DEBUGGER,
location);
return
result;
}
/**
* Statement block
* Creates the empty statement block
* Must make subsequent calls to add statements to the node
*/
public
Node createBlock(
CodePosition location) {
return new
Node(
TokenStream.
BLOCK,
location);
}
public
Node createFunction(
Node name,
Node args,
Node statements,
CodePosition location) {
if (
name == null) {
name =
createName("",
location);
}
return new
Node(
TokenStream.
FUNCTION,
name,
args,
statements,
location);
}
/**
* While
*/
public
Node createWhile(
Node cond,
Node body,
CodePosition location) {
return new
Node(
TokenStream.
WHILE,
cond,
body,
location);
}
/**
* DoWhile
*/
public
Node createDoWhile(
Node body,
Node cond,
CodePosition location) {
return new
Node(
TokenStream.
DO,
body,
cond,
location);
}
/**
* For
*/
public
Node createFor(
Node init,
Node test,
Node incr,
Node body,
CodePosition location) {
return new
Node(
TokenStream.
FOR,
init,
test,
incr,
body,
location);
}
/**
* For .. In
*
*/
public
Node createForIn(
Node lhs,
Node obj,
Node body,
CodePosition location) {
return new
Node(
TokenStream.
FOR,
lhs,
obj,
body,
location);
}
/**
* Try/Catch/Finally
*/
public
Node createTryCatchFinally(
Node tryblock,
Node catchblocks,
Node finallyblock,
CodePosition location) {
if (
finallyblock == null) {
return new
Node(
TokenStream.
TRY,
tryblock,
catchblocks,
location);
}
return new
Node(
TokenStream.
TRY,
tryblock,
catchblocks,
finallyblock,
location);
}
/**
* Throw, Return, Label, Break and Continue are defined in ASTFactory.
*/
/**
* With
*/
public
Node createWith(
Node obj,
Node body,
CodePosition location) {
return new
Node(
TokenStream.
WITH,
obj,
body,
location);
}
/**
* Array Literal
*/
public
Node createArrayLiteral(
Node obj) {
return
obj;
}
/**
* Object Literals
*/
public
Node createObjectLiteral(
Node obj) {
return
obj;
}
/**
* Regular expressions
*/
public
Node createRegExp(
String string,
String flags,
CodePosition location) {
return
flags.
length() == 0
? new
Node(
TokenStream.
REGEXP,
Node.
newString(
string,
location),
location)
: new
Node(
TokenStream.
REGEXP,
Node.
newString(
string,
location),
Node.
newString(
flags,
location),
location);
}
/**
* If statement
*/
public
Node createIf(
Node cond,
Node ifTrue,
Node ifFalse,
CodePosition location) {
if (
ifFalse == null)
return new
Node(
TokenStream.
IF,
cond,
ifTrue,
location);
return new
Node(
TokenStream.
IF,
cond,
ifTrue,
ifFalse,
location);
}
public
Node createTernary(
Node cond,
Node ifTrue,
Node ifFalse,
CodePosition location) {
return new
Node(
TokenStream.
HOOK,
cond,
ifTrue,
ifFalse,
location);
}
/**
* Unary
*/
public
Node createUnary(int
nodeType,
Node child,
CodePosition location) {
return new
Node(
nodeType,
child,
location);
}
public
Node createUnary(int
nodeType, int
nodeOp,
Node child,
CodePosition location) {
return new
Node(
nodeType,
child,
nodeOp,
location);
}
/**
* Binary
*/
public
Node createBinary(int
nodeType,
Node left,
Node right,
CodePosition location) {
switch (
nodeType) {
case
TokenStream.
DOT:
nodeType =
TokenStream.
GETPROP;
right.
setType(
TokenStream.
STRING);
break;
case
TokenStream.
LB:
// OPT: could optimize to GETPROP iff string can't be a number
nodeType =
TokenStream.
GETELEM;
break;
}
return new
Node(
nodeType,
left,
right,
location);
}
public
Node createBinary(int
nodeType, int
nodeOp,
Node left,
Node right,
CodePosition location) {
if (
nodeType ==
TokenStream.
ASSIGN) {
return
createAssignment(
nodeOp,
left,
right,
location);
}
return new
Node(
nodeType,
left,
right,
nodeOp,
location);
}
public
Node createAssignment(int
nodeOp,
Node left,
Node right,
CodePosition location) {
int
nodeType =
left.
getType();
switch (
nodeType) {
case
TokenStream.
NAME:
case
TokenStream.
GETPROP:
case
TokenStream.
GETELEM:
break;
default:
// TODO: This should be a ReferenceError--but that's a runtime
// exception. Should we compile an exception into the code?
ts.
reportSyntaxError("msg.bad.lhs.assign", null);
}
return new
Node(
TokenStream.
ASSIGN,
left,
right,
nodeOp,
location);
}
// Only needed to get file/line information. Could create an interface
// that TokenStream implements if we want to make the connection less
// direct.
private
TokenStream ts;
}