public void storeVar(BytecodeVariable variable) {
   MethodVisitor mv = controller.getMethodVisitor();
   int idx = variable.getIndex();
   ClassNode type = variable.getType();
   // value is on stack
   if (variable.isHolder()) {
     doGroovyCast(type);
     box();
     mv.visitVarInsn(ALOAD, idx);
     mv.visitTypeInsn(CHECKCAST, "groovy/lang/Reference");
     mv.visitInsn(SWAP);
     mv.visitMethodInsn(
         INVOKEVIRTUAL, "groovy/lang/Reference", "set", "(Ljava/lang/Object;)V", false);
   } else {
     doGroovyCast(type);
     if (type == ClassHelper.double_TYPE) {
       mv.visitVarInsn(DSTORE, idx);
     } else if (type == ClassHelper.float_TYPE) {
       mv.visitVarInsn(FSTORE, idx);
     } else if (type == ClassHelper.long_TYPE) {
       mv.visitVarInsn(LSTORE, idx);
     } else if (type == ClassHelper.boolean_TYPE
         || type == ClassHelper.char_TYPE
         || type == ClassHelper.byte_TYPE
         || type == ClassHelper.int_TYPE
         || type == ClassHelper.short_TYPE) {
       mv.visitVarInsn(ISTORE, idx);
     } else {
       mv.visitVarInsn(ASTORE, idx);
     }
   }
   // remove RHS value from operand stack
   remove(1);
 }
  public static void loadReference(String name, WriterController controller) {
    CompileStack compileStack = controller.getCompileStack();
    MethodVisitor mv = controller.getMethodVisitor();
    ClassNode classNode = controller.getClassNode();
    AsmClassGenerator acg = controller.getAcg();

    // compileStack.containsVariable(name) means to ask if the variable is already declared
    // compileStack.getScope().isReferencedClassVariable(name) means to ask if the variable is a
    // field
    // If it is no field and is not yet declared, then it is either a closure shared variable or
    // an already declared variable.
    if (!compileStack.containsVariable(name)
        && compileStack.getScope().isReferencedClassVariable(name)) {
      acg.visitFieldExpression(new FieldExpression(classNode.getDeclaredField(name)));
    } else {
      BytecodeVariable v =
          compileStack.getVariable(name, !classNodeUsesReferences(controller.getClassNode()));
      if (v == null) {
        // variable is not on stack because we are
        // inside a nested Closure and this variable
        // was not used before
        // then load it from the Closure field
        FieldNode field = classNode.getDeclaredField(name);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(
            GETFIELD,
            controller.getInternalClassName(),
            name,
            BytecodeHelper.getTypeDescription(field.getType()));
      } else {
        mv.visitVarInsn(ALOAD, v.getIndex());
      }
      controller.getOperandStack().push(ClassHelper.REFERENCE_TYPE);
    }
  }
  public void loadOrStoreVariable(BytecodeVariable variable, boolean useReferenceDirectly) {
    CompileStack compileStack = controller.getCompileStack();

    if (compileStack.isLHS()) {
      storeVar(variable);
    } else {
      MethodVisitor mv = controller.getMethodVisitor();
      int idx = variable.getIndex();
      ClassNode type = variable.getType();

      if (variable.isHolder()) {
        mv.visitVarInsn(ALOAD, idx);
        if (!useReferenceDirectly) {
          mv.visitMethodInsn(
              INVOKEVIRTUAL, "groovy/lang/Reference", "get", "()Ljava/lang/Object;", false);
          BytecodeHelper.doCast(mv, type);
          push(type);
        } else {
          push(ClassHelper.REFERENCE_TYPE);
        }
      } else {
        load(type, idx);
      }
    }
  }