public IValue visitNode(INode o) throws IOException {
      printString(o.getName());

      boolean indent = checkIndent(o);

      append('(');
      tab();
      indent(indent);
      Iterator<IValue> it = o.iterator();
      int k = 0;
      while (it.hasNext()) {
        it.next().accept(this);
        if (it.hasNext()) {
          append(',');
          indent(indent);
        }
        k++;
      }

      if (o.mayHaveKeywordParameters()) {
        IWithKeywordParameters<? extends INode> wkw = o.asWithKeywordParameters();
        if (wkw.hasParameters()) {
          if (k > 0) {
            append(',');
          }

          Iterator<Entry<String, IValue>> kwIt = wkw.getParameters().entrySet().iterator();
          while (kwIt.hasNext()) {
            Entry<String, IValue> e = kwIt.next();
            indent();
            append(e.getKey());
            append('=');
            e.getValue().accept(this);

            if (kwIt.hasNext()) {
              append(',');
            }
          }
        }
      }
      append(')');
      untab();
      if (o.isAnnotatable() && o.asAnnotatable().hasAnnotations()) {
        append('[');
        tab();
        indent();
        int i = 0;
        Map<String, IValue> annotations = o.asAnnotatable().getAnnotations();
        for (Entry<String, IValue> entry : annotations.entrySet()) {
          append("@" + entry.getKey() + "=");
          entry.getValue().accept(this);

          if (++i < annotations.size()) {
            append(",");
            indent();
          }
        }
        untab();
        indent();
        append(']');
      }

      return o;
    }
    public IValue visitConstructor(IConstructor o) throws IOException {
      String name = o.getName();
      if (name == null) System.err.println("hello");
      if (name.equals("loc")) {
        append('\\');
      }

      if (name.indexOf('-') != -1) {
        append('\\');
      }
      append(name);

      boolean indent = checkIndent(o);

      append('(');
      tab();
      indent(indent);
      Iterator<IValue> it = o.iterator();
      int k = 0;
      while (it.hasNext()) {
        it.next().accept(this);
        if (it.hasNext()) {
          append(',');
          indent(indent);
        }
        k++;
      }

      if (o.mayHaveKeywordParameters()) {
        IWithKeywordParameters<? extends IConstructor> wkw = o.asWithKeywordParameters();
        if (wkw.hasParameters()) {
          if (k > 0) {
            append(',');
          }

          Iterator<Entry<String, IValue>> iterator = wkw.getParameters().entrySet().iterator();
          while (iterator.hasNext()) {
            Entry<String, IValue> e = iterator.next();

            append(e.getKey());
            append('=');
            e.getValue().accept(this);

            if (iterator.hasNext()) {
              append(',');
            }
          }
        }
      }

      append(')');
      untab();
      if (o.isAnnotatable() && o.asAnnotatable().hasAnnotations()) {
        append('[');
        tab();
        indent();
        int i = 0;
        Map<String, IValue> annotations = o.asAnnotatable().getAnnotations();
        for (Entry<String, IValue> entry : annotations.entrySet()) {
          append("@" + entry.getKey() + "=");
          entry.getValue().accept(this);

          if (++i < annotations.size()) {
            append(",");
            indent();
          }
        }
        untab();
        indent();
        append(']');
      }
      try {
        stream.flush();
      } catch (IOException e) {
        // flushing is just to make sure we get some intermediate output
      }

      return o;
    }