/*
 *  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
 *
 *    http://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.
 */
package org.codehaus.groovy.classgen;

import groovy.lang.GroovyRuntimeException;
import org.apache.groovy.io.StringBuilderWriter;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.InnerClassNode;
import org.codehaus.groovy.ast.InterfaceHelperClassNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.PackageNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.PropertyNode;
import org.codehaus.groovy.ast.expr.AnnotationConstantExpression;
import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.ArrayExpression;
import org.codehaus.groovy.ast.expr.AttributeExpression;
import org.codehaus.groovy.ast.expr.BinaryExpression;
import org.codehaus.groovy.ast.expr.BitwiseNegationExpression;
import org.codehaus.groovy.ast.expr.BooleanExpression;
import org.codehaus.groovy.ast.expr.CastExpression;
import org.codehaus.groovy.ast.expr.ClassExpression;
import org.codehaus.groovy.ast.expr.ClosureExpression;
import org.codehaus.groovy.ast.expr.ClosureListExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
import org.codehaus.groovy.ast.expr.DeclarationExpression;
import org.codehaus.groovy.ast.expr.EmptyExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.FieldExpression;
import org.codehaus.groovy.ast.expr.GStringExpression;
import org.codehaus.groovy.ast.expr.LambdaExpression;
import org.codehaus.groovy.ast.expr.ListExpression;
import org.codehaus.groovy.ast.expr.MapEntryExpression;
import org.codehaus.groovy.ast.expr.MapExpression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.MethodPointerExpression;
import org.codehaus.groovy.ast.expr.MethodReferenceExpression;
import org.codehaus.groovy.ast.expr.NotExpression;
import org.codehaus.groovy.ast.expr.PostfixExpression;
import org.codehaus.groovy.ast.expr.PrefixExpression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
import org.codehaus.groovy.ast.expr.RangeExpression;
import org.codehaus.groovy.ast.expr.SpreadExpression;
import org.codehaus.groovy.ast.expr.SpreadMapExpression;
import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
import org.codehaus.groovy.ast.expr.TernaryExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.expr.UnaryMinusExpression;
import org.codehaus.groovy.ast.expr.UnaryPlusExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.AssertStatement;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.BreakStatement;
import org.codehaus.groovy.ast.stmt.CaseStatement;
import org.codehaus.groovy.ast.stmt.CatchStatement;
import org.codehaus.groovy.ast.stmt.ContinueStatement;
import org.codehaus.groovy.ast.stmt.DoWhileStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.ForStatement;
import org.codehaus.groovy.ast.stmt.IfStatement;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.ast.stmt.SwitchStatement;
import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
import org.codehaus.groovy.ast.stmt.ThrowStatement;
import org.codehaus.groovy.ast.stmt.TryCatchStatement;
import org.codehaus.groovy.ast.stmt.WhileStatement;
import org.codehaus.groovy.ast.tools.WideningCategories;
import org.codehaus.groovy.classgen.asm.BytecodeHelper;
import org.codehaus.groovy.classgen.asm.BytecodeVariable;
import org.codehaus.groovy.classgen.asm.MethodCaller;
import org.codehaus.groovy.classgen.asm.MethodCallerMultiAdapter;
import org.codehaus.groovy.classgen.asm.MopWriter;
import org.codehaus.groovy.classgen.asm.OperandStack;
import org.codehaus.groovy.classgen.asm.OptimizingStatementWriter;
import org.codehaus.groovy.classgen.asm.WriterController;
import org.codehaus.groovy.classgen.asm.WriterControllerFactory;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.syntax.RuntimeParserException;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.util.TraceMethodVisitor;

import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static org.apache.groovy.util.BeanUtils.capitalize;

/**
 * Generates Java class versions of Groovy classes using ASM.
 */
public class AsmClassGenerator extends ClassGenerator {

