/* -*- 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
 * Roger Lawrence
 * Mike McCabe
 *
 * 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.
 */
// Modified by Google

package com.google.gwt.dev.js.rhino;

/**
 * This class implements the root of the intermediate representation.
 *
 * @author Norris Boyd
 * @author Mike McCabe
 */

public class Node implements Cloneable {

    private static class NumberNode extends Node {

        NumberNode(double number) {
            super(TokenStream.NUMBER);
            this.number = number;
        }

        public double getDouble() {
          return this.number;
        }

        public boolean equals(Object o) {
            return o instanceof NumberNode
                && getDouble() == ((NumberNode) o).getDouble();
        }

        private double number;
    }

    private static class StringNode extends Node {

        StringNode(int type, String str) {
            super(type);
            if (null == str) {
                throw new IllegalArgumentException("StringNode: str is null");
            }
            this.str = str;
        }

        /** returns the string content.
          * @return non null.
          */
        public String getString() {
            return this.str;
        }

        /** sets the string content.
          * @param str the new value.  Non null.
          */
        public void setString(String str) {
            if (null == str) {
                throw new IllegalArgumentException("StringNode: str is null");
            }
            this.str = str;
        }

        public boolean equals(Object o) {
            if (!(o instanceof StringNode)) { return false; }
            return o instanceof StringNode
                && this.str.equals(((StringNode) o).str);
        }

        private String str;
    }

    public Node(int nodeType) {
        type = nodeType;
    }

    public Node(int nodeType, Node child) {
        type = nodeType;
        first = last = child;
        child.next = null;
    }

    public Node(int nodeType, Node left, Node right) {
        type = nodeType;
        first = left;
        last = right;
        left.next = right;
        right.next = null;
    }

    public Node(int nodeType, Node left, Node mid, Node right) {
        type = nodeType;
        first = left;
        last = right;
        left.next = mid;
        mid.next = right;
        right.next = null;
    }

    public Node(int nodeType, Node left, Node mid, Node mid2, Node right) {
        type = nodeType;
        first = left;
        last = right;
        left.next = mid;
        mid.next = mid2;
        mid2.next = right;
        right.next = null;
    }

    public Node(int nodeType, Node[] children) {
        this.type = nodeType;
        if (children.length != 0) {
            this.first = children[0];
            this.last = children[children.length - 1];

            for (int i = 1; i < children.length; i++) {
                if (null != children[i - 1].next) {
                    // fail early on loops.  implies same node in array twice
                    throw new IllegalArgumentException("duplicate child");
                }
                children[i - 1].next = children[i];
            }
            if (null != this.last.next) {
                // fail early on loops.  implies same node in array twice
                throw new IllegalArgumentException("duplicate child");
            }
        }
    }

    public Node(int nodeType, int value) {
        type = nodeType;
        intDatum = value;
    }

    public Node(int nodeType, Node child, int value) {
        this(nodeType, child);
        intDatum = value;
    }

    public Node(int nodeType, Node left, Node right, int value) {
        this(nodeType, left, right);
        intDatum = value;
    }

    public Node(int nodeType, Node left, Node mid, Node right, int value) {
        this(nodeType, left, mid, right);
        intDatum = value;
    }

    public static Node newNumber(double number) {
        return new NumberNode(number);
    }

    public static Node newString(String str) {
        return new StringNode(TokenStream.STRING, str);
    }

