private int _getAccessor(Object o, Class type) {
    if (o instanceof List) {
      assert debug("NEW " + LIST_IMPL);
      mv.visitTypeInsn(NEW, LIST_IMPL);

      assert debug("DUP");
      mv.visitInsn(DUP);

      assert debug("DUP");
      mv.visitInsn(DUP);

      intPush(((List) o).size());
      assert debug("INVOKESPECIAL " + LIST_IMPL + ".<init>");
      mv.visitMethodInsn(INVOKESPECIAL, LIST_IMPL, "<init>", "(I)V");

      for (Object item : (List) o) {
        if (_getAccessor(item, type) != VAL) {
          assert debug("POP");
          mv.visitInsn(POP);
        }

        assert debug("INVOKEINTERFACE java/util/List.add");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z");

        assert debug("POP");
        mv.visitInsn(POP);

        assert debug("DUP");
        mv.visitInsn(DUP);
      }

      returnType = List.class;

      return LIST;
    }
    else if (o instanceof Map) {
      assert debug("NEW " + MAP_IMPL);
      mv.visitTypeInsn(NEW, MAP_IMPL);

      assert debug("DUP");
      mv.visitInsn(DUP);

      assert debug("DUP");
      mv.visitInsn(DUP);

      intPush(((Map) o).size());

      assert debug("INVOKESPECIAL " + MAP_IMPL + ".<init>");
      mv.visitMethodInsn(INVOKESPECIAL, MAP_IMPL, "<init>", "(I)V");

      for (Object item : ((Map) o).keySet()) {
        mv.visitTypeInsn(CHECKCAST, "java/util/Map");

        if (_getAccessor(item, type) != VAL) {
          assert debug("POP");
          mv.visitInsn(POP);
        }
        if (_getAccessor(((Map) o).get(item), type) != VAL) {
          assert debug("POP");
          mv.visitInsn(POP);
        }

        assert debug("INVOKEINTERFACE java/util/Map.put");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put",
            "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

        assert debug("POP");
        mv.visitInsn(POP);

        assert debug("DUP");
        mv.visitInsn(DUP);
      }

      returnType = Map.class;

      return MAP;
    }
    else if (o instanceof Object[]) {
      Accessor[] a = new Accessor[((Object[]) o).length];
      int i = 0;
      int dim = 0;

      if (type != null) {
        String nm = type.getName();
        while (nm.charAt(dim) == '[') dim++;
      }
      else {
        type = Object[].class;
        dim = 1;
      }

      try {
        intPush(((Object[]) o).length);
        assert debug("ANEWARRAY " + getInternalName(getSubComponentType(type)) + " (" + ((Object[]) o).length + ")");
        mv.visitTypeInsn(ANEWARRAY, getInternalName(getSubComponentType(type)));

        Class cls = dim > 1 ? findClass(null, repeatChar('[', dim - 1)
            + "L" + getBaseComponentType(type).getName() + ";", pCtx)
            : type;


        assert debug("DUP");
        mv.visitInsn(DUP);

        for (Object item : (Object[]) o) {
          intPush(i);

          if (_getAccessor(item, cls) != VAL) {
            assert debug("POP");
            mv.visitInsn(POP);
          }

          assert debug("AASTORE (" + o.hashCode() + ")");
          mv.visitInsn(AASTORE);

          assert debug("DUP");
          mv.visitInsn(DUP);

          i++;
        }

      }
      catch (ClassNotFoundException e) {
        throw new RuntimeException("this error should never throw:" + getBaseComponentType(type).getName(), e);
      }

      return ARRAY;
    }
    else {
      if (type.isArray()) {
        writeLiteralOrSubexpression(subCompileExpression(((String) o).toCharArray(), pCtx), getSubComponentType(type));
      }
      else {
        writeLiteralOrSubexpression(subCompileExpression(((String) o).toCharArray(), pCtx));
      }
      return VAL;
    }
  }