/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/* Generated By:JJTree: Do not edit this line. ASTFunDecl.java */
/* JJT: 0.3pre1 */

package Mini;

import java.io.PrintWriter;
import java.util.Iterator;

import org.apache.bcel.Const;
import org.apache.bcel.generic.ALOAD;
import org.apache.bcel.generic.ASTORE;
import org.apache.bcel.generic.ArrayType;
import org.apache.bcel.generic.BranchHandle;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.GETSTATIC;
import org.apache.bcel.generic.GOTO;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.InstructionConst;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.InstructionTargeter;
import org.apache.bcel.generic.LocalVariableGen;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.TargetLostException;
import org.apache.bcel.generic.Type;
import org.apache.bcel.util.InstructionFinder;

/**
 */
public class ASTFunDecl extends SimpleNode implements MiniParserTreeConstants {
    private static final InstructionFinder.CodeConstraint my_constraint = match -> {
        final BranchInstruction if_icmp = (BranchInstruction) match[0].getInstruction();
        final GOTO goto_ = (GOTO) match[2].getInstruction();
        return if_icmp.getTarget() == match[3] && goto_.getTarget() == match[4];
    };
    /*
     * Used to simpulate stack with local vars and compute maximum stack size.
     */
    static int size, max_size;

    private static String getVarDecls() {
        final StringBuilder buf = new StringBuilder("    int ");

        for (int i = 0; i < max_size; i++) {
            buf.append("_s" + i);

            if (i < max_size - 1) {
                buf.append(", ");
            }
        }

        buf.append(";\n");
        return buf.toString();
    }

    public static Node jjtCreate(final MiniParser p, final int id) {
        return new ASTFunDecl(p, id);
    }

    /**
     * Replaces instruction sequences (typically generated by ASTIfExpr) of the form
     *
     * IF_ICMP__, ICONST_1, GOTO, ICONST_0, IFEQ, Instruction
     *
     * where the IF_ICMP__ branches to the ICONST_0 (else part) and the GOTO branches to the IFEQ with the simpler
     * expression
     *
     * IF_ICMP__, Instruction
     *
     * where the IF_ICMP__ now branches to the target of the previous IFEQ instruction.
     */
    private static void optimizeIFs(final InstructionList il) {
        final InstructionFinder f = new InstructionFinder(il);
        final String pat = "IF_ICMP ICONST_1 GOTO ICONST_0 IFEQ Instruction";

        for (final Iterator<InstructionHandle[]> it = f.search(pat, my_constraint); it.hasNext();) {
            final InstructionHandle[] match = it.next();
            // Everything ok, update code
            final BranchInstruction ifeq = (BranchInstruction) match[4].getInstruction();
            final BranchHandle if_icmp = (BranchHandle) match[0];

            if_icmp.setTarget(ifeq.getTarget());

            try {
                il.delete(match[1], match[4]);
            } catch (final TargetLostException e) {
                final InstructionHandle[] targets = e.getTargets();

                System.err.println(targets[0]);

                for (final InstructionHandle target : targets) {
                    final InstructionTargeter[] targeters = target.getTargeters();

                    for (final InstructionTargeter targeter : targeters) {
                        // TODO Is this really identity equality and not object equality?
                        if (target != match[4] || targeter != match[2]) {
                            System.err.println("Unexpected: " + e);
                        }
                    }
                }
            }
        }
    }

    static String pop() {
        return "_s" + --size;
    }

    /**
     * Used by byte_code()
     */
    static void pop(final int s) {
        size -= s;
    }

    static void push() {
        push(1);
    }

    static void push(final int s) {
        size += s;

        if (size > max_size) {
            max_size = size;
        }
    }

    /**
     * Used byte code()
     */
    static void push(final StringBuffer buf, final String str) {
        buf.append("    _s" + size + " = " + str + ";\n");
        push(1);
    }

    static void reset() {
        size = max_size = 0;
    }

    private ASTIdent name;

    private ASTIdent[] argv;

    private ASTExpr body;

    private int type = Const.T_UNKNOWN;