    // fields
    public  static final MethodCallerMultiAdapter setField = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "setField", false, false);
    public  static final MethodCallerMultiAdapter getField = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "getField", false, false);
  //private static final MethodCallerMultiAdapter setFieldOnSuper = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "setFieldOnSuper", false, false);
  //private static final MethodCallerMultiAdapter getFieldOnSuper = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "getFieldOnSuper", false, false);
    public  static final MethodCallerMultiAdapter setGroovyObjectField = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "setGroovyObjectField", false, false);
    public  static final MethodCallerMultiAdapter getGroovyObjectField = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "getGroovyObjectField", false, false);

    // properties
    public  static final MethodCallerMultiAdapter setProperty = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "setProperty", false, false);
    private static final MethodCallerMultiAdapter getProperty = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "getProperty", false, false);
  //private static final MethodCallerMultiAdapter setPropertyOnSuper = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "setPropertyOnSuper", false, false);
  //private static final MethodCallerMultiAdapter getPropertyOnSuper = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "getPropertyOnSuper", false, false);
    private static final MethodCallerMultiAdapter setGroovyObjectProperty = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "setGroovyObjectProperty", false, false);
    private static final MethodCallerMultiAdapter getGroovyObjectProperty = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "getGroovyObjectProperty", false, false);

    // spread expressions
    private static final MethodCaller spreadMap = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "spreadMap");
    private static final MethodCaller despreadList = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "despreadList");

    // type conversions
    private static final MethodCaller createMapMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createMap");
    private static final MethodCaller createListMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createList");
    private static final MethodCaller createRangeMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createRange");
    private static final MethodCaller createPojoWrapperMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createPojoWrapper");
    private static final MethodCaller createGroovyObjectWrapperMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createGroovyObjectWrapper");

    private final Map<String,ClassNode> referencedClasses = new HashMap<>();
    private boolean passingParams;

    public static final boolean CREATE_DEBUG_INFO = true;
    public static final boolean CREATE_LINE_NUMBER_INFO = true;
    public static final boolean ASM_DEBUG = false; // add marker in the bytecode to show source-bytecode relationship
    public static final String MINIMUM_BYTECODE_VERSION = "_MINIMUM_BYTECODE_VERSION";

    private WriterController controller;
    private ASTNode currentASTNode;

    private final SourceUnit source;
    private final GeneratorContext context;
    private ClassVisitor classVisitor;
    private final String sourceFile;

    public AsmClassGenerator(final SourceUnit source, final GeneratorContext context, final ClassVisitor classVisitor, final String sourceFile) {
        this.source = source;
        this.context = context;
        this.classVisitor = classVisitor;
        this.sourceFile = sourceFile;
    }

    @Override
    public SourceUnit getSourceUnit() {
        return source;
    }

    public WriterController getController() {
        return controller;
    }

    // GroovyClassVisitor interface
    //--------------------------------------------------------------------------

    @Override
    public void visitClass(final ClassNode classNode) {
        referencedClasses.clear();
        WriterControllerFactory factory = classNode.getNodeMetaData(WriterControllerFactory.class);
        WriterController normalController = new WriterController();
        if (factory != null) {
            this.controller = factory.makeController(normalController);
        } else {
            this.controller = normalController;
        }
        this.controller.init(this, context, classVisitor, classNode);
        this.classVisitor = this.controller.getClassVisitor();

        if (controller.shouldOptimizeForInt() || factory != null) {
            OptimizingStatementWriter.setNodeMeta(controller.getTypeChooser(),classNode);
        }

        try {
            int bytecodeVersion = controller.getBytecodeVersion();
            Object min = classNode.getNodeMetaData(MINIMUM_BYTECODE_VERSION);
            if (min instanceof Integer) {
                int minVersion = (int) min;
                if ((bytecodeVersion ^ V_PREVIEW) < minVersion) {
                    bytecodeVersion = minVersion;
                }
            }
            classVisitor.visit(
                    bytecodeVersion,
                    adjustedClassModifiersForClassWriting(classNode),
                    controller.getInternalClassName(),
                    BytecodeHelper.getGenericsSignature(classNode),
                    controller.getInternalBaseClassName(),
                    BytecodeHelper.getClassInternalNames(classNode.getInterfaces())
            );
            classVisitor.visitSource(sourceFile, null);
            if (classNode instanceof InnerClassNode) {
                InnerClassNode innerClass = (InnerClassNode) classNode;
                MethodNode enclosingMethod = innerClass.getEnclosingMethod();
                if (enclosingMethod != null) {
                    String outerClassName = BytecodeHelper.getClassInternalName(innerClass.getOuterClass().getName());
                    classVisitor.visitOuterClass(outerClassName, enclosingMethod.getName(), BytecodeHelper.getMethodDescriptor(enclosingMethod));
                }
            }
            if (classNode.getName().endsWith("package-info")) {
                PackageNode packageNode = classNode.getPackage();
                if (packageNode != null) {
                    // pull them out of package node but treat them like they were on class node
                    visitAnnotations(classNode, packageNode, classVisitor);
                }
                classVisitor.visitEnd();
                return;
            } else {
                visitAnnotations(classNode, classVisitor);
            }

            if (classNode.isInterface()) {
                ClassNode owner = classNode;
                if (owner instanceof InnerClassNode) {
                    owner = owner.getOuterClass();
                }
                String outerClassName = classNode.getName();
                String name = outerClassName + "$" + context.getNextInnerClassIdx();
                controller.setInterfaceClassLoadingClass(
                        new InterfaceHelperClassNode (
                                owner, name, ACC_SUPER | ACC_SYNTHETIC | ACC_STATIC, ClassHelper.OBJECT_TYPE,
                                controller.getCallSiteWriter().getCallSites()));
                super.visitClass(classNode);
                createInterfaceSyntheticStaticFields();
            } else {
                super.visitClass(classNode);
                MopWriter.Factory mopWriterFactory = classNode.getNodeMetaData(MopWriter.Factory.class);
                if (mopWriterFactory == null) {
                    mopWriterFactory = MopWriter.FACTORY;
                }
                MopWriter mopWriter = mopWriterFactory.create(controller);
                mopWriter.createMopMethods();
                controller.getCallSiteWriter().generateCallSiteArray();
                createSyntheticStaticFields();
            }

            // GROOVY-6750 and GROOVY-6808
            for (Iterator<InnerClassNode> iter = classNode.getInnerClasses(); iter.hasNext();) {
                InnerClassNode innerClass = iter.next();
                makeInnerClassEntry(innerClass);
            }
            makeInnerClassEntry(classNode);

            classVisitor.visitEnd();
        } catch (GroovyRuntimeException e) {
            e.setModule(classNode.getModule());
            throw e;
        } catch (NegativeArraySizeException nase) {
            throw new GroovyRuntimeException("NegativeArraySizeException while processing " + sourceFile, nase);
        } catch (NullPointerException npe) {
            throw new GroovyRuntimeException("NPE while processing " + sourceFile, npe);
        }
    }

    private void makeInnerClassEntry(final ClassNode cn) {
        if (!(cn instanceof InnerClassNode)) return;
        InnerClassNode innerClass = (InnerClassNode) cn;
        String innerClassName = innerClass.getName();
        String innerClassInternalName = BytecodeHelper.getClassInternalName(innerClassName);
        {
            int index = innerClassName.lastIndexOf('$');
            if (index >= 0) innerClassName = innerClassName.substring(index + 1);
        }
        String outerClassName = BytecodeHelper.getClassInternalName(innerClass.getOuterClass().getName());
        MethodNode enclosingMethod = innerClass.getEnclosingMethod();
        if (enclosingMethod != null) {
            // local inner classes do not specify the outer class name
            outerClassName = null;
            if (innerClass.isAnonymous()) innerClassName = null;
        }
        int modifiers = adjustedClassModifiersForInnerClassTable(cn);
        classVisitor.visitInnerClass(innerClassInternalName, outerClassName, innerClassName, modifiers);
    }

    /*
     * See http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.6-300-D.2-5
     * for what flags are allowed depending on the fact we are writing the inner class table
     * or the class itself
     */
    private static int adjustedClassModifiersForInnerClassTable(final ClassNode classNode) {
        int modifiers = classNode.getModifiers();
        modifiers = modifiers & ~ACC_SUPER;
        modifiers = fixInterfaceModifiers(classNode, modifiers);
        return modifiers;
    }

    private static int fixInterfaceModifiers(final ClassNode classNode, int modifiers) {
        // (JLS §9.1.1.1). Such a class file must not have its ACC_FINAL, ACC_SUPER or ACC_ENUM flags set.
        if (classNode.isInterface()) {
            modifiers = modifiers & ~ACC_ENUM;
            modifiers = modifiers & ~ACC_FINAL;
        }
        return modifiers;
    }

    private static int fixInnerClassModifiers(final ClassNode classNode, int modifiers) {
        // on the inner class node itself, private/protected are not allowed
        if (classNode.getOuterClass() != null) {
            if ((modifiers & ACC_PRIVATE) != 0) {
                // GROOVY-6357: The JVM does not allow private modifier on inner classes: should be package private
                modifiers = (modifiers & ~ACC_PRIVATE);
            }
            if ((modifiers & ACC_PROTECTED) != 0) {
                // GROOVY-6357: Following Java's behavior for protected modifier on inner classes: should be public
                modifiers = (modifiers & ~ACC_PROTECTED) | ACC_PUBLIC;
            }
        }
        return modifiers;
    }

    /*
     * Classes but not interfaces should have ACC_SUPER set
     * See http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.6-300-D.2-5
     * for what flags are allowed depending on the fact we are writing the inner class table
     * or the class itself
     */
    private static int adjustedClassModifiersForClassWriting(final ClassNode classNode) {
        int modifiers = classNode.getModifiers();
        boolean needsSuper = !classNode.isInterface();
        modifiers = needsSuper ? modifiers | ACC_SUPER : modifiers & ~ACC_SUPER;
        // eliminate static
        modifiers = modifiers & ~ACC_STATIC;
        modifiers = fixInnerClassModifiers(classNode, modifiers);
        modifiers = fixInterfaceModifiers(classNode, modifiers);
        return modifiers;
    }

    @Override
    protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {
        controller.resetLineNumber();
        Parameter[] parameters = node.getParameters();
        String methodType = BytecodeHelper.getMethodDescriptor(node.getReturnType(), parameters);
        String signature = BytecodeHelper.getGenericsMethodSignature(node);
        int modifiers = node.getModifiers();
        if (isVargs(node.getParameters())) modifiers |= ACC_VARARGS;
        MethodVisitor mv = classVisitor.visitMethod(modifiers, node.getName(), methodType, signature, buildExceptions(node.getExceptions()));
        controller.setMethodVisitor(mv);

        visitAnnotations(node, mv);
        for (int i = 0, n = parameters.length; i < n; i += 1) {
            visitParameterAnnotations(parameters[i], i, mv);
        }

        // add parameter names to the MethodVisitor (jdk8+ only)
        if (Optional.ofNullable(controller.getClassNode().getCompileUnit())
                .orElseGet(context::getCompileUnit).getConfig().getParameters()) {
            for (Parameter parameter : parameters) {
                // TODO: handle ACC_SYNTHETIC for enum method parameters?
                mv.visitParameter(parameter.getName(), 0);
            }
        }

        if (controller.getClassNode().isAnnotationDefinition() && !node.isStaticConstructor()) {
            visitAnnotationDefault(node, mv);
        } else if (!node.isAbstract()) {
            Statement code = node.getCode();
            mv.visitCode();
            // fast path for getter/setters etc.
            if (code instanceof BytecodeSequence && ((BytecodeSequence)code).getInstructions().size() == 1 && ((BytecodeSequence)code).getInstructions().get(0) instanceof BytecodeInstruction) {
               ((BytecodeInstruction)((BytecodeSequence)code).getInstructions().get(0)).visit(mv);
            } else {
                visitStdMethod(node, isConstructor, parameters, code);
            }
            try {
                mv.visitMaxs(0, 0);
            } catch (Exception e) {
                Writer writer = null;
                if (mv instanceof TraceMethodVisitor) {
                    TraceMethodVisitor tracer = (TraceMethodVisitor) mv;
                    writer = new StringBuilderWriter();
                    PrintWriter p = new PrintWriter(writer);
                    tracer.p.print(p);
                    p.flush();
                }
                StringBuilder message = new StringBuilder(64);
                message.append("ASM reporting processing error for ");
                message.append(controller.getClassNode().toString()).append("#").append(node.getName());
                message.append(" with signature ").append(node.getTypeDescriptor());
                message.append(" in ").append(sourceFile).append(":").append(node.getLineNumber());
                if (writer != null) {
                    message.append("\nLast known generated bytecode in last generated method or constructor:\n");
                    message.append(writer);
                }
                throw new GroovyRuntimeException(message.toString(), e);
            }
        }
        mv.visitEnd();
    }

    private void visitStdMethod(final MethodNode node, final boolean isConstructor, final Parameter[] parameters, final Statement code) {
        controller.getCompileStack().init(node.getVariableScope(), parameters);
        controller.getCallSiteWriter().makeSiteEntry();

        MethodVisitor mv = controller.getMethodVisitor();
        final ClassNode superClass = controller.getClassNode().getSuperClass();
        if (isConstructor && (code == null || !((ConstructorNode) node).firstStatementIsSpecialConstructorCall())) {
            boolean hasCallToSuper = false;
            if (code != null && controller.getClassNode() instanceof InnerClassNode) {
                // if the class not is an inner class node, there are chances that the call to super is already added
                // so we must ensure not to add it twice (see GROOVY-4471)
                if (code instanceof BlockStatement) {
                    for (Statement statement : ((BlockStatement) code).getStatements()) {
                        if (statement instanceof ExpressionStatement) {
                            final Expression expression = ((ExpressionStatement) statement).getExpression();
                            if (expression instanceof ConstructorCallExpression) {
                                ConstructorCallExpression call = (ConstructorCallExpression) expression;
                                if (call.isSuperCall()) {
                                    hasCallToSuper = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            if (!hasCallToSuper) {
                // invokes the super class constructor
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(superClass), "<init>", "()V", false);
            }
        }

        // handle body
        super.visitConstructorOrMethod(node, isConstructor);

        controller.getCompileStack().clear();
        if (node.isVoidMethod()) {
            mv.visitInsn(RETURN);
        } else {
            ClassNode type = node.getReturnType();
            if (ClassHelper.isPrimitiveType(type)) {
                mv.visitLdcInsn(0);
                controller.getOperandStack().push(ClassHelper.int_TYPE);
                controller.getOperandStack().doGroovyCast(type);
                BytecodeHelper.doReturn(mv, type);
                controller.getOperandStack().remove(1);
            } else {
                mv.visitInsn(ACONST_NULL);
                BytecodeHelper.doReturn(mv, type);
            }
        }
    }

    private void visitAnnotationDefaultExpression(final AnnotationVisitor av, final ClassNode type, final Expression exp) {
        if (exp instanceof ClosureExpression) {
            ClassNode closureClass = controller.getClosureWriter().getOrAddClosureClass((ClosureExpression) exp, ACC_PUBLIC);
            Type t = Type.getType(BytecodeHelper.getTypeDescription(closureClass));
            av.visit(null, t);
        } else if (type.isArray()) {
            AnnotationVisitor avl = av.visitArray(null);
            ClassNode componentType = type.getComponentType();
            if (exp instanceof ListExpression) {
                ListExpression list = (ListExpression) exp;
                for (Expression lExp : list.getExpressions()) {
                    visitAnnotationDefaultExpression(avl, componentType, lExp);
                }
            } else {
                visitAnnotationDefaultExpression(avl, componentType, exp);
            }
        } else if (ClassHelper.isPrimitiveType(type) || type.equals(ClassHelper.STRING_TYPE)) {
            ConstantExpression constExp = (ConstantExpression) exp;
            av.visit(null, constExp.getValue());
        } else if (ClassHelper.CLASS_Type.equals(type)) {
            ClassNode clazz = exp.getType();
            Type t = Type.getType(BytecodeHelper.getTypeDescription(clazz));
            av.visit(null, t);
        } else if (type.isDerivedFrom(ClassHelper.Enum_Type)) {
            PropertyExpression pExp = (PropertyExpression) exp;
            ClassExpression cExp = (ClassExpression) pExp.getObjectExpression();
            String desc = BytecodeHelper.getTypeDescription(cExp.getType());
            String name = pExp.getPropertyAsString();
            av.visitEnum(null, desc, name);
        } else if (type.implementsInterface(ClassHelper.Annotation_TYPE)) {
            AnnotationConstantExpression avExp = (AnnotationConstantExpression) exp;
            AnnotationNode value = (AnnotationNode) avExp.getValue();
            AnnotationVisitor avc = av.visitAnnotation(null, BytecodeHelper.getTypeDescription(avExp.getType()));
            visitAnnotationAttributes(value, avc);
        } else {
            throw new GroovyBugError("unexpected annotation type " + type.getName());
        }
        av.visitEnd();
    }

    private void visitAnnotationDefault(final MethodNode node, final MethodVisitor mv) {
        if (!node.hasAnnotationDefault()) return;
        Expression exp = ((ReturnStatement) node.getCode()).getExpression();
        AnnotationVisitor av = mv.visitAnnotationDefault();
        visitAnnotationDefaultExpression(av,node.getReturnType(),exp);
    }

    @Override
    public void visitConstructor(final ConstructorNode node) {
        controller.setConstructorNode(node);
        super.visitConstructor(node);
    }

    @Override
    public void visitMethod(final MethodNode node) {
        controller.setMethodNode(node);
        super.visitMethod(node);
    }

    @Override
    public void visitField(final FieldNode fieldNode) {
        onLineNumber(fieldNode, "visitField: " + fieldNode.getName());
        ClassNode t = fieldNode.getType();
        String signature = BytecodeHelper.getGenericsBounds(t);

        Expression initialValueExpression = fieldNode.getInitialValueExpression();
        ConstantExpression cexp = initialValueExpression instanceof ConstantExpression? (ConstantExpression) initialValueExpression :null;
        if (cexp!=null) {
            cexp = Verifier.transformToPrimitiveConstantIfPossible(cexp);
        }
        Object value = cexp != null && ClassHelper.isStaticConstantInitializerType(cexp.getType())
                && cexp.getType().equals(t) && fieldNode.isStatic() && fieldNode.isFinal()
                ? cexp.getValue() : null; // GROOVY-5150
        if (value != null) {
            // byte, char and short require an extra cast
            if (ClassHelper.byte_TYPE.equals(t) || ClassHelper.short_TYPE.equals(t)) {
                value = ((Number) value).intValue();
            } else if (ClassHelper.char_TYPE.equals(t)) {
                value = Integer.valueOf((Character)value);
            }
        }
        FieldVisitor fv = classVisitor.visitField(
                fieldNode.getModifiers(),
                fieldNode.getName(),
                BytecodeHelper.getTypeDescription(t),
                signature,
                value);
        visitAnnotations(fieldNode, fv);
        fv.visitEnd();
    }

    @Override
    public void visitProperty(final PropertyNode statement) {
        // the verifier created the field and the setter/getter methods, so here is
        // not really something to do
        onLineNumber(statement, "visitProperty:" + statement.getField().getName());
        controller.setMethodNode(null);
    }

    // GroovyCodeVisitor interface
    //-------------------------------------------------------------------------

    // Statements
    //-------------------------------------------------------------------------

    @Override
    protected void visitStatement(final Statement statement) {
        throw new GroovyBugError("visitStatement should not be visited here.");
    }

    @Override
    public void visitCatchStatement(final CatchStatement statement) {
        statement.getCode().visit(this);
    }

    @Override
    public void visitBlockStatement(final BlockStatement statement) {
        controller.getStatementWriter().writeBlockStatement(statement);
    }

    @Override
    public void visitForLoop(final ForStatement statement) {
        controller.getStatementWriter().writeForStatement(statement);
    }

    @Override
    public void visitWhileLoop(final WhileStatement statement) {
        controller.getStatementWriter().writeWhileLoop(statement);
    }

    @Override
    public void visitDoWhileLoop(final DoWhileStatement statement) {
        controller.getStatementWriter().writeDoWhileLoop(statement);
    }

    @Override
    public void visitIfElse(final IfStatement statement) {
        controller.getStatementWriter().writeIfElse(statement);
    }

    @Override
    public void visitAssertStatement(final AssertStatement statement) {
        controller.getStatementWriter().writeAssert(statement);
    }

    @Override
    public void visitTryCatchFinally(final TryCatchStatement statement) {
        controller.getStatementWriter().writeTryCatchFinally(statement);
    }

    @Override
    public void visitSwitch(final SwitchStatement statement) {
        controller.getStatementWriter().writeSwitch(statement);
    }

    @Override
    public void visitCaseStatement(final CaseStatement statement) {
    }

    @Override
    public void visitBreakStatement(final BreakStatement statement) {
        controller.getStatementWriter().writeBreak(statement);
    }

    @Override
    public void visitContinueStatement(final ContinueStatement statement) {
        controller.getStatementWriter().writeContinue(statement);
    }

    @Override
    public void visitSynchronizedStatement(final SynchronizedStatement statement) {
        controller.getStatementWriter().writeSynchronized(statement);
    }

    @Override
    public void visitThrowStatement(final ThrowStatement statement) {
        controller.getStatementWriter().writeThrow(statement);
    }

    @Override
    public void visitReturnStatement(final ReturnStatement statement) {
        controller.getStatementWriter().writeReturn(statement);
    }

    @Override
    public void visitExpressionStatement(final ExpressionStatement statement) {
        controller.getStatementWriter().writeExpressionStatement(statement);
    }

    // Expressions
    //-------------------------------------------------------------------------

    @Override
    public void visitTernaryExpression(final TernaryExpression expression) {
        onLineNumber(expression, "visitTernaryExpression");
        controller.getBinaryExpressionHelper().evaluateTernary(expression);
    }

    @Override
    public void visitDeclarationExpression(final DeclarationExpression expression) {
        onLineNumber(expression, "visitDeclarationExpression: \"" + expression.getText() + "\"");
        controller.getBinaryExpressionHelper().evaluateEqual(expression,true);
    }

    @Override
    public void visitBinaryExpression(final BinaryExpression expression) {
        onLineNumber(expression, "visitBinaryExpression: \"" + expression.getOperation().getText() + "\" ");
        controller.getBinaryExpressionHelper().eval(expression);
        controller.getAssertionWriter().record(expression.getOperation());
    }

    @Override
    public void visitPostfixExpression(final PostfixExpression expression) {
        controller.getBinaryExpressionHelper().evaluatePostfixMethod(expression);
        controller.getAssertionWriter().record(expression);
    }

    @Override
    public void visitPrefixExpression(final PrefixExpression expression) {
        controller.getBinaryExpressionHelper().evaluatePrefixMethod(expression);
        controller.getAssertionWriter().record(expression);
    }

    @Override
    public void visitClosureExpression(final ClosureExpression expression) {
        controller.getClosureWriter().writeClosure(expression);
    }

    @Override
    public void visitLambdaExpression(final LambdaExpression expression) {
        controller.getLambdaWriter().writeLambda(expression);
    }

    /**
     * Loads either this object or if we're inside a closure then load the top level owner
     */
    protected void loadThisOrOwner() {
        if (isInnerClass()) {
            visitFieldExpression(new FieldExpression(controller.getClassNode().getDeclaredField("owner")));
        } else {
            loadThis(null);
        }
    }

    /**
     * Generates byte code for constants.
     *
     * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#14152">Class field types</a>
     */
    @Override
    public void visitConstantExpression(final ConstantExpression expression) {
        final String constantName = expression.getConstantName();
        if (controller.isStaticConstructor() || constantName == null) {
            controller.getOperandStack().pushConstant(expression);
        } else {
            controller.getMethodVisitor().visitFieldInsn(GETSTATIC, controller.getInternalClassName(),constantName, BytecodeHelper.getTypeDescription(expression.getType()));
            controller.getOperandStack().push(expression.getType());
        }
    }

    @Override
    public void visitSpreadExpression(final SpreadExpression expression) {
        throw new GroovyBugError("SpreadExpression should not be visited here");
    }

    @Override
    public void visitSpreadMapExpression(final SpreadMapExpression expression) {
        Expression subExpression = expression.getExpression();
        // to not record the underlying MapExpression twice,
        // we disable the assertion tracker
        // see https://issues.apache.org/jira/browse/GROOVY-3421
        controller.getAssertionWriter().disableTracker();
        subExpression.visit(this);
        controller.getOperandStack().box();
        spreadMap.call(controller.getMethodVisitor());
        controller.getAssertionWriter().reenableTracker();
        controller.getOperandStack().replace(ClassHelper.OBJECT_TYPE);
    }

    @Override
    public void visitMethodPointerExpression(final MethodPointerExpression expression) {
        controller.getMethodPointerExpressionWriter().writeMethodPointerExpression(expression);
    }

    @Override
    public void visitMethodReferenceExpression(final MethodReferenceExpression expression) {
        controller.getMethodReferenceExpressionWriter().writeMethodReferenceExpression(expression);
    }

    @Override
    public void visitUnaryMinusExpression(final UnaryMinusExpression expression) {
        controller.getUnaryExpressionHelper().writeUnaryMinus(expression);
    }

    @Override
    public void visitUnaryPlusExpression(final UnaryPlusExpression expression) {
        controller.getUnaryExpressionHelper().writeUnaryPlus(expression);
    }

    @Override
    public void visitBitwiseNegationExpression(final BitwiseNegationExpression expression) {
        controller.getUnaryExpressionHelper().writeBitwiseNegate(expression);
    }

    @Override
    public void visitCastExpression(final CastExpression castExpression) {
        ClassNode type = castExpression.getType();
        Expression subExpression = castExpression.getExpression();
        subExpression.visit(this);
        if (ClassHelper.OBJECT_TYPE.equals(type)) return;
        if (castExpression.isCoerce()) {
            controller.getOperandStack().doAsType(type);
        } else {
            if (isNullConstant(subExpression) && !ClassHelper.isPrimitiveType(type)) {
                controller.getOperandStack().replace(type);
            } else {
                ClassNode subExprType = controller.getTypeChooser().resolveType(subExpression, controller.getClassNode());
                if (castExpression.isStrict() ||
                        (!ClassHelper.isPrimitiveType(type) && WideningCategories.implementsInterfaceOrSubclassOf(subExprType, type))) {
                    BytecodeHelper.doCast(controller.getMethodVisitor(), type);
                    controller.getOperandStack().replace(type);
                } else {
                    controller.getOperandStack().doGroovyCast(type);
                }
            }
        }
    }

    @Override
    public void visitNotExpression(final NotExpression expression) {
        controller.getUnaryExpressionHelper().writeNotExpression(expression);
    }

    @Override
    public void visitBooleanExpression(final BooleanExpression expression) {
        controller.getCompileStack().pushBooleanExpression();
        int mark = controller.getOperandStack().getStackLength();
        Expression inner = expression.getExpression();
        inner.visit(this);
        controller.getOperandStack().castToBool(mark, true);
        controller.getCompileStack().pop();
    }

    @Override
    public void visitMethodCallExpression(final MethodCallExpression call) {
        onLineNumber(call, "visitMethodCallExpression: \"" + call.getMethod() + "\":");
        controller.getInvocationWriter().writeInvokeMethod(call);
        controller.getAssertionWriter().record(call.getMethod());
    }

    @Override
    public void visitStaticMethodCallExpression(final StaticMethodCallExpression call) {
        onLineNumber(call, "visitStaticMethodCallExpression: \"" + call.getMethod() + "\":");
        controller.getInvocationWriter().writeInvokeStaticMethod(call);
        controller.getAssertionWriter().record(call);
    }

    @Override
    public void visitConstructorCallExpression(final ConstructorCallExpression call) {
        onLineNumber(call, "visitConstructorCallExpression: \"" + call.getType().getName() + "\":");

        if (call.isSpecialCall()) {
            controller.getInvocationWriter().writeSpecialConstructorCall(call);
            return;
        }
        controller.getInvocationWriter().writeInvokeConstructor(call);
        controller.getAssertionWriter().record(call);
    }

    private static String makeFieldClassName(final ClassNode type) {
        String internalName = BytecodeHelper.getClassInternalName(type);
        StringBuilder ret = new StringBuilder(internalName.length());
        for (int i = 0, n = internalName.length(); i < n; i += 1) {
            char c = internalName.charAt(i);
            if (c == '/') {
                ret.append('$');
            } else if (c == ';') {
                //append nothing -> delete ';'
            } else {
                ret.append(c);
            }
        }
        return ret.toString();
    }

    private static String getStaticFieldName(final ClassNode type) {
        ClassNode componentType = type;
        StringBuilder prefix = new StringBuilder();
        for (; componentType.isArray(); componentType = componentType.getComponentType()) {
            prefix.append("$");
        }
        if (prefix.length() != 0) prefix.insert(0, "array");
        String name = prefix + "$class$" + makeFieldClassName(componentType);
        return name;
    }

    private static boolean isValidFieldNodeForByteCodeAccess(final FieldNode fn, final ClassNode accessingNode) {
        if (fn == null) return false;
        ClassNode declaringClass = fn.getDeclaringClass();
        // same class is always allowed access
        if (fn.isPublic() || declaringClass.equals(accessingNode)) return true;
        boolean samePackages = Objects.equals(declaringClass.getPackageName(), accessingNode.getPackageName());
        // protected means same class or same package, or subclass
        if (fn.isProtected() && (samePackages || accessingNode.isDerivedFrom(declaringClass))) {
            return true;
        }
        if (!fn.isPrivate()) {
            // package private is the only modifier left. It means  same package is allowed, subclass not, same class is
            return samePackages;
        }
        return false;
    }

    public static FieldNode getDeclaredFieldOfCurrentClassOrAccessibleFieldOfSuper(final ClassNode accessingNode, final ClassNode current, final String name, final boolean skipCurrent) {
        if (!skipCurrent) {
            FieldNode currentClassField = current.getDeclaredField(name);
            if (isValidFieldNodeForByteCodeAccess(currentClassField, accessingNode)) return currentClassField;
        }
        for (ClassNode node = current.getSuperClass(); node != null; node = node.getSuperClass()) {
            FieldNode fn = node.getDeclaredField(name);
            if (isValidFieldNodeForByteCodeAccess(fn, accessingNode)) return fn;
        }
        return null;
    }

    private void visitAttributeOrProperty(final PropertyExpression expression, final MethodCallerMultiAdapter adapter) {
        ClassNode classNode = controller.getClassNode();
        String propertyName = expression.getPropertyAsString();
        Expression objectExpression = expression.getObjectExpression();

        if (objectExpression instanceof ClassExpression && "this".equals(propertyName)) {
            // we have something like A.B.this, and need to make it
            // into this.this$0.this$0, where this.this$0 returns
            // A.B and this.this$0.this$0 return A.
            ClassNode type = objectExpression.getType();
            if (controller.getCompileStack().isInSpecialConstructorCall() && type.equals(classNode.getOuterClass())) {
                // Outer.this in a special constructor call
                ConstructorNode ctor = controller.getConstructorNode();
                Expression receiver = !classNode.isStaticClass() ? new VariableExpression(ctor.getParameters()[0]) : new ClassExpression(type);
                receiver.setSourcePosition(expression);
                receiver.visit(this);
                return;
            }

            MethodVisitor mv = controller.getMethodVisitor();
            mv.visitVarInsn(ALOAD, 0);
            ClassNode iterType = classNode;
            while (!iterType.equals(type)) {
                String ownerName = BytecodeHelper.getClassInternalName(iterType);
                if (iterType.getOuterClass() == null) break;
                FieldNode thisField = iterType.getField("this$0");
                iterType = iterType.getOuterClass();
                if (thisField == null) {
                    // closure within inner class
                    while (ClassHelper.isGeneratedFunction(iterType)) {
                        // GROOVY-8881: cater for closures within closures - getThisObject is already outer class of all closures
                        iterType = iterType.getOuterClass();
                    }
                    mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ClassHelper.CLOSURE_TYPE), "getThisObject", "()Ljava/lang/Object;", false);
                    mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(iterType));
                } else {
                    ClassNode thisFieldType = thisField.getType();
                    if (ClassHelper.CLOSURE_TYPE.equals(thisFieldType)) {
                        mv.visitFieldInsn(GETFIELD, ownerName, "this$0", BytecodeHelper.getTypeDescription(ClassHelper.CLOSURE_TYPE));
                        mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ClassHelper.CLOSURE_TYPE), "getThisObject", "()Ljava/lang/Object;", false);
                        mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(iterType));
                    } else {
                        String typeName = BytecodeHelper.getTypeDescription(iterType);
                        mv.visitFieldInsn(GETFIELD, ownerName, "this$0", typeName);
                    }
                }
            }
            controller.getOperandStack().push(type);
            return;
        }

        if (propertyName != null) {
            // TODO: spread safe should be handled inside
            if (adapter == getProperty && !expression.isSpreadSafe()) {
                controller.getCallSiteWriter().makeGetPropertySite(objectExpression, propertyName, expression.isSafe(), expression.isImplicitThis());
            } else if (adapter == getGroovyObjectProperty && !expression.isSpreadSafe()) {
                controller.getCallSiteWriter().makeGroovyObjectGetPropertySite(objectExpression, propertyName, expression.isSafe(), expression.isImplicitThis());
            } else {
                controller.getCallSiteWriter().fallbackAttributeOrPropertySite(expression, objectExpression, propertyName, adapter);
            }
        } else {
            controller.getCallSiteWriter().fallbackAttributeOrPropertySite(expression, objectExpression, null, adapter);
        }
    }

    private void setPropertyOfSuperClass(final ClassNode classNode, final PropertyExpression expression, final MethodVisitor mv) {
        String fieldName = expression.getPropertyAsString();
        FieldNode fieldNode = classNode.getSuperClass().getField(fieldName);

        if (null == fieldNode) {
            throw new RuntimeParserException("Failed to find field[" + fieldName + "] of " + classNode.getName() + "'s super class", expression);
        }

        if (fieldNode.isFinal()) {
            throw new RuntimeParserException("Cannot modify final field[" + fieldName + "] of " + classNode.getName() + "'s super class", expression);
        }

        MethodNode setter = findSetterOfSuperClass(classNode, fieldNode);
        MethodNode getter = findGetterOfSuperClass(classNode, fieldNode);

        if (fieldNode.isPrivate() && !getterAndSetterExists(setter, getter)) {
            throw new RuntimeParserException("Cannot access private field[" + fieldName + "] of " + classNode.getName() + "'s super class", expression);
        }

        OperandStack operandStack = controller.getOperandStack();
        operandStack.doAsType(fieldNode.getType());

        mv.visitVarInsn(ALOAD, 0);
        operandStack.push(classNode);

        operandStack.swap();

        String owner = BytecodeHelper.getClassInternalName(classNode.getSuperClass().getName());
        String desc = BytecodeHelper.getTypeDescription(fieldNode.getType());
        if (fieldNode.isPublic() || fieldNode.isProtected()) {
            mv.visitFieldInsn(PUTFIELD, owner, fieldName, desc);
        } else {
            mv.visitMethodInsn(INVOKESPECIAL, owner, setter.getName(), BytecodeHelper.getMethodDescriptor(setter), false);
        }
    }

    private static boolean getterAndSetterExists(final MethodNode setter, final MethodNode getter) {
        return setter != null && getter != null && setter.getDeclaringClass().equals(getter.getDeclaringClass());
    }

    private static MethodNode findSetterOfSuperClass(final ClassNode classNode, final FieldNode fieldNode) {
        String setterMethodName = "set" + capitalize(fieldNode.getName());
        return classNode.getSuperClass().getSetterMethod(setterMethodName);
    }

    private static MethodNode findGetterOfSuperClass(final ClassNode classNode, final FieldNode fieldNode) {
        String getterMethodName = "get" + capitalize(fieldNode.getName());
        return classNode.getSuperClass().getGetterMethod(getterMethodName);
    }

    private boolean isGroovyObject(final Expression objectExpression) {
        if (isThisExpression(objectExpression)) return true;
        if (objectExpression instanceof ClassExpression) return false;

        ClassNode objectExpressionType = controller.getTypeChooser().resolveType(objectExpression, controller.getClassNode());
        if (objectExpressionType.equals(ClassHelper.OBJECT_TYPE)) objectExpressionType = objectExpression.getType();
        return objectExpressionType.isDerivedFromGroovyObject();
    }

    @Override
    public void visitPropertyExpression(final PropertyExpression expression) {
        Expression objectExpression = expression.getObjectExpression();
        OperandStack operandStack = controller.getOperandStack();
        int mark = operandStack.getStackLength() - 1;
        boolean visited = false;

        if (isThisOrSuper(objectExpression)) {
            String name = expression.getPropertyAsString();
            if (name != null) {
                FieldNode field = null;
                boolean privateSuperField = false;
                ClassNode classNode = controller.getClassNode();

                if (isSuperExpression(objectExpression)) {
                    field = classNode.getSuperClass().getDeclaredField(name);
                    privateSuperField = (field != null && field.isPrivate());
                } else if (expression.isImplicitThis() || !controller.isInGeneratedFunction()) {
                    field = classNode.getDeclaredField(name);

                    ClassNode outer = classNode.getOuterClass();
                    if (field == null && outer != null) {
                        do {
                            FieldNode outerClassField = outer.getDeclaredField(name);
                            if (outerClassField != null && outerClassField.isStatic() && outerClassField.isFinal()) {
                                if (outerClassField.isPrivate() && classNode.getOuterClass() != outer) {
                                    throw new GroovyBugError("Trying to access private field [" + outerClassField.getDeclaringClass() + "#" + outerClassField.getName() + "] from inner class");
                                }
                                PropertyExpression staticOuterField = new PropertyExpression(new ClassExpression(outer), expression.getProperty());
                                staticOuterField.getObjectExpression().setSourcePosition(objectExpression);
                                staticOuterField.visit(this);
                                return;
                            }
                            outer = outer.getSuperClass();
                        } while (outer != null);
                    }
                }

                if (field != null && !privateSuperField) { // GROOVY-4497: don't visit super field if it is private
                    visitFieldExpression(new FieldExpression(field));
                    visited = true;
                } else if (isSuperExpression(objectExpression)) {
                    if (controller.getCompileStack().isLHS()) {
                        setPropertyOfSuperClass(classNode, expression, controller.getMethodVisitor());
                    } else {
                        visitMethodCallExpression(new MethodCallExpression(objectExpression, "get" + capitalize(name), MethodCallExpression.NO_ARGUMENTS));
                    }
                    visited = true;
                }
            }
        }

        if (!visited) {
            boolean useMetaObjectProtocol = isGroovyObject(objectExpression)
                    && (!isThisOrSuper(objectExpression) || !controller.isStaticContext() || controller.isInGeneratedFunction());

            MethodCallerMultiAdapter adapter;
            if (controller.getCompileStack().isLHS()) {
                adapter = useMetaObjectProtocol ? setGroovyObjectProperty : setProperty;
            } else {
                adapter = useMetaObjectProtocol ? getGroovyObjectProperty : getProperty;
            }
            visitAttributeOrProperty(expression, adapter);
        }

        if (controller.getCompileStack().isLHS()) {
            operandStack.remove(operandStack.getStackLength() - mark);
        } else {
            controller.getAssertionWriter().record(expression.getProperty());
        }
    }

    @Override
    public void visitAttributeExpression(final AttributeExpression expression) {
        Expression objectExpression = expression.getObjectExpression();
        OperandStack operandStack = controller.getOperandStack();
        int mark = operandStack.getStackLength() - 1;
        boolean visited = false;

        if (isThisOrSuper(objectExpression)) {
            String name = expression.getPropertyAsString();
            if (name != null) {
                ClassNode classNode = controller.getClassNode();
                FieldNode field = getDeclaredFieldOfCurrentClassOrAccessibleFieldOfSuper(classNode, classNode, name, isSuperExpression(objectExpression));
                if (field != null) {
                    visitFieldExpression(new FieldExpression(field));
                    visited = true;
                } else if (isSuperExpression(objectExpression)) {
                    if (controller.getCompileStack().isLHS()) {
                        setPropertyOfSuperClass(classNode, expression, controller.getMethodVisitor());
                    } else {
                        visitMethodCallExpression(new MethodCallExpression(objectExpression, "get" + capitalize(name), MethodCallExpression.NO_ARGUMENTS));
                    }
                    visited = true;
                }
            }
        }

        if (!visited) {
            MethodCallerMultiAdapter adapter;
            if (controller.getCompileStack().isLHS()) {
                adapter = isGroovyObject(objectExpression) ? setGroovyObjectField : setField;
            } else {
                adapter = isGroovyObject(objectExpression) ? getGroovyObjectField : getField;
            }
            visitAttributeOrProperty(expression, adapter);
        }

        if (controller.getCompileStack().isLHS()) {
            operandStack.remove(operandStack.getStackLength() - mark);
        } else {
            controller.getAssertionWriter().record(expression.getProperty());
        }
    }

    @Override
    public void visitFieldExpression(final FieldExpression expression) {
        FieldNode field = expression.getField();
        if (field.isStatic()) {
            if (controller.getCompileStack().isLHS()) {
                storeStaticField(expression);
            } else {
                loadStaticField(expression);
            }
        } else {
            if (controller.getCompileStack().isLHS()) {
                storeThisInstanceField(expression);
            } else {
                loadInstanceField(expression);
            }
        }
    }

    public void loadStaticField(final FieldExpression fldExp) {
        MethodVisitor mv = controller.getMethodVisitor();
        FieldNode field = fldExp.getField();
        boolean holder = field.isHolder() && !controller.isInGeneratedFunctionConstructor();
        ClassNode type = field.getType();

        String ownerName = (field.getOwner().equals(controller.getClassNode()))
                ? controller.getInternalClassName()
                : BytecodeHelper.getClassInternalName(field.getOwner());
        if (holder) {
            mv.visitFieldInsn(GETSTATIC, ownerName, fldExp.getFieldName(), BytecodeHelper.getTypeDescription(type));
            mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "get", "()Ljava/lang/Object;", false);
            controller.getOperandStack().push(ClassHelper.OBJECT_TYPE);
        } else {
            mv.visitFieldInsn(GETSTATIC, ownerName, fldExp.getFieldName(), BytecodeHelper.getTypeDescription(type));
            controller.getOperandStack().push(field.getType());
        }
    }

    /**
     * RHS instance field. should move most of the code in the BytecodeHelper
     */
    public void loadInstanceField(final FieldExpression fldExp) {
        MethodVisitor mv = controller.getMethodVisitor();
        FieldNode field = fldExp.getField();
        boolean holder = field.isHolder() && !controller.isInGeneratedFunctionConstructor();
        ClassNode type = field.getType();
        String ownerName = (field.getOwner().equals(controller.getClassNode()))
                ? controller.getInternalClassName()
                : BytecodeHelper.getClassInternalName(field.getOwner());

        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, ownerName, fldExp.getFieldName(), BytecodeHelper.getTypeDescription(type));

        if (holder) {
            mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "get", "()Ljava/lang/Object;", false);
            controller.getOperandStack().push(ClassHelper.OBJECT_TYPE);
        } else {
            controller.getOperandStack().push(field.getType());
        }
    }

    private void storeThisInstanceField(final FieldExpression expression) {
        MethodVisitor mv = controller.getMethodVisitor();
        FieldNode field = expression.getField();

        boolean setReferenceFromReference = field.isHolder() && expression.isUseReferenceDirectly();
        String ownerName = (field.getOwner().equals(controller.getClassNode()))
                ? controller.getInternalClassName() : BytecodeHelper.getClassInternalName(field.getOwner());
        OperandStack operandStack = controller.getOperandStack();

        if (setReferenceFromReference) {
            // rhs is ready to use reference, just put it in the field
            mv.visitVarInsn(ALOAD, 0);
            operandStack.push(controller.getClassNode());
            operandStack.swap();
            mv.visitFieldInsn(PUTFIELD, ownerName, field.getName(), BytecodeHelper.getTypeDescription(field.getType()));
        } else if (field.isHolder()) {
            // rhs is normal value, set the value in the Reference
            operandStack.doGroovyCast(field.getOriginType());
            operandStack.box();
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, ownerName, expression.getFieldName(), BytecodeHelper.getTypeDescription(field.getType()));
            mv.visitInsn(SWAP);
            mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "set", "(Ljava/lang/Object;)V", false);
        } else {
            // rhs is normal value, set normal value
            operandStack.doGroovyCast(field.getOriginType());
            mv.visitVarInsn(ALOAD, 0);
            operandStack.push(controller.getClassNode());
            operandStack.swap();
            mv.visitFieldInsn(PUTFIELD, ownerName, field.getName(), BytecodeHelper.getTypeDescription(field.getType()));
        }
    }

    private void storeStaticField(final FieldExpression expression) {
        MethodVisitor mv = controller.getMethodVisitor();
        FieldNode field = expression.getField();

        boolean holder = field.isHolder() && !controller.isInGeneratedFunctionConstructor();
        controller.getOperandStack().doGroovyCast(field);

        String ownerName = (field.getOwner().equals(controller.getClassNode()))
                ? controller.getInternalClassName() : BytecodeHelper.getClassInternalName(field.getOwner());
        if (holder) {
            controller.getOperandStack().box();
            mv.visitFieldInsn(GETSTATIC, ownerName, expression.getFieldName(), BytecodeHelper.getTypeDescription(field.getType()));
            mv.visitInsn(SWAP);
            mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "set", "(Ljava/lang/Object;)V", false);
        } else {
            mv.visitFieldInsn(PUTSTATIC, ownerName, expression.getFieldName(), BytecodeHelper.getTypeDescription(field.getType()));
        }
        controller.getOperandStack().remove(1);
    }

    @Override
    public void visitVariableExpression(final VariableExpression expression) {
        String variableName = expression.getName();

        //-----------------------------------------------------------------------
        // SPECIAL CASES

        // "this" for static methods is the Class instance
        ClassNode classNode = controller.getClassNode();

        if (expression.isThisExpression()) {
            if (controller.isStaticMethod() || (!controller.getCompileStack().isImplicitThis() && controller.isStaticContext())) {
                if (controller.isInGeneratedFunction()) classNode = controller.getOutermostClass();
                visitClassExpression(new ClassExpression(classNode));
            } else {
                loadThis(expression);
            }
            return;
        }

        // "super" also requires special handling
        if (expression.isSuperExpression()) {
            if (controller.isStaticMethod()) {
                visitClassExpression(new ClassExpression(classNode.getSuperClass()));
            } else {
                loadThis(expression);
            }
            return;
        }

        BytecodeVariable variable = controller.getCompileStack().getVariable(variableName, false);
        if (variable == null) {
            processClassVariable(expression);
        } else {
            controller.getOperandStack().loadOrStoreVariable(variable, expression.isUseReferenceDirectly());
        }
        if (!controller.getCompileStack().isLHS()) {
            controller.getAssertionWriter().record(expression);
        }
    }

    private void loadThis(final VariableExpression thisExpression) {
        MethodVisitor mv = controller.getMethodVisitor();
        mv.visitVarInsn(ALOAD, 0);
        if (controller.isInGeneratedFunction() && !controller.getCompileStack().isImplicitThis()) {
            mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Closure", "getThisObject", "()Ljava/lang/Object;", false);
            ClassNode expectedType = thisExpression!=null?controller.getTypeChooser().resolveType(thisExpression, controller.getOutermostClass()):null;
            if (!ClassHelper.OBJECT_TYPE.equals(expectedType) && !ClassHelper.isPrimitiveType(expectedType)) {
                BytecodeHelper.doCast(mv, expectedType);
                controller.getOperandStack().push(expectedType);
            } else {
                controller.getOperandStack().push(ClassHelper.OBJECT_TYPE);
            }
        } else {
            controller.getOperandStack().push(controller.getClassNode());
        }
    }

    private void processClassVariable(final VariableExpression expression) {
        if (passingParams && controller.isInScriptBody()) {
            //TODO: check if this part is actually used
            MethodVisitor mv = controller.getMethodVisitor();
            // let's create a ScriptReference to pass into the closure
            mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/ScriptReference");
            mv.visitInsn(DUP);

            loadThisOrOwner();
            mv.visitLdcInsn(expression.getName());

            mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/ScriptReference", "<init>", "(Lgroovy/lang/Script;Ljava/lang/String;)V", false);
        } else {
            PropertyExpression pexp = new PropertyExpression(new VariableExpression("this"), expression.getName());
            pexp.getObjectExpression().setSourcePosition(expression);
            pexp.getProperty().setSourcePosition(expression);
            pexp.setImplicitThis(true);
            visitPropertyExpression(pexp);
        }
    }

    protected void createInterfaceSyntheticStaticFields() {
        ClassNode icl =  controller.getInterfaceClassLoadingClass();

        if (referencedClasses.isEmpty()) {
            Iterator<InnerClassNode> it = icl.getOuterClass().getInnerClasses();
            while(it.hasNext()) {
                InnerClassNode inner = it.next();
                if (inner==icl) {
                    it.remove();
                    return;
                }
            }
            return;
        }

        addInnerClass(icl);
        for (Map.Entry<String, ClassNode> entry : referencedClasses.entrySet()) {
            // generate a field node
            String staticFieldName = entry.getKey();
            ClassNode cn = entry.getValue();
            icl.addField(staticFieldName, ACC_STATIC + ACC_SYNTHETIC, ClassHelper.CLASS_Type.getPlainNodeReference(), new ClassExpression(cn));
        }
    }

    protected void createSyntheticStaticFields() {
        if (referencedClasses.isEmpty()) {
            return;
        }
        MethodVisitor mv;
        for (Map.Entry<String, ClassNode> entry : referencedClasses.entrySet()) {
            String staticFieldName = entry.getKey();
            ClassNode cn = entry.getValue();
            // generate a field node
            FieldNode fn = controller.getClassNode().getDeclaredField(staticFieldName);
            if (fn != null) {
                boolean type = fn.getType().equals(ClassHelper.CLASS_Type);
                boolean modifiers = fn.getModifiers() == ACC_STATIC + ACC_SYNTHETIC;
                if (!type || !modifiers) {
                    String text = "";
                    if (!type) text = " with wrong type: " + fn.getType() + " (java.lang.Class needed)";
                    if (!modifiers)
                        text = " with wrong modifiers: " + fn.getModifiers() + " (" + (ACC_STATIC + ACC_SYNTHETIC) + " needed)";
                    throwException("tried to set a static synthetic field " + staticFieldName + " in " + controller.getClassNode().getName() +
                            " for class resolving, but found already a node of that name " + text);
                }
            } else {
                classVisitor.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, staticFieldName, "Ljava/lang/Class;", null, null);
            }

            mv = classVisitor.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$get$" + staticFieldName,"()Ljava/lang/Class;",null, null);
            mv.visitCode();
            mv.visitFieldInsn(GETSTATIC,controller.getInternalClassName(),staticFieldName,"Ljava/lang/Class;");
            mv.visitInsn(DUP);
            Label l0 = new Label();
            mv.visitJumpInsn(IFNONNULL,l0);
            mv.visitInsn(POP);
            mv.visitLdcInsn(BytecodeHelper.getClassLoadingTypeDescription(cn));
            mv.visitMethodInsn(INVOKESTATIC, controller.getInternalClassName(), "class$", "(Ljava/lang/String;)Ljava/lang/Class;", false);
            mv.visitInsn(DUP);
            mv.visitFieldInsn(PUTSTATIC,controller.getInternalClassName(),staticFieldName,"Ljava/lang/Class;");
            mv.visitLabel(l0);
            mv.visitInsn(ARETURN);
            mv.visitMaxs(0,0);
            mv.visitEnd();
        }

        mv = classVisitor.visitMethod(ACC_STATIC + ACC_SYNTHETIC, "class$", "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitInsn(ARETURN);
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitVarInsn(ASTORE, 1);
        mv.visitTypeInsn(NEW, "java/lang/NoClassDefFoundError");
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ClassNotFoundException", "getMessage", "()Ljava/lang/String;", false);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/NoClassDefFoundError", "<init>", "(Ljava/lang/String;)V", false);
        mv.visitInsn(ATHROW);
        mv.visitTryCatchBlock(l0, l2, l2, "java/lang/ClassNotFoundException"); // br using l2 as the 2nd param seems create the right table entry
        mv.visitMaxs(3, 2);
    }

    @Override
    public void visitClassExpression(final ClassExpression expression) {
        ClassNode type = expression.getType();
        MethodVisitor mv = controller.getMethodVisitor();
        if (BytecodeHelper.isClassLiteralPossible(type) || BytecodeHelper.isSameCompilationUnit(controller.getClassNode(), type)) {
            if (controller.getClassNode().isInterface()) {
                InterfaceHelperClassNode interfaceClassLoadingClass = controller.getInterfaceClassLoadingClass();
                if (BytecodeHelper.isClassLiteralPossible(interfaceClassLoadingClass)) {
                    BytecodeHelper.visitClassLiteral(mv, interfaceClassLoadingClass);
                    controller.getOperandStack().push(ClassHelper.CLASS_Type);
                    return;
                }
            } else {
                BytecodeHelper.visitClassLiteral(mv, type);
                controller.getOperandStack().push(ClassHelper.CLASS_Type);
                return;
            }
        }
        String staticFieldName = getStaticFieldName(type);
        referencedClasses.put(staticFieldName, type);

        String internalClassName = controller.getInternalClassName();
        if (controller.getClassNode().isInterface()) {
            internalClassName = BytecodeHelper.getClassInternalName(controller.getInterfaceClassLoadingClass());
            mv.visitFieldInsn(GETSTATIC, internalClassName, staticFieldName, "Ljava/lang/Class;");
        } else {
            mv.visitMethodInsn(INVOKESTATIC, internalClassName, "$get$" + staticFieldName, "()Ljava/lang/Class;", false);
        }
        controller.getOperandStack().push(ClassHelper.CLASS_Type);
    }

    @Override
    public void visitRangeExpression(final RangeExpression expression) {
        OperandStack operandStack = controller.getOperandStack();
        expression.getFrom().visit(this);
        operandStack.box();
        expression.getTo().visit(this);
        operandStack.box();
        operandStack.pushBool(expression.isInclusive());

        createRangeMethod.call(controller.getMethodVisitor());
        operandStack.replace(ClassHelper.RANGE_TYPE, 3);
    }

    @Override
    public void visitMapEntryExpression(final MapEntryExpression expression) {
        throw new GroovyBugError("MapEntryExpression should not be visited here");
    }

    @Override
    public void visitMapExpression(final MapExpression expression) {
        MethodVisitor mv = controller.getMethodVisitor();

        List<MapEntryExpression> entries = expression.getMapEntryExpressions();
        int size = entries.size();
        BytecodeHelper.pushConstant(mv, size * 2);

        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");

        int i = 0;
        for (Object object : entries) {
            MapEntryExpression entry = (MapEntryExpression) object;

            mv.visitInsn(DUP);
            BytecodeHelper.pushConstant(mv, i++);
            entry.getKeyExpression().visit(this);
            controller.getOperandStack().box();
            mv.visitInsn(AASTORE);

            mv.visitInsn(DUP);
            BytecodeHelper.pushConstant(mv, i++);
            entry.getValueExpression().visit(this);
            controller.getOperandStack().box();
            mv.visitInsn(AASTORE);

            controller.getOperandStack().remove(2);
        }
        createMapMethod.call(mv);
        controller.getOperandStack().push(ClassHelper.MAP_TYPE);
    }

    @Override
    public void visitArgumentlistExpression(final ArgumentListExpression ale) {
        if (containsSpreadExpression(ale)) {
            despreadList(ale.getExpressions(), true);
        } else {
            visitTupleExpression(ale, true);
        }
    }

    public void despreadList(final List<Expression> expressions, final boolean wrap) {
        List<Expression> spreadIndexes = new ArrayList<>();
        List<Expression> spreadExpressions = new ArrayList<>();
        List<Expression> normalArguments = new ArrayList<>();
        for (int i = 0, n = expressions.size(); i < n; i += 1) {
            Expression expr = expressions.get(i);
            if (!(expr instanceof SpreadExpression)) {
                normalArguments.add(expr);
            } else {
                spreadIndexes.add(new ConstantExpression(i - spreadExpressions.size(), true));
                spreadExpressions.add(((SpreadExpression) expr).getExpression());
            }
        }

        // load normal arguments as array
        visitTupleExpression(new ArgumentListExpression(normalArguments), wrap);
        // load spread expressions as array
        new TupleExpression(spreadExpressions).visit(this);
        // load insertion index
        new ArrayExpression(ClassHelper.int_TYPE, spreadIndexes, null).visit(this);

        controller.getOperandStack().remove(1);
        despreadList.call(controller.getMethodVisitor());
    }

    @Override
    public void visitTupleExpression(final TupleExpression expression) {
        visitTupleExpression(expression, false);
    }

    void visitTupleExpression(final TupleExpression expression, final boolean useWrapper) {
        MethodVisitor mv = controller.getMethodVisitor();
        int size = expression.getExpressions().size();

        BytecodeHelper.pushConstant(mv, size);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");

        for (int i = 0; i < size; i += 1) {
            mv.visitInsn(DUP);
            BytecodeHelper.pushConstant(mv, i);
            Expression argument = expression.getExpression(i);
            argument.visit(this);
            controller.getOperandStack().box();
            if (useWrapper && argument instanceof CastExpression) loadWrapper(argument);

            mv.visitInsn(AASTORE);
            controller.getOperandStack().remove(1);
        }
    }

    public void loadWrapper(final Expression argument) {
        MethodVisitor mv = controller.getMethodVisitor();
        ClassNode goalClass = argument.getType();
        visitClassExpression(new ClassExpression(goalClass));
        if (goalClass.isDerivedFromGroovyObject()) {
            createGroovyObjectWrapperMethod.call(mv);
        } else {
            createPojoWrapperMethod.call(mv);
        }
        controller.getOperandStack().remove(1);
    }

    @Override
    public void visitArrayExpression(final ArrayExpression expression) {
        MethodVisitor mv = controller.getMethodVisitor();
        ClassNode elementType = expression.getElementType();
        String arrayTypeName = BytecodeHelper.getClassInternalName(elementType);
        List<Expression> sizeExpression = expression.getSizeExpression();

        int size = 0;
        int dimensions = 0;
        if (sizeExpression != null) {
            for (Expression element : sizeExpression) {
                if (element == ConstantExpression.EMPTY_EXPRESSION) break;
                dimensions += 1;
                // let's convert to an int
                element.visit(this);
                controller.getOperandStack().doGroovyCast(ClassHelper.int_TYPE);
            }
            controller.getOperandStack().remove(dimensions);
        } else {
            size = expression.getExpressions().size();
            BytecodeHelper.pushConstant(mv, size);
        }

        int storeIns = AASTORE;
        if (sizeExpression != null) {
            arrayTypeName = BytecodeHelper.getTypeDescription(expression.getType());
            mv.visitMultiANewArrayInsn(arrayTypeName, dimensions);
        } else if (ClassHelper.isPrimitiveType(elementType)) {
            int primType = 0;
            if (elementType == ClassHelper.boolean_TYPE) {
                primType = T_BOOLEAN;
                storeIns = BASTORE;
            } else if (elementType == ClassHelper.char_TYPE) {
                primType = T_CHAR;
                storeIns = CASTORE;
            } else if (elementType == ClassHelper.float_TYPE) {
                primType = T_FLOAT;
                storeIns = FASTORE;
            } else if (elementType == ClassHelper.double_TYPE) {
                primType = T_DOUBLE;
                storeIns = DASTORE;
            } else if (elementType == ClassHelper.byte_TYPE) {
                primType = T_BYTE;
                storeIns = BASTORE;
            } else if (elementType == ClassHelper.short_TYPE) {
                primType = T_SHORT;
                storeIns = SASTORE;
            } else if (elementType == ClassHelper.int_TYPE) {
                primType = T_INT;
                storeIns = IASTORE;
            } else if (elementType == ClassHelper.long_TYPE) {
                primType = T_LONG;
                storeIns = LASTORE;
            }
            mv.visitIntInsn(NEWARRAY, primType);
        } else {
            mv.visitTypeInsn(ANEWARRAY, arrayTypeName);
        }

        for (int i = 0; i < size; i += 1) {
            mv.visitInsn(DUP);
            BytecodeHelper.pushConstant(mv, i);
            Expression elementExpression = expression.getExpression(i);
            if (elementExpression == null) {
                ConstantExpression.NULL.visit(this);
            } else {
                elementExpression.visit(this);
                controller.getOperandStack().doGroovyCast(elementType);
            }
            mv.visitInsn(storeIns);
            controller.getOperandStack().remove(1);
        }

        controller.getOperandStack().push(expression.getType());
    }

    @Override
    public void visitClosureListExpression(final ClosureListExpression expression) {
        MethodVisitor mv = controller.getMethodVisitor();
        controller.getCompileStack().pushVariableScope(expression.getVariableScope());

        List<Expression> expressions = expression.getExpressions();
        final int size = expressions.size();
        // init declarations
        for (int i = 0; i < size; i += 1) {
            Expression expr = expressions.get(i);
            if (expr instanceof DeclarationExpression) {
                DeclarationExpression de = (DeclarationExpression) expr;
                BinaryExpression be = new BinaryExpression(
                        de.getLeftExpression(),
                        de.getOperation(),
                        de.getRightExpression());
                expressions.set(i, be);
                de.setRightExpression(ConstantExpression.NULL);
                visitDeclarationExpression(de);
            }
        }

        List<Object> instructions = new LinkedList<>();
        BytecodeSequence seq = new BytecodeSequence(instructions);
        BlockStatement bs = new BlockStatement();
        bs.addStatement(seq);
        Parameter closureIndex = new Parameter(ClassHelper.int_TYPE, "__closureIndex");
        ClosureExpression ce = new ClosureExpression(new Parameter[]{closureIndex}, bs);
        ce.setVariableScope(expression.getVariableScope());

        // to keep stack height put a null on stack
        instructions.add(ConstantExpression.NULL);

        // init table
        final Label dflt = new Label();
        final Label tableEnd = new Label();
        final Label[] labels = new Label[size];
        instructions.add(new BytecodeInstruction() {
            public void visit(MethodVisitor mv) {
                mv.visitVarInsn(ILOAD, 1);
                mv.visitTableSwitchInsn(0, size - 1, dflt, labels);
            }
        });

        // visit cases
        for (int i = 0; i < size; i += 1) {
            Label label = new Label();
            Expression expr = expressions.get(i);
            labels[i] = label;
            instructions.add(new BytecodeInstruction() {
                public void visit(MethodVisitor mv) {
                    mv.visitLabel(label);
                    // expressions will leave a value on stack, so need to pop the alibi null
                    mv.visitInsn(POP);
                }
            });
            instructions.add(expr);
            instructions.add(new BytecodeInstruction() {
                public void visit(MethodVisitor mv) {
                    mv.visitJumpInsn(GOTO, tableEnd);
                }
            });
        }

        // default case
        instructions.add(new BytecodeInstruction() {
            public void visit(MethodVisitor mv) {
                mv.visitLabel(dflt);
            }
        });
        ConstantExpression text = new ConstantExpression("invalid index for closure");
        ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
        ThrowStatement ts = new ThrowStatement(cce);
        instructions.add(ts);

        // return
        instructions.add(new BytecodeInstruction() {
            public void visit(MethodVisitor mv) {
                mv.visitLabel(tableEnd);
                mv.visitInsn(ARETURN);
            }
        });

        // load main Closure
        visitClosureExpression(ce);

        // we need later an array to store the curried
        // closures, so we create it here and ave it
        // in a temporary variable
        BytecodeHelper.pushConstant(mv, size);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        int listArrayVar = controller.getCompileStack().defineTemporaryVariable("_listOfClosures", true);

        // add curried versions
        for (int i = 0; i < size; i += 1) {
            // stack: closure

            // we need to create a curried closure version
            // so we store the type on stack
            mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/CurriedClosure");
            // stack: closure, type
            // for a constructor call we need the type two times

            // and the closure after them
            mv.visitInsn(DUP2);
            mv.visitInsn(SWAP);
            // stack: closure,type,type,closure

            // so we can create the curried closure
            mv.visitInsn(ICONST_1);
            mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
            mv.visitInsn(DUP);
            mv.visitInsn(ICONST_0);
            mv.visitLdcInsn(i);
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
            mv.visitInsn(AASTORE);
            mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/CurriedClosure", "<init>", "(Lgroovy/lang/Closure;[Ljava/lang/Object;)V", false);
            // stack: closure,curriedClosure

            // we need to save the result
            mv.visitVarInsn(ALOAD, listArrayVar);
            mv.visitInsn(SWAP);
            BytecodeHelper.pushConstant(mv, i);
            mv.visitInsn(SWAP);
            mv.visitInsn(AASTORE);
            // stack: closure
        }

        // we don't need the closure any longer, so remove it
        mv.visitInsn(POP);
        // we load the array and create a list from it
        mv.visitVarInsn(ALOAD, listArrayVar);
        createListMethod.call(mv);

        // remove the temporary variable to keep the
        // stack clean
        controller.getCompileStack().removeVar(listArrayVar);
        controller.getOperandStack().pop();
    }

    @Override
    public void visitBytecodeExpression(final BytecodeExpression expression) {
        expression.visit(controller.getMethodVisitor());
        controller.getOperandStack().push(expression.getType());
    }

    @Override
    public void visitBytecodeSequence(final BytecodeSequence bytecodeSequence) {
        MethodVisitor mv = controller.getMethodVisitor();
        List instructions = bytecodeSequence.getInstructions();
        int mark = controller.getOperandStack().getStackLength();
        for (Object part : instructions) {
            if (part instanceof EmptyExpression) {
                mv.visitInsn(ACONST_NULL);
            } else if (part instanceof Expression) {
                ((Expression) part).visit(this);
            } else if (part instanceof Statement) {
                Statement stm = (Statement) part;
                stm.visit(this);
                mv.visitInsn(ACONST_NULL);
            } else {
                BytecodeInstruction runner = (BytecodeInstruction) part;
                runner.visit(mv);
            }
        }
        controller.getOperandStack().remove(mark - controller.getOperandStack().getStackLength());
    }

    @Override
    public void visitListExpression(final ListExpression expression) {
        onLineNumber(expression, "ListExpression");

        int size = expression.getExpressions().size();
        boolean containsSpreadExpression = containsSpreadExpression(expression);
        boolean containsOnlyConstants = !containsSpreadExpression && containsOnlyConstants(expression);
        OperandStack operandStack = controller.getOperandStack();
        if (!containsSpreadExpression) {
            MethodVisitor mv = controller.getMethodVisitor();
            BytecodeHelper.pushConstant(mv, size);
            mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
            int maxInit = 1000;
            if (size<maxInit || !containsOnlyConstants) {
                for (int i = 0; i < size; i += 1) {
                    mv.visitInsn(DUP);
                    BytecodeHelper.pushConstant(mv, i);
                    expression.getExpression(i).visit(this);
                    operandStack.box();
                    mv.visitInsn(AASTORE);
                }
                controller.getOperandStack().remove(size);
            } else {
                List<Expression> expressions = expression.getExpressions();
                List<String> methods = new ArrayList<>();
                MethodVisitor oldMv = mv;
                int index = 0;
                while (index<size) {
                    String methodName = "$createListEntry_" + controller.getNextHelperMethodIndex();
                    methods.add(methodName);
                    mv = controller.getClassVisitor().visitMethod(
                            ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC,
                            methodName,
                            "([Ljava/lang/Object;)V",
                            null, null);
                    controller.setMethodVisitor(mv);
                    mv.visitCode();
                    int methodBlockSize = Math.min(size-index, maxInit);
                    int methodBlockEnd = index + methodBlockSize;
                    for (; index < methodBlockEnd; index += 1) {
                        mv.visitVarInsn(ALOAD, 0);
                        mv.visitLdcInsn(index);
                        expressions.get(index).visit(this);
                        operandStack.box();
                        mv.visitInsn(AASTORE);
                    }
                    operandStack.remove(methodBlockSize);
                    mv.visitInsn(RETURN);
                    mv.visitMaxs(0,0);
                    mv.visitEnd();
                }
                mv = oldMv;
                controller.setMethodVisitor(mv);
                for (String methodName : methods) {
                    mv.visitInsn(DUP);
                    mv.visitMethodInsn(INVOKESTATIC, controller.getInternalClassName(), methodName, "([Ljava/lang/Object;)V", false);
                }
            }
        } else {
            despreadList(expression.getExpressions(), false);
        }
        createListMethod.call(controller.getMethodVisitor());
        operandStack.push(ClassHelper.LIST_TYPE);
    }

    @Override
    public void visitGStringExpression(final GStringExpression expression) {
        MethodVisitor mv = controller.getMethodVisitor();

        mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/GStringImpl");
        mv.visitInsn(DUP);

        int size = expression.getValues().size();
        BytecodeHelper.pushConstant(mv, size);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");

        for (int i = 0; i < size; i += 1) {
            mv.visitInsn(DUP);
            BytecodeHelper.pushConstant(mv, i);
            expression.getValue(i).visit(this);
            controller.getOperandStack().box();
            mv.visitInsn(AASTORE);
        }
        controller.getOperandStack().remove(size);

        List<ConstantExpression> strings = expression.getStrings();
        size = strings.size();
        BytecodeHelper.pushConstant(mv, size);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/String");

        for (int i = 0; i < size; i += 1) {
            mv.visitInsn(DUP);
            BytecodeHelper.pushConstant(mv, i);
            controller.getOperandStack().pushConstant(strings.get(i));
            controller.getOperandStack().box();
            mv.visitInsn(AASTORE);
        }
        controller.getOperandStack().remove(size);

        mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/GStringImpl", "<init>", "([Ljava/lang/Object;[Ljava/lang/String;)V", false);
        controller.getOperandStack().push(ClassHelper.GSTRING_TYPE);
    }

    @Override
    public void visitAnnotations(final AnnotatedNode node) {
        // ignore it; annotation generation needs the current visitor
    }

    private void visitAnnotations(final AnnotatedNode targetNode, final Object visitor) {
        visitAnnotations(targetNode, targetNode, visitor);
    }

    private void visitAnnotations(final AnnotatedNode targetNode, final AnnotatedNode sourceNode, final Object visitor) {
        for (AnnotationNode an : sourceNode.getAnnotations()) {
            // skip built-in properties
            if (an.isBuiltIn()) continue;
            if (an.hasSourceRetention()) continue;

            AnnotationVisitor av = getAnnotationVisitor(targetNode, an, visitor);
            visitAnnotationAttributes(an, av);
            av.visitEnd();
        }
    }

    private void visitParameterAnnotations(final Parameter parameter, final int paramNumber, final MethodVisitor mv) {
        for (AnnotationNode an : parameter.getAnnotations()) {
            // skip built-in properties
            if (an.isBuiltIn()) continue;
            if (an.hasSourceRetention()) continue;

            final String annotationDescriptor = BytecodeHelper.getTypeDescription(an.getClassNode());
            AnnotationVisitor av = mv.visitParameterAnnotation(paramNumber, annotationDescriptor, an.hasRuntimeRetention());
            visitAnnotationAttributes(an, av);
            av.visitEnd();
        }
    }

    private AnnotationVisitor getAnnotationVisitor(final AnnotatedNode targetNode, final AnnotationNode an, final Object visitor) {
        final String annotationDescriptor = BytecodeHelper.getTypeDescription(an.getClassNode());
        if (targetNode instanceof MethodNode) {
            return ((MethodVisitor) visitor).visitAnnotation(annotationDescriptor, an.hasRuntimeRetention());
        } else if (targetNode instanceof FieldNode) {
            return ((FieldVisitor) visitor).visitAnnotation(annotationDescriptor, an.hasRuntimeRetention());
        } else if (targetNode instanceof ClassNode) {
            return ((ClassVisitor) visitor).visitAnnotation(annotationDescriptor, an.hasRuntimeRetention());
        }
        throwException("Cannot create an AnnotationVisitor. Please report Groovy bug");
        return null;
    }

    /**
     * Generates the annotation attributes.
     *
     * @param an the node with an annotation
     * @param av the visitor to use
     */
    private void visitAnnotationAttributes(final AnnotationNode an, final AnnotationVisitor av) {
        Map<String, Object> constantAttrs = new HashMap<>();
        Map<String, PropertyExpression> enumAttrs = new HashMap<>();
        Map<String, Object> atAttrs = new HashMap<>();
        Map<String, ListExpression> arrayAttrs = new HashMap<>();

        for (Map.Entry<String, Expression> member : an.getMembers().entrySet()) {
            String name = member.getKey();
            Expression expr = member.getValue();
            if (expr instanceof AnnotationConstantExpression) {
                atAttrs.put(name, ((AnnotationConstantExpression) expr).getValue());
            } else if (expr instanceof ConstantExpression) {
                constantAttrs.put(name, ((ConstantExpression) expr).getValue());
            } else if (expr instanceof ClassExpression) {
                constantAttrs.put(name, Type.getType(BytecodeHelper.getTypeDescription((expr.getType()))));
            } else if (expr instanceof PropertyExpression) {
                enumAttrs.put(name, (PropertyExpression) expr);
            } else if (expr instanceof ListExpression) {
                arrayAttrs.put(name, (ListExpression) expr);
            } else if (expr instanceof ClosureExpression) {
                ClassNode closureClass = controller.getClosureWriter().getOrAddClosureClass((ClosureExpression) expr, ACC_PUBLIC);
                constantAttrs.put(name, Type.getType(BytecodeHelper.getTypeDescription(closureClass)));
            }
        }

        for (Map.Entry<String, Object> entry : constantAttrs.entrySet()) {
            av.visit(entry.getKey(), entry.getValue());
        }
        for (Map.Entry<String, PropertyExpression> entry : enumAttrs.entrySet()) {
            PropertyExpression propExp = entry.getValue();
            av.visitEnum(entry.getKey(),
                    BytecodeHelper.getTypeDescription(propExp.getObjectExpression().getType()),
                    String.valueOf(((ConstantExpression) propExp.getProperty()).getValue()));
        }
        for (Map.Entry<String, Object> entry : atAttrs.entrySet()) {
            AnnotationNode atNode = (AnnotationNode) entry.getValue();
            AnnotationVisitor av2 = av.visitAnnotation(entry.getKey(),
                    BytecodeHelper.getTypeDescription(atNode.getClassNode()));
            visitAnnotationAttributes(atNode, av2);
            av2.visitEnd();
        }
        visitArrayAttributes(an, arrayAttrs, av);
    }

    private void visitArrayAttributes(final AnnotationNode an, final Map<String, ListExpression> arrayAttr, final AnnotationVisitor av) {
        if (arrayAttr.isEmpty()) return;
        for (Map.Entry<String, ListExpression> entry : arrayAttr.entrySet()) {
            AnnotationVisitor av2 = av.visitArray(entry.getKey());
            List<Expression> values = entry.getValue().getExpressions();
            if (!values.isEmpty()) {
                int arrayElementType = determineCommonArrayType(values);
                for (Expression exprChild : values) {
                    visitAnnotationArrayElement(exprChild, arrayElementType, av2);
                }
            }
            av2.visitEnd();
        }
    }

    private static int determineCommonArrayType(final List<Expression> values) {
        Expression expr = values.get(0);
        int arrayElementType = -1;
        if (expr instanceof AnnotationConstantExpression) {
            arrayElementType = 1;
        } else if (expr instanceof ConstantExpression) {
            arrayElementType = 2;
        } else if (expr instanceof ClassExpression) {
            arrayElementType = 3;
        } else if (expr instanceof PropertyExpression) {
            arrayElementType = 4;
        }
        return arrayElementType;
    }

    private void visitAnnotationArrayElement(final Expression expr, final int arrayElementType, final AnnotationVisitor av) {
        switch (arrayElementType) {
            case 1:
                AnnotationNode atAttr = (AnnotationNode) ((AnnotationConstantExpression) expr).getValue();
                AnnotationVisitor av2 = av.visitAnnotation(null, BytecodeHelper.getTypeDescription(atAttr.getClassNode()));
                visitAnnotationAttributes(atAttr, av2);
                av2.visitEnd();
                break;
            case 2:
                av.visit(null, ((ConstantExpression) expr).getValue());
                break;
            case 3:
                av.visit(null, Type.getType(BytecodeHelper.getTypeDescription(expr.getType())));
                break;
            case 4:
                PropertyExpression propExpr = (PropertyExpression) expr;
                av.visitEnum(null,
                        BytecodeHelper.getTypeDescription(propExpr.getObjectExpression().getType()),
                        String.valueOf(((ConstantExpression) propExpr.getProperty()).getValue()));
                break;
        }
    }

    // Implementation methods
    //-------------------------------------------------------------------------

    public static int argumentSize(final Expression arguments) {
        if (arguments instanceof TupleExpression) {
            TupleExpression tupleExpression = (TupleExpression) arguments;
            int size = tupleExpression.getExpressions().size();
            return size;
        }
        return 1;
    }

    private static String[] buildExceptions(final ClassNode[] exceptions) {
        if (exceptions == null) return null;
        return Arrays.stream(exceptions).map(BytecodeHelper::getClassInternalName).toArray(String[]::new);
    }

    private static boolean containsOnlyConstants(final ListExpression list) {
        for (Expression exp : list.getExpressions()) {
            if (exp instanceof ConstantExpression) continue;
            return false;
        }
        return true;
    }

    public static boolean containsSpreadExpression(final Expression arguments) {
        List<Expression> args = null;
        if (arguments instanceof TupleExpression) {
            TupleExpression tupleExpression = (TupleExpression) arguments;
            args = tupleExpression.getExpressions();
        } else if (arguments instanceof ListExpression) {
            ListExpression le = (ListExpression) arguments;
            args = le.getExpressions();
        } else {
            return arguments instanceof SpreadExpression;
        }
        for (Expression arg : args) {
            if (arg instanceof SpreadExpression) return true;
        }
        return false;
    }

    private boolean isInnerClass() {
        return controller.getClassNode().getOuterClass() != null;
    }

    public static boolean isNullConstant(final Expression expression) {
        return expression instanceof ConstantExpression && ((ConstantExpression) expression).isNullExpression();
    }

    public static boolean isThisExpression(final Expression expression) {
        return expression instanceof VariableExpression && ((VariableExpression) expression).isThisExpression();
    }

    public static boolean isSuperExpression(final Expression expression) {
        return expression instanceof VariableExpression && ((VariableExpression) expression).isSuperExpression();
    }

    private static boolean isThisOrSuper(final Expression expression) {
        return isThisExpression(expression) || isSuperExpression(expression);
    }

    private static boolean isVargs(final Parameter[] params) {
        return (params.length > 0 && params[params.length - 1].getType().isArray());
    }

    public boolean addInnerClass(final ClassNode innerClass) {
        ModuleNode mn = controller.getClassNode().getModule();
        innerClass.setModule(mn);
        mn.getUnit().addGeneratedInnerClass((InnerClassNode)innerClass);
        return innerClasses.add(innerClass);
    }

    public void onLineNumber(final ASTNode statement, final String message) {
        if (statement == null || statement instanceof BlockStatement) return;

        currentASTNode = statement;
        int line = statement.getLineNumber();
        if (line < 0 || (!ASM_DEBUG && line == controller.getLineNumber())) return;

        controller.setLineNumber(line);
        MethodVisitor mv = controller.getMethodVisitor();
        if (mv != null) {
            Label l = new Label();
            mv.visitLabel(l);
            mv.visitLineNumber(line, l);
        }
    }

    public void throwException(final String message) {
        throw new RuntimeParserException(message, currentASTNode);
    }
}
