/* -*- 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
 * @author Mike McCabe
 * @author Norris Boyd
 */
public class IRFactory {

    public IRFactory(TokenStream ts) {
        this.ts = ts;
    }

    /**
     * Script (for associating file/url names with toplevel scripts.)
     */
    public Object createScript(Object body, String sourceName,
                               int baseLineno, int endLineno, Object source)
    {
        Node result = new Node(TokenStream.SCRIPT);
        Node children = ((Node) body).getFirstChild();
        if (children != null)
            result.addChildrenToBack(children);

        result.putProp(Node.SOURCENAME_PROP, sourceName);
        result.putIntProp(Node.BASE_LINENO_PROP, baseLineno);
        result.putIntProp(Node.END_LINENO_PROP, endLineno);
        if (source != null)
            result.putProp(Node.SOURCE_PROP, source);
        return result;
    }

    /**
     * Leaf
     */
    public Object createLeaf(int nodeType) {
            return new Node(nodeType);
    }

    public Object createLeaf(int nodeType, int nodeOp) {
        return new Node(nodeType, nodeOp);
    }

    public int getLeafType(Object leaf) {
        Node n = (Node) leaf;
        return n.getType();
    }

    /**
     * Statement leaf nodes.
     */

    public Object createSwitch(int lineno) {
        return new Node(TokenStream.SWITCH, lineno);
    }

    public Object createVariables(int lineno) {
        return new Node(TokenStream.VAR, lineno);
    }

    public Object createExprStatement(Object expr, int lineno) {
        return new Node(TokenStream.EXPRSTMT, (Node) expr, lineno);
    }

    /**
     * Name
     */
    public Object createName(String name) {
        return Node.newString(TokenStream.NAME, name);
    }

    /**
     * String (for literals)
     */
    public Object createString(String string) {
        return Node.newString(string);
    }

    /**
     * Number (for literals)
     */
    public Object createNumber(double number) {
        return Node.newNumber(number);
    }

    /**
     * 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 Object createCatch(String varName, Object catchCond, Object stmts,
                              int lineno)
    {
        if (catchCond == null) {
            catchCond = new Node(TokenStream.PRIMARY, TokenStream.TRUE);
        }
        return new Node(TokenStream.CATCH, (Node)createName(varName),
                               (Node)catchCond, (Node)stmts, lineno);
    }

    /**
     * Throw
     */
    public Object createThrow(Object expr, int lineno) {
        return new Node(TokenStream.THROW, (Node)expr, lineno);
    }

    /**
     * Return
     */
    public Object createReturn(Object expr, int lineno) {
        return expr == null
            ? new Node(TokenStream.RETURN, lineno)
            : new Node(TokenStream.RETURN, (Node)expr, lineno);
    }

    /**
     * Label
     */
    public Object createLabel(String label, int lineno) {
        Node result = new Node(TokenStream.LABEL, lineno);
        Node name = Node.newString(TokenStream.NAME, label);
        result.addChildToBack(name);
        return result;
    }

    /**
     * Break (possibly labeled)
     */
    public Object createBreak(String label, int lineno) {
        Node result = new Node(TokenStream.BREAK, lineno);
        if (label == null) {
            return result;
        } else {
            Node name = Node.newString(TokenStream.NAME, label);
            result.addChildToBack(name);
            return result;
        }
    }

    /**
     * Continue (possibly labeled)
     */
    public Object createContinue(String label, int lineno) {
        Node result = new Node(TokenStream.CONTINUE, lineno);
        if (label == null) {
            return result;
        } else {
            Node name = Node.newString(TokenStream.NAME, label);
            result.addChildToBack(name);
            return result;
        }
    }

    /**
     * debugger
     */
    public Object createDebugger(int lineno) {
        Node result = new Node(TokenStream.DEBUGGER, lineno);
        return result;
    }

    /**
     * Statement block
     * Creates the empty statement block
     * Must make subsequent calls to add statements to the node
     */
    public Object createBlock(int lineno) {
        return new Node(TokenStream.BLOCK, lineno);
    }

    public Object createFunction(String name, Object args, Object statements,
                                 String sourceName, int baseLineno,
                                 int endLineno, Object source,
                                 boolean isExpr)
    {
        Node f = new Node(TokenStream.FUNCTION,
                          Node.newString(TokenStream.NAME,
                                         name == null ? "" : name),
                          (Node)args, (Node)statements, baseLineno);

        f.putProp(Node.SOURCENAME_PROP, sourceName);
        f.putIntProp(Node.BASE_LINENO_PROP, baseLineno);
        f.putIntProp(Node.END_LINENO_PROP, endLineno);
        if (source != null)
            f.putProp(Node.SOURCE_PROP, source);

        return f;
    }

    /**
     * Add a child to the back of the given node.  This function
     * breaks the Factory abstraction, but it removes a requirement
     * from implementors of Node.
     */
    public void addChildToBack(Object parent, Object child) {
        ((Node)parent).addChildToBack((Node)child);
    }

    /**
     * While
     */
    public Object createWhile(Object cond, Object body, int lineno) {
        return new Node(TokenStream.WHILE, (Node)cond, (Node)body, lineno);
    }