    private int line, column;

    private boolean is_simple; // true, if simple expression like '12 + f(a)'

    private boolean is_recursive; // Not used yet, TODO

    // private int max_depth; // max. expression tree depth
    private Environment env;

    ASTFunDecl(final ASTIdent name, final ASTIdent[] argv, final ASTExpr body, final int type) {
        this(JJTFUNDECL);

        this.name = name;
        this.argv = argv;
        this.body = body;
        this.type = type;
    }

    // Generated methods
    ASTFunDecl(final int id) {
        super(id);
    }

    ASTFunDecl(final MiniParser p, final int id) {
        super(p, id);
    }

    /**
     * Fifth pass, produce Java byte code.
     */
    public void byte_code(final ClassGen classGen, final ConstantPoolGen cp) {
        MethodGen method = null;
        boolean main = false, ignore = false;
        final String className = classGen.getClassName();
        final String fname = name.getName();
        final InstructionList il = new InstructionList();

        Type[] args = {new ArrayType(Type.STRING, 1)}; // default for 'main'
        String[] arg_names = {"$argv"};

        if (fname.equals("main")) {
            method = new MethodGen(Const.ACC_STATIC | Const.ACC_PUBLIC, Type.VOID, args, arg_names, "main", className, il, cp);

            main = true;
        } else if (fname.equals("READ") || fname.equals("WRITE")) { // Do nothing
            ignore = true;
        } else {
            final int size = argv.length;

            arg_names = new String[size];
            args = new Type[size];

            for (int i = 0; i < size; i++) {
                args[i] = Type.INT;
                arg_names[i] = argv[i].getName();
            }

            method = new MethodGen(Const.ACC_STATIC | Const.ACC_PRIVATE | Const.ACC_FINAL, Type.INT, args, arg_names, fname, className, il, cp);

            final LocalVariableGen[] lv = method.getLocalVariables();
            for (int i = 0; i < size; i++) {
                final Variable entry = (Variable) env.get(arg_names[i]);
                entry.setLocalVariable(lv[i]);
            }

            method.addException("java.io.IOException");
        }

        if (!ignore) {
            body.byte_code(il, method, cp);

            if (main) {
                final ObjectType eType = new ObjectType("java.lang.Exception");
                final InstructionHandle start = il.getStart();
                InstructionHandle end, handler, end_handler;
                final LocalVariableGen exc = method.addLocalVariable("$e", eType, null, null);
                final int slot = exc.getIndex();

                il.append(InstructionConst.POP);
                pop(); // Remove last element on stack
                end = il.append(InstructionConst.RETURN); // Use instruction constants, if possible

                // catch
                handler = il.append(new ASTORE(slot)); // save exception object
                il.append(new GETSTATIC(cp.addFieldref("java.lang.System", "err", "Ljava/io/PrintStream;")));
                il.append(new ALOAD(slot));
                push(2);
                il.append(new INVOKEVIRTUAL(cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/Object;)V")));
                pop(2);
                end_handler = il.append(InstructionConst.RETURN);
                method.addExceptionHandler(start, end, handler, eType);
                exc.setStart(handler);
                exc.setEnd(end_handler);
            } else {
                il.append(InstructionConst.IRETURN); // Reuse object to save memory
            }

            method.removeNOPs(); // First optimization pass, provided by MethodGen
            optimizeIFs(il); // Second optimization pass, application-specific
            method.setMaxStack(max_size);
            classGen.addMethod(method.getMethod());
        }

        il.dispose(); // Dispose instruction handles for better memory utilization

        reset();
    }

    /**
     * Overrides SimpleNode.closeNode() Cast children to appropriate type.
     */
    @Override
    public void closeNode() {
        name = (ASTIdent) children[0];
        body = (ASTExpr) children[children.length - 1];

        argv = new ASTIdent[children.length - 2]; // May be 0-size array
        for (int i = 1; i < children.length - 1; i++) {
            argv[i - 1] = (ASTIdent) children[i];
        }

        children = null; // Throw away old reference
    }

    /**
     * Fourth pass, produce Java code.
     */
    public void code(final PrintWriter out) {
        String expr;
        boolean main = false, ignore = false;

        final String fname = name.getName();

        if (fname.equals("main")) {
            out.println("  public static void main(String[] _argv) {");
            main = true;
        } else if (fname.equals("READ") || fname.equals("WRITE")) { // Do nothing
            ignore = true;
        } else {
            out.print("  public static final " + "int" + // type_names[type] +
                " " + fname + "(");

            for (int i = 0; i < argv.length; i++) {
                out.print("int " + argv[i].getName());

                if (i < argv.length - 1) {
                    out.print(", ");
                }
            }

            out.println(")\n    throws IOException\n  {");
        }

        if (!ignore) {
            final StringBuffer buf = new StringBuffer();

            body.code(buf);
            out.println(getVarDecls());

            expr = buf.toString();

            if (main) {
                out.println("    try {");
            }

            out.println(expr);

            if (main) {
                out.println("    } catch (Exception e) { System.err.println(e); }\n  }\n");
            } else {
                out.println("\n    return " + pop() + ";\n  }\n");
            }
        }

        reset();
    }

    /**
     * Overrides SimpleNode.dump()
     */
    @Override
    public void dump(final String prefix) {
        System.out.println(toString(prefix));

        for (final ASTIdent element : argv) {
            element.dump(prefix + " ");
        }

        body.dump(prefix + " ");
    }

    /**
     * Second pass.
     *
     * @return type of expression.
     */
    public int eval(final int pass) {
        final int expected = name.getType(); // Maybe other function has already called us
        type = body.eval(expected); // And updated the env

        if (expected != Const.T_UNKNOWN && type != expected) {
            MiniC.addError(line, column,
                    "Function f ist not of type " + Const.getTypeName(expected) + " as previously assumed, but " + Const.getTypeName(type));
        }

        name.setType(type);

        is_simple = body.isSimple();

        if (pass == 2 && type == Const.T_UNKNOWN) {
            is_recursive = true;
        }

        return type;
    }

    public ASTIdent[] getArgs() {
        return argv;
    }

    public int getColumn() {
        return column;
    }

    public int getLine() {
        return line;
    }

    public ASTIdent getName() {
        return name;
    }

    public int getNoArgs() {
        return argv.length;
    }

    public int getType() {
        return type;
    }

    public boolean isrecursive() {
        return is_recursive;
    }

    public boolean isSimple() {
        return is_simple;
    }

    public void setColumn(final int column) {
        this.column = column;
    }

    public void setLine(final int line) {
        this.line = line;
    }

    public void setPosition(final int line, final int column) {
        this.line = line;
        this.column = column;
    }

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

    /**
     * Overrides SimpleNode.toString()
     */
    @Override
    public String toString() {
        final StringBuilder buf = new StringBuilder();
        buf.append(jjtNodeName[id] + " " + name + "(");

        for (int i = 0; i < argv.length; i++) {
            buf.append(argv[i].getName());
            if (i < argv.length - 1) {
                buf.append(", ");
            }
        }

        buf.append(")");
        return buf.toString();
    }

    /**
     * First pass of parse tree.
     */
    public ASTFunDecl traverse(final Environment env) {
        this.env = env;

        // Put arguments into hash table aka environment
        for (final ASTIdent element : argv) {
            final EnvEntry entry = env.get(element.getName());

            if (entry != null) {
                MiniC.addError(element.getLine(), element.getColumn(), "Redeclaration of " + entry + ".");
            } else {
                env.put(new Variable(element));
            }
        }

        /*
         * Update entry of this function, that is, sets argument references. The entry is already in there by garantee, but may be
         * of the wrong type: The user-defined a function 'TRUE', for example and 'TRUE' is of type 'Variable'.
         */
        try {
            final Function fun = (Function) env.get(name.getName());
            fun.setArgs(argv);
        } catch (final ClassCastException e) {
        } // Who cares?

        body = body.traverse(env); // Traverse expression body

        return this;
    }
}
