/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.codegen;

import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import jdk.nashorn.internal.IntDeque;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LexicalContextNode;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.ir.WithNode;

/**
 * A lexical context that also tracks if we have any dynamic scopes in the context. Such scopes can have new
 * variables introduced into them at run time - a with block or a function directly containing an eval call.
 * Furthermore, this class keeps track of current discard state, which the current method emitter being used is,
 * the current compile unit, and local variable indexes
 */
final class CodeGeneratorLexicalContext extends LexicalContext {
    private int dynamicScopeCount;

    /** Map of shared scope call sites */
    private final Map<SharedScopeCall, SharedScopeCall> scopeCalls = new HashMap<>();

    /** Compile unit stack - every time we start a sub method (e.g. a split) we push one */
    private final Deque<CompileUnit> compileUnits = new ArrayDeque<>();

    /** Method emitter stack - every time we start a sub method (e.g. a split) we push one */
    private final Deque<MethodEmitter> methodEmitters = new ArrayDeque<>();

    /** The discard stack - whenever we enter a discard node we keep track of its return value status -
     *  i.e. should we keep it or throw it away */
    private final Deque<Node> discard = new ArrayDeque<>();

    private final Deque<Map<String, Collection<Label>>> unwarrantedOptimismHandlers = new ArrayDeque<>();
    private final Deque<StringBuilder> slotTypesDescriptors = new ArrayDeque<>();
    private final IntDeque splitNodes = new IntDeque();

    /** A stack tracking the next free local variable slot in the blocks. There's one entry for every block
     *  currently on the lexical context stack. */
    private int[] nextFreeSlots = new int[16];

    /** size of next free slot vector */
    private int nextFreeSlotsSize;

    private boolean isWithBoundary(final LexicalContextNode node) {
        return node instanceof Block && !isEmpty() && peek() instanceof WithNode;
    }

    @Override
    public <T extends LexicalContextNode> T push(final T node) {
        if (isWithBoundary(node)) {
            dynamicScopeCount++;
        } else if (node instanceof FunctionNode) {
            if (((FunctionNode)node).inDynamicContext()) {
                dynamicScopeCount++;
            }
            splitNodes.push(0);
        }
        return super.push(node);
    }

    void enterSplitNode() {
        splitNodes.getAndIncrement();
        pushFreeSlots(methodEmitters.peek().getUsedSlotsWithLiveTemporaries());
    }

    void exitSplitNode() {
        final int count = splitNodes.decrementAndGet();
        assert count >= 0;
    }

    @Override
    public <T extends LexicalContextNode> T pop(final T node) {
        final T popped = super.pop(node);
        if (isWithBoundary(node)) {
            dynamicScopeCount--;
            assert dynamicScopeCount >= 0;
        } else if (node instanceof FunctionNode) {
            if (((FunctionNode)node).inDynamicContext()) {
                dynamicScopeCount--;
                assert dynamicScopeCount >= 0;
            }
            assert splitNodes.peek() == 0;
            splitNodes.pop();
        }
        return popped;
    }

    boolean inDynamicScope() {
        return dynamicScopeCount > 0;
    }

    boolean inSplitNode() {
        return !splitNodes.isEmpty() && splitNodes.peek() > 0;
    }

    MethodEmitter pushMethodEmitter(final MethodEmitter newMethod) {
        methodEmitters.push(newMethod);
        return newMethod;
    }

    MethodEmitter popMethodEmitter(final MethodEmitter oldMethod) {
        assert methodEmitters.peek() == oldMethod;
        methodEmitters.pop();
        return methodEmitters.isEmpty() ? null : methodEmitters.peek();
    }

    void pushUnwarrantedOptimismHandlers() {
        unwarrantedOptimismHandlers.push(new HashMap<String, Collection<Label>>());
        slotTypesDescriptors.push(new StringBuilder());
    }

    Map<String, Collection<Label>> getUnwarrantedOptimismHandlers() {
        return unwarrantedOptimismHandlers.peek();
    }

    Map<String, Collection<Label>> popUnwarrantedOptimismHandlers() {
        slotTypesDescriptors.pop();
        return unwarrantedOptimismHandlers.pop();
    }

    CompileUnit pushCompileUnit(final CompileUnit newUnit) {
        compileUnits.push(newUnit);
        return newUnit;
    }