    /**
     * DoWhile
     */
    public Object createDoWhile(Object body, Object cond, int lineno) {
        return new Node(TokenStream.DO, (Node)body, (Node)cond, lineno);
    }

    /**
     * For
     */
    public Object createFor(Object init, Object test, Object incr,
                            Object body, int lineno)
    {
        return new Node(TokenStream.FOR, (Node)init, (Node)test, (Node)incr,
                        (Node)body);
    }

    /**
     * For .. In
     *
     */
    public Object createForIn(Object lhs, Object obj, Object body, int lineno) {
        return new Node(TokenStream.FOR, (Node)lhs, (Node)obj, (Node)body);
    }

    /**
     * Try/Catch/Finally
     */
    public Object createTryCatchFinally(Object tryblock, Object catchblocks,
                                        Object finallyblock, int lineno)
    {
        if (finallyblock == null) {
            return new Node(TokenStream.TRY, (Node)tryblock, (Node)catchblocks);
        }
        return new Node(TokenStream.TRY, (Node)tryblock,
                        (Node)catchblocks, (Node)finallyblock);
    }

    /**
     * Throw, Return, Label, Break and Continue are defined in ASTFactory.
     */

    /**
     * With
     */
    public Object createWith(Object obj, Object body, int lineno) {
        return new Node(TokenStream.WITH, (Node)obj, (Node)body, lineno);
    }

    /**
     * Array Literal
     */
    public Object createArrayLiteral(Object obj) {
        return obj;
    }

    /**
     * Object Literals
     */
    public Object createObjectLiteral(Object obj) {
        return obj;
    }

    /**
     * Regular expressions
     */
    public Object createRegExp(String string, String flags) {
        return flags.length() == 0
               ? new Node(TokenStream.REGEXP,
                          Node.newString(string))
               : new Node(TokenStream.REGEXP,
                          Node.newString(string),
                          Node.newString(flags));
    }

    /**
     * If statement
     */
    public Object createIf(Object cond, Object ifTrue, Object ifFalse,
                           int lineno)
    {
        if (ifFalse == null)
            return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue);
        return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue, (Node)ifFalse);
    }

    public Object createTernary(Object cond, Object ifTrue, Object ifFalse) {
        return new Node(TokenStream.HOOK,
                        (Node)cond, (Node)ifTrue, (Node)ifFalse);
    }

    /**
     * Unary
     */
    public Object createUnary(int nodeType, Object child) {
        Node childNode = (Node) child;
        return new Node(nodeType, childNode);
    }

    public Object createUnary(int nodeType, int nodeOp, Object child) {
        return new Node(nodeType, (Node)child, nodeOp);
    }

    /**
     * Binary
     */
    public Object createBinary(int nodeType, Object left, Object right) {
        Node temp;
        switch (nodeType) {

          case TokenStream.DOT:
            nodeType = TokenStream.GETPROP;
            Node idNode = (Node) right;
            idNode.setType(TokenStream.STRING);
            String id = idNode.getString();
            if (id.equals("__proto__") || id.equals("__parent__")) {
                Node result = new Node(nodeType, (Node) left);
                result.putProp(Node.SPECIAL_PROP_PROP, id);
                return result;
            }
            break;

          case TokenStream.LB:
            // OPT: could optimize to GETPROP iff string can't be a number
            nodeType = TokenStream.GETELEM;
            break;
        }
        return new Node(nodeType, (Node)left, (Node)right);
    }

    public Object createBinary(int nodeType, int nodeOp, Object left,
                               Object right)
    {
        if (nodeType == TokenStream.ASSIGN) {
            return createAssignment(nodeOp, (Node) left, (Node) right,
                                    null, false);
        }
        return new Node(nodeType, (Node) left, (Node) right, nodeOp);
    }

    public Object createAssignment(int nodeOp, Node left, Node right,
                                   Class convert, boolean postfix)
    {
        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?
                reportError("msg.bad.lhs.assign");
        }

        return new Node(TokenStream.ASSIGN, left, right, nodeOp);
    }

    private Node createConvert(Class toType, Node expr) {
        if (toType == null)
            return expr;
        Node result = new Node(TokenStream.CONVERT, expr);
        result.putProp(Node.TYPE_PROP, Number.class);
        return result;
    }

    public static boolean hasSideEffects(Node exprTree) {
        switch (exprTree.getType()) {
            case TokenStream.INC:
            case TokenStream.DEC:
            case TokenStream.SETPROP:
            case TokenStream.SETELEM:
            case TokenStream.SETNAME:
            case TokenStream.CALL:
            case TokenStream.NEW:
                return true;
            default:
                Node child = exprTree.getFirstChild();
                while (child != null) {
                    if (hasSideEffects(child))
                        return true;
                    else
                        child = child.getNext();
                }
                break;
        }
        return false;
    }

    private void reportError(String msgResource) {

        String message = Context.getMessage0(msgResource);
        Context.reportError(
            message, ts.getSourceName(), ts.getLineno(),
            ts.getLine(), ts.getOffset());
    }

    // 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;
}