    public static Node newString(int type, String str) {
        return new StringNode(type, str);
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public int getIntDatum() {
        return this.intDatum;
    }

    public boolean hasChildren() {
        return first != null;
    }

    public Node getFirstChild() {
        return first;
    }

    public Node getLastChild() {
        return last;
    }

    public Node getNext() {
        return next;
    }

    public int getChildCount() {
        int c = 0;
        for (Node n = first; n != null; n = n.next)
            c++;

        return c;
    }


    public Node getChildBefore(Node child) {
        if (child == first)
            return null;
        Node n = first;
        while (n.next != child) {
            n = n.next;
            if (n == null)
                throw new RuntimeException("node is not a child");
        }
        return n;
    }

    public Node getLastSibling() {
        Node n = this;
        while (n.next != null) {
            n = n.next;
        }
        return n;
    }

    public void addChildToFront(Node child) {
        child.next = first;
        first = child;
        if (last == null) {
            last = child;
        }
    }

    public void addChildToBack(Node child) {
        child.next = null;
        if (last == null) {
            first = last = child;
            return;
        }
        last.next = child;
        last = child;
    }

    public void addChildrenToFront(Node children) {
        Node lastSib = children.getLastSibling();
        lastSib.next = first;
        first = children;
        if (last == null) {
            last = lastSib;
        }
    }

    public void addChildrenToBack(Node children) {
        if (last != null) {
            last.next = children;
        }
        last = children.getLastSibling();
        if (first == null) {
            first = children;
        }
    }

    /**
     * Add 'child' before 'node'.
     */
    public void addChildBefore(Node newChild, Node node) {
        if (newChild.next != null)
            throw new RuntimeException(
                      "newChild had siblings in addChildBefore");
        if (first == node) {
            newChild.next = first;
            first = newChild;
            return;
        }
        Node prev = getChildBefore(node);
        addChildAfter(newChild, prev);
    }

    /**
     * Add 'child' after 'node'.
     */
    public void addChildAfter(Node newChild, Node node) {
        if (newChild.next != null)
            throw new RuntimeException(
                      "newChild had siblings in addChildAfter");
        newChild.next = node.next;
        node.next = newChild;
        if (last == node)
            last = newChild;
    }

    public void removeChild(Node child) {
        Node prev = getChildBefore(child);
        if (prev == null)
            first = first.next;
        else
            prev.next = child.next;
        if (child == last) last = prev;
        child.next = null;
    }

    public void replaceChild(Node child, Node newChild) {
        newChild.next = child.next;
        if (child == first) {
            first = newChild;
        } else {
            Node prev = getChildBefore(child);
            prev.next = newChild;
        }
        if (child == last)
            last = newChild;
        child.next = null;
    }

    public void replaceChildAfter(Node prevChild, Node newChild) {
        Node child = prevChild.next;
        newChild.next = child.next;
        prevChild.next = newChild;
        if (child == last)
            last = newChild;
        child.next = null;
    }

    public static final int
        TARGET_PROP       =  1,
        BREAK_PROP        =  2,
        CONTINUE_PROP     =  3,
        ENUM_PROP         =  4,
        FUNCTION_PROP     =  5,
        TEMP_PROP         =  6,
        LOCAL_PROP        =  7,
        CODEOFFSET_PROP   =  8,
        FIXUPS_PROP       =  9,
        VARS_PROP         = 10,
        USES_PROP         = 11,
        REGEXP_PROP       = 12,
        CASES_PROP        = 13,
        DEFAULT_PROP      = 14,
        CASEARRAY_PROP    = 15,
        SOURCENAME_PROP   = 16,
        SOURCE_PROP       = 17,
        TYPE_PROP         = 18,
        SPECIAL_PROP_PROP = 19,
        LABEL_PROP        = 20,
        FINALLY_PROP      = 21,
        LOCALCOUNT_PROP   = 22,
    /*
        the following properties are defined and manipulated by the
        optimizer -
        TARGETBLOCK_PROP - the block referenced by a branch node
        VARIABLE_PROP - the variable referenced by a BIND or NAME node
        LASTUSE_PROP - that variable node is the last reference before
                        a new def or the end of the block
        ISNUMBER_PROP - this node generates code on Number children and
                        delivers a Number result (as opposed to Objects)
        DIRECTCALL_PROP - this call node should emit code to test the function
                          object against the known class and call diret if it
                          matches.
    */

        TARGETBLOCK_PROP  = 23,
        VARIABLE_PROP     = 24,
        LASTUSE_PROP      = 25,
        ISNUMBER_PROP     = 26,
        DIRECTCALL_PROP   = 27,

        BASE_LINENO_PROP  = 28,
        END_LINENO_PROP   = 29,
        SPECIALCALL_PROP  = 30,
        DEBUGSOURCE_PROP  = 31;

    public static final int    // this value of the ISNUMBER_PROP specifies
        BOTH = 0,               // which of the children are Number types
        LEFT = 1,
        RIGHT = 2;

    private static final String propToString(int propType) {
        switch (propType) {
            case TARGET_PROP:        return "target";
            case BREAK_PROP:         return "break";
            case CONTINUE_PROP:      return "continue";
            case ENUM_PROP:          return "enum";
            case FUNCTION_PROP:      return "function";
            case TEMP_PROP:          return "temp";
            case LOCAL_PROP:         return "local";
            case CODEOFFSET_PROP:    return "codeoffset";
            case FIXUPS_PROP:        return "fixups";
            case VARS_PROP:          return "vars";
            case USES_PROP:          return "uses";
            case REGEXP_PROP:        return "regexp";
            case CASES_PROP:         return "cases";
            case DEFAULT_PROP:       return "default";
            case CASEARRAY_PROP:     return "casearray";
            case SOURCENAME_PROP:    return "sourcename";
            case SOURCE_PROP:        return "source";
            case TYPE_PROP:          return "type";
            case SPECIAL_PROP_PROP:  return "special_prop";
            case LABEL_PROP:         return "label";
            case FINALLY_PROP:       return "finally";
            case LOCALCOUNT_PROP:    return "localcount";

            case TARGETBLOCK_PROP:   return "targetblock";
            case VARIABLE_PROP:      return "variable";
            case LASTUSE_PROP:       return "lastuse";
            case ISNUMBER_PROP:      return "isnumber";
            case DIRECTCALL_PROP:    return "directcall";

            case BASE_LINENO_PROP:   return "base_lineno";
            case END_LINENO_PROP:    return "end_lineno";
            case SPECIALCALL_PROP:   return "specialcall";
            case DEBUGSOURCE_PROP:   return "debugsource";

            default: Context.codeBug();

        }
        return null;
    }

    public Object getProp(int propType) {
        if (props == null)
            return null;
        return props.getObject(propType);
    }

    public int getIntProp(int propType, int defaultValue) {
        if (props == null)
            return defaultValue;
        return props.getInt(propType, defaultValue);
    }

    public int getExistingIntProp(int propType) {
        return props.getExistingInt(propType);
    }

    public void putProp(int propType, Object prop) {
        if (prop == null) {
            removeProp(propType);
        }
        else {
            if (props == null) {
                props = new UintMap(2);
            }
            props.put(propType, prop);
        }
    }

    public void putIntProp(int propType, int prop) {
        if (props == null)
            props = new UintMap(2);
        props.put(propType, prop);
    }

    public void removeProp(int propType) {
        if (props != null) {
            props.remove(propType);
        }
    }

    public int getOperation() {
        switch (type) {
            case TokenStream.EQOP:
            case TokenStream.RELOP:
            case TokenStream.UNARYOP:
            case TokenStream.PRIMARY:
                return intDatum;
        }
        Context.codeBug();
        return 0;
    }

    public int getLineno() {
        if (hasLineno()) {
            return intDatum;
        }
        return -1;
    }

    private boolean hasLineno() {
        switch (type) {
            case TokenStream.EXPRSTMT:
            case TokenStream.BLOCK:
            case TokenStream.VAR:
            case TokenStream.WHILE:
            case TokenStream.DO:
            case TokenStream.SWITCH:
            case TokenStream.CATCH:
            case TokenStream.THROW:
            case TokenStream.RETURN:
            case TokenStream.BREAK:
            case TokenStream.CONTINUE:
            case TokenStream.WITH:
                return true;
        }
        return false;
    }

    /** Can only be called when <tt>getType() == TokenStream.NUMBER</tt> */
    public double getDouble() throws UnsupportedOperationException {
        throw new UnsupportedOperationException(this + " is not a number node");
    }

    /** Can only be called when node has String context. */
    public String getString() throws UnsupportedOperationException {
        throw new UnsupportedOperationException(this + " is not a string node");
    }

    /** Can only be called when node has String context. */
    public void setString(String s) throws UnsupportedOperationException {
        throw new UnsupportedOperationException(this + " is not a string node");
    }

    /**
     * Not usefully implemented.
     */
    public final int hashCode() {
        assert false : "hashCode not designed";
        return 42; // any arbitrary constant will do
    }

    public boolean equals(Object o) {
        if (!(o instanceof Node)) { return false; }
        return hasLineno()
            || this.getIntDatum() == ((Node) o).getIntDatum();
    }

    public Node cloneNode() {
        Node result;
        try {
            result = (Node) super.clone();
            result.next = null;
            result.first = null;
            result.last = null;
        }
        catch (CloneNotSupportedException e) {
            throw new RuntimeException(e.getMessage());
        }
        return result;
    }

    public Node cloneTree() {
        Node result = cloneNode();
        for (Node n2 = getFirstChild(); n2 != null; n2 = n2.getNext()) {
            Node n2clone = n2.cloneTree();
            if (result.last != null) {
                result.last.next = n2clone;
            }
            if (result.first == null) {
                result.first = n2clone;
            }
            result.last = n2clone;
        }
        return result;
    }



    public String toString() {
        if (Context.printTrees) {
            StringBuffer sb = new StringBuffer(TokenStream.tokenToName(type));
            if (this instanceof StringNode) {
                sb.append(' ');
                sb.append(getString());
            } else {
                switch (type) {
                    case TokenStream.TARGET:
                        sb.append(' ');
                        sb.append(hashCode());
                        break;
                    case TokenStream.NUMBER:
                        sb.append(' ');
                        sb.append(getDouble());
                        break;
                    case TokenStream.FUNCTION:
                        sb.append(' ');
                        sb.append(first.getString());
                        break;
                }
            }
            if (intDatum != -1) {
                sb.append(' ');
                sb.append(intDatum);
            }
            if (props == null)
                return sb.toString();

            int[] keys = props.getKeys();
            for (int i = 0; i != keys.length; ++i) {
                int key = keys[i];
                sb.append(" [");
                sb.append(propToString(key));
                sb.append(": ");
                switch (key) {
                    case FIXUPS_PROP : // can't add this as it recurses
                        sb.append("fixups property");
                        break;
                    case SOURCE_PROP : // can't add this as it has unprintables
                        sb.append("source property");
                        break;
                    case TARGETBLOCK_PROP : // can't add this as it recurses
                        sb.append("target block property");
                        break;
                    case LASTUSE_PROP :     // can't add this as it is dull
                        sb.append("last use property");
                        break;
                    default :
                        Object obj = props.getObject(key);
                        if (obj != null) {
                            sb.append(obj.toString());
                        } else {
                            sb.append(props.getExistingInt(key));
                        }
                        break;
                }
                sb.append(']');
            }
            return sb.toString();
        }
        return null;
    }

    public String toStringTree() {
        return toStringTreeHelper(0);
    }


    private String toStringTreeHelper(int level) {
        if (Context.printTrees) {
            StringBuffer s = new StringBuffer();
            for (int i=0; i < level; i++) {
                s.append("    ");
            }
            s.append(toString());
            s.append('\n');
            for (Node cursor = getFirstChild(); cursor != null;
                 cursor = cursor.getNext())
            {
                Node n = cursor;
                s.append(n.toStringTreeHelper(level+1));
            }
            return s.toString();
        }
        return "";
    }

    /**
     * Checks if the subtree under this node is the same as another subtree.
     * Returns null if it's equal, or a message describing the differences.
     */
    public String checkTreeEquals(Node node2) {
        boolean eq = false;

        if (type == node2.getType() &&
            getChildCount() == node2.getChildCount() &&
            getClass() == node2.getClass()) {

            eq = this.equals(node2);
        }

        if (!eq) {
            return "Node tree inequality:\nTree1:\n" + toStringTreeHelper(1) +
                "\n\nTree2:\n" + node2.toStringTreeHelper(1);
        }

        String res = null;
        Node n, n2;
        for (n = first, n2 = node2.first;
             res == null && n != null;
             n = n.next, n2 = n2.next) {
            res = n.checkTreeEquals(n2);
            if (res != null) {
                return res;
            }
        }
        return res;
    }

    public void setIsSyntheticBlock(boolean val) {
        isSyntheticBlock = val;
    }

    public boolean isSyntheticBlock() {
        return isSyntheticBlock;
    }

    int type;              // type of the node; TokenStream.NAME for example
    Node next;             // next sibling
    private Node first;    // first element of a linked list of children
    private Node last;     // last element of a linked list of children
    private int intDatum = -1;    // encapsulated int data; depends on type
    private UintMap props;
    private boolean isSyntheticBlock = false;
}