    CompileUnit popCompileUnit(final CompileUnit oldUnit) {
        assert compileUnits.peek() == oldUnit;
        final CompileUnit unit = compileUnits.pop();
        assert unit.hasCode() : "compile unit popped without code";
        unit.setUsed();
        return compileUnits.isEmpty() ? null : compileUnits.peek();
    }

    boolean hasCompileUnits() {
        return !compileUnits.isEmpty();
    }

    Collection<SharedScopeCall> getScopeCalls() {
        return Collections.unmodifiableCollection(scopeCalls.values());
    }

    /**
     * Get a shared static method representing a dynamic scope callsite.
     *
     * @param unit current compile unit
     * @param symbol the symbol
     * @param valueType the value type of the symbol
     * @param returnType the return type
     * @param paramTypes the parameter types
     * @param flags the callsite flags
     * @return an object representing a shared scope call
     */
    SharedScopeCall getScopeCall(final CompileUnit unit, final Symbol symbol, final Type valueType, final Type returnType, final Type[] paramTypes, final int flags) {
        final SharedScopeCall scopeCall = new SharedScopeCall(symbol, valueType, returnType, paramTypes, flags);
        if (scopeCalls.containsKey(scopeCall)) {
            return scopeCalls.get(scopeCall);
        }
        scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName(":scopeCall"));
        scopeCalls.put(scopeCall, scopeCall);
        return scopeCall;
    }

    /**
     * Get a shared static method representing a dynamic scope get access.
     *
     * @param unit current compile unit
     * @param symbol the symbol
     * @param valueType the type of the variable
     * @param flags the callsite flags
     * @return an object representing a shared scope call
     */
    SharedScopeCall getScopeGet(final CompileUnit unit, final Symbol symbol, final Type valueType, final int flags) {
        return getScopeCall(unit, symbol, valueType, valueType, null, flags);
    }

    void onEnterBlock(final Block block) {
        pushFreeSlots(assignSlots(block, isFunctionBody() ? 0 : getUsedSlotCount()));
    }

    private void pushFreeSlots(final int freeSlots) {
        if (nextFreeSlotsSize == nextFreeSlots.length) {
            final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2];
            System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize);
            nextFreeSlots = newNextFreeSlots;
        }
        nextFreeSlots[nextFreeSlotsSize++] = freeSlots;
    }

    int getUsedSlotCount() {
        return nextFreeSlots[nextFreeSlotsSize - 1];
    }

    void releaseSlots() {
        --nextFreeSlotsSize;
        final int undefinedFromSlot = nextFreeSlotsSize == 0 ? 0 : nextFreeSlots[nextFreeSlotsSize - 1];
        if(!slotTypesDescriptors.isEmpty()) {
            slotTypesDescriptors.peek().setLength(undefinedFromSlot);
        }
        methodEmitters.peek().undefineLocalVariables(undefinedFromSlot, false);
    }

    private int assignSlots(final Block block, final int firstSlot) {
        int fromSlot = firstSlot;
        final MethodEmitter method = methodEmitters.peek();
        for (final Symbol symbol : block.getSymbols()) {
            if (symbol.hasSlot()) {
                symbol.setFirstSlot(fromSlot);
                final int toSlot = fromSlot + symbol.slotCount();
                method.defineBlockLocalVariable(fromSlot, toSlot);
                fromSlot = toSlot;
            }
        }
        return fromSlot;
    }

    static Type getTypeForSlotDescriptor(final char typeDesc) {
        // Recognizing both lowercase and uppercase as we're using both to signify symbol boundaries; see
        // MethodEmitter.markSymbolBoundariesInLvarTypesDescriptor().
        switch (typeDesc) {
            case 'I':
            case 'i':
                return Type.INT;
            case 'J':
            case 'j':
                return Type.LONG;
            case 'D':
            case 'd':
                return Type.NUMBER;
            case 'A':
            case 'a':
                return Type.OBJECT;
            case 'U':
            case 'u':
                return Type.UNKNOWN;
            default:
                throw new AssertionError();
        }
    }

    void pushDiscard(final Node node) {
        discard.push(node);
    }

    Node popDiscard() {
        return discard.pop();
    }

    Node getCurrentDiscard() {
        return discard.peek();
    }

    int quickSlot(final Type type) {
        return methodEmitters.peek().defineTemporaryLocalVariable(type.getSlots());
    }
}

