#include "Node.h"

#include "idst-config.h"

#include <stdio.h>
#include <assert.h>

extern oop s__2a;	// *
extern oop s__2b;	// +
extern oop s__2d;	// -
extern oop s__2f_2f;	// //
extern oop s__3c;	// <
extern oop s__3c_3d;	// <=
extern oop s__3d;	// =
extern oop s__3d_3d;	// ==
extern oop s__3e;	// >
extern oop s__3e_3d;	// >=
extern oop s__5c_5c;	// div
extern oop s__7e_3d;	// ~=
extern oop s__7e_7e;	// ~~
extern oop s_bitAnd_;
extern oop s_bitOr_;
extern oop s_bitXor_;
extern oop s_value;
extern oop s_and_;
extern oop s_or_;
extern oop s_ifFalse_;
extern oop s_ifFalse_ifTrue_;
extern oop s_ifTrue_;
extern oop s_ifTrue_ifFalse_;
extern oop s_self;
extern oop s_super;
extern oop s_whileTrue;
extern oop s_whileTrue_;
extern oop s_whileFalse;
extern oop s_whileFalse_;

//  oop mReceiver;
//  oop mSelector;
//  oop mArguments;
//  oop mCascade;

SendNode::SendNode(oop selector, oop arguments)
{
  mReceiver=  0;
  mSelector=  selector;
  mArguments= arguments;
  mCascade=   0;
  mGenMacro=  0;
  mSuper=     0;
}

oop SendNode::withSelectorArgument(oop selector, oop argument)
{
  return new SendNode(selector, ListNode::with(argument));
}

oop SendNode::withSelector(oop selector)
{
  return new SendNode(selector, ListNode::empty());
}

oop SendNode::receiver(void)
{
  return mReceiver;
}

oop SendNode::selector(void)
{
  return mSelector;
}

oop SendNode::arguments(void)
{
  return mArguments;
}

oop SendNode::cascade(void)
{
  return mCascade;
}

oop SendNode::super(oop super)
{
  mSuper= super;
  return this;
}

oop SendNode::super(void)
{
  return mSuper;
}

oop SendNode::addReceiver(oop receiver)
{
  assert(!mReceiver);
  mReceiver= receiver;
  return this;
}

oop SendNode::addKeywordArgument(oop keyword, oop argument)
{
  mSelector= *mSelector + keyword;
  mArguments->add(argument);
  return this;
}

oop SendNode::addArgument(oop argument)
{
  mArguments->add(argument);
  return this;
}

oop SendNode::addCascade(oop cascade)
{
  assert(!cascade->receiver());
  assert(!cascade->cascade());
  if (mCascade)
    mCascade->addCascade(cascade);
  else
    mCascade= cascade;
  return this;
}

oop SendNode::encodeMacro(oop encoder)
{
  if (mCascade)
    return 0;

  switch (mArguments->size())
    {
    case 0:
      if (mReceiver->isOpenBlock())
	{
	  if ((*mSelector == s_whileTrue) || (*mSelector == s_whileFalse))
	    {
	      mGenMacro= (*mSelector == s_whileTrue) ? &SendNode::gen_whileTrue : &SendNode::gen_whileFalse;
	      mReceiver->sequence()->encode(encoder);
	      mLocation= mReceiver->sequence()->location();
	      return this;
	    }
	  if (*mSelector == s_value)
	    {
	      mGenMacro= &SendNode::gen_value;
	      mReceiver->sequence()->encode(encoder);
	      mLocation= mReceiver->sequence()->location();
	      return this;
	    }
	}
      break;

    case 1:
      {
	oop arg1= mArguments->at(0);
#      if (INLINE_ARITHMETIC)
	if (*mSelector == s__2b)	{ mGenMacro= &SendNode::gen_add_;	goto commonBinary; }
	if (*mSelector == s__2d)	{ mGenMacro= &SendNode::gen_sub_;	goto commonBinary; }
	if (*mSelector == s__2a)	{ mGenMacro= &SendNode::gen_mul_;	goto commonBinary; }
	if (*mSelector == s__2f_2f)	{ mGenMacro= &SendNode::gen_div_;	goto commonBinary; }
	if (*mSelector == s__5c_5c)	{ mGenMacro= &SendNode::gen_mod_;	goto commonBinary; }
	if (*mSelector == s__3c)	{ mGenMacro= &SendNode::gen_lt_;	goto commonBinary; }
	if (*mSelector == s__3c_3d)	{ mGenMacro= &SendNode::gen_le_;	goto commonBinary; }
	if (*mSelector == s__3d)	{ mGenMacro= &SendNode::gen_eq_;	goto commonBinary; }
	if (*mSelector == s__3d_3d)	{ mGenMacro= &SendNode::gen_id_;	goto commonBinary; }
	if (*mSelector == s__7e_7e)	{ mGenMacro= &SendNode::gen_ni_;	goto commonBinary; }
	if (*mSelector == s__7e_3d)	{ mGenMacro= &SendNode::gen_ne_;	goto commonBinary; }
	if (*mSelector == s__3e_3d)	{ mGenMacro= &SendNode::gen_ge_;	goto commonBinary; }
	if (*mSelector == s__3e)	{ mGenMacro= &SendNode::gen_gt_;	goto commonBinary; }
	if (*mSelector == s_bitAnd_)	{ mGenMacro= &SendNode::gen_bitAnd_;	goto commonBinary; }
	if (*mSelector == s_bitOr_)	{ mGenMacro= &SendNode::gen_bitOr_;	goto commonBinary; }
	if (*mSelector == s_bitXor_)	{ mGenMacro= &SendNode::gen_bitXor_;
	    {
	     commonBinary:
	      mReceiver->encode(encoder);
	      arg1->encode(encoder);
	      encoder->popStack();
	      mLocation= mReceiver->location();
	      return this;
	    }
	  }
#      endif
	if (arg1->isOpenBlock())
	  {
	    if ((*mSelector == s_ifTrue_) || (*mSelector == s_ifFalse_)
		|| (*mSelector == s_and_) || (*mSelector == s_or_))
	      {
		if (mReceiver->isBlockNode())
		  fprintf(stderr, "WARNING: sending %s to a literal block is probably not what you intended\n", mSelector->cString());
		if      (*mSelector == s_ifTrue_)	mGenMacro= &SendNode::gen_ifTrue_;
		else if (*mSelector == s_ifFalse_)	mGenMacro= &SendNode::gen_ifFalse_;
		else if (*mSelector == s_and_)		mGenMacro= &SendNode::gen_and_;
		else if (*mSelector == s_or_)		mGenMacro= &SendNode::gen_or_;
		assert(mGenMacro);
		mReceiver->encode(encoder);
		arg1->sequence()->encode(encoder);
		encoder->popStack();
		mLocation= mReceiver->location();
		return this;
	      }
	    if (mReceiver->isOpenBlock())
	      {
		if ((*mSelector == s_whileTrue_) || (*mSelector == s_whileFalse_))
		  {
		    mGenMacro= (*mSelector == s_whileTrue_) ? &SendNode::gen_whileTrue_ : &SendNode::gen_whileFalse_;
		    mReceiver->sequence()->encode(encoder);
		    encoder->popStack();
		    arg1->sequence()->encode(encoder);
		    mLocation= arg1->sequence()->location();
		    return this;
		  }
	      }
	  }
      }
      break;

    case 2:
      {
	oop arg1= mArguments->at(0), arg2= mArguments->at(1);
	if (arg1->isOpenBlock() && arg1->isOpenBlock())
	  {
	    if ((*mSelector == s_ifTrue_ifFalse_) || (*mSelector == s_ifFalse_ifTrue_))
	      {
		if (mReceiver->isBlockNode())
		  fprintf(stderr, "WARNING: sending %s to a literal block is probably not what you intended\n", mSelector->cString());
		mReceiver->encode(encoder);
		mGenMacro= (*mSelector == s_ifTrue_ifFalse_) ? &SendNode::gen_ifTrue_ifFalse_ : &SendNode::gen_ifFalse_ifTrue_;
		arg1->sequence()->encode(encoder);
		encoder->popStack();
		arg2->sequence()->encode(encoder);
		encoder->popStack();
		mLocation= mReceiver->location();
		assert(arg1->sequence()->location() == arg2->sequence()->location());
		return this;
	      }
	  }
      }
      break;
    }      
  return 0;
}

oop SendNode::encode(oop encoder)
{
  oop encoded= 0;

  encoder->translationUnit()->declareSelector(mSelector);

  if ((encoded= encodeMacro(encoder)))
    return encoded;

  if (mReceiver->isVariableNode() && (*s_super == mReceiver->name()))
    {
      oop super= encoder->getClass()->superclass();
      if (!super)
	error("cannot send to super at root of hierarchy");
      for (oop send= this;  send;  send= send->cascade())
	send->super(super);
      mReceiver= VariableNode::withName(s_self);
    }
  mReceiver->encode(encoder);
  for (oop send= this;  send;  send= send->cascade())
    {
      encoder->translationUnit()->declareSelector(send->selector());
      oop arguments= send->arguments();
      iterate(arguments, arg)
	arg.element()->encode(encoder);
      encoder->popStack(arguments->size());
    }
  mLocation= mReceiver->location();
  return this;
}

oop SendNode::gen_add_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= (oop)((int)_%d + (int)_%d - 1);\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_sub_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= (oop)((int)_%d - (int)_%d + 1);\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_mul_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= _integerObject(_integerValue(_%d) * _integerValue(_%d));\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_div_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= _integerObject(_integerValue(_%d) / _integerValue(_%d));\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_mod_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= _integerObject(_integerValue(_%d) % _integerValue(_%d));\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_lt_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= ((int)_%d < (int)_%d) ? v_true : v_false;\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_le_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= ((int)_%d <= (int)_%d) ? v_true : v_false;\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_eq_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= ((int)_%d == (int)_%d) ? v_true : v_false;\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_id_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream->format("  _%d= (_%d == _%d) ? v_true : v_false;\n", mLocation, mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_ni_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream->format("  _%d= (_%d != _%d) ? v_true : v_false;\n", mLocation, mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_ne_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= ((int)_%d != (int)_%d) ? v_true : v_false;\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_ge_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= ((int)_%d >= (int)_%d) ? v_true : v_false;\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_gt_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= ((int)_%d > (int)_%d) ? v_true : v_false;\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_bitAnd_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= (oop)(((int)_%d & (int)_%d) | 1);\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_bitOr_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= (oop)((int)_%d | (int)_%d);\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_bitXor_(oop unit)
{
  oop stream= unit->outputStream();
  oop arg= mArguments->at(0);
  mReceiver->gen(unit);
  arg->gen(unit);
  stream
    ->format("  if (_areIntegerObjects(_%d, _%d))\n", mReceiver->location(), arg->location())
    ->format("    _%d= (oop)(((int)_%d ^ (int)_%d) | 1);\n", mLocation, mReceiver->location(), arg->location())
    ->format("  else\n")
    ->format("    _%d= _bind(_%d, %s)(_%d, _%d);\n",
	     mLocation, mReceiver->location(),
	     unit->lookupSelector(mSelector)->cString(),
	     mReceiver->location(), arg->location());
  return this;
}

oop SendNode::gen_value(oop unit)
{
  mReceiver->sequence()->genBody(unit, 0);
  return this;
}

oop SendNode::gen_and_(oop unit)
{
  mReceiver->gen(unit);
  oop stream= unit->outputStream();
  oop seq1= mArguments->at(0)->sequence();
  stream->format("  if (_%d) {\n", mLocation);
  seq1->genBody(unit, 0);
  stream->format("  _%d= _%d;\n", mLocation, seq1->location());
  stream->format("  }\n");
  return this;
}

oop SendNode::gen_or_(oop unit)
{
  mReceiver->gen(unit);
  oop stream= unit->outputStream();
  oop seq1= mArguments->at(0)->sequence();
  stream->format("  if (!_%d) {\n", mLocation);
  seq1->genBody(unit, 0);
  stream->format("  _%d= _%d;\n", mLocation, seq1->location());
  stream->format("  }\n");
  return this;
}

oop SendNode::gen_ifTrue_(oop unit)
{
  mReceiver->gen(unit);
  oop stream= unit->outputStream();
  oop seq1= mArguments->at(0)->sequence();
  stream->format("  if (_%d) {\n", mLocation);
  seq1->genBody(unit, 0);
  stream->format("  _%d= _%d;\n", mLocation, seq1->location());
  stream->format("  } else _%d= 0;\n", mLocation);
  return this;
}

oop SendNode::gen_ifFalse_(oop unit)
{
  mReceiver->gen(unit);
  oop stream= unit->outputStream();
  oop seq1= mArguments->at(0)->sequence();
  stream->format("  if (!_%d) {\n", mLocation);
  seq1->genBody(unit, 0);
  stream->format("  _%d= _%d;\n", mLocation, seq1->location());
  stream->format("  } else _%d= 0;\n", mLocation);
  return this;
}

oop SendNode::gen_ifTrue_ifFalse_(oop unit)
{
  mReceiver->gen(unit);
  oop stream= unit->outputStream();
  oop seq1= mArguments->at(0)->sequence();
  oop seq2= mArguments->at(1)->sequence();
  stream->format("  if (_%d) {\n", mLocation);
  seq1->genBody(unit, 0);
  stream->format("  } else {\n");
  seq2->genBody(unit, 0);
  stream->format("  } _%d= _%d;\n", mLocation, seq2->location());
  return this;
}

oop SendNode::gen_ifFalse_ifTrue_(oop unit)
{
  mReceiver->gen(unit);
  oop stream= unit->outputStream();
  oop seq1= mArguments->at(0)->sequence();
  oop seq2= mArguments->at(1)->sequence();
  stream->format("  if (!_%d) {\n", mLocation);
  seq1->genBody(unit, 0);
  stream->format("  } else {\n");
  seq2->genBody(unit, 0);
  stream->format("  } _%d= _%d;\n", mLocation, seq2->location());
  return this;
}

oop SendNode::gen_whileTrue(oop unit)
{
  oop stream= unit->outputStream();
  stream->format("  do {\n");
  mReceiver->sequence()->genBody(unit, 0);
  stream->format("  } while (_%d);\n", mLocation);
  return this;
}

oop SendNode::gen_whileTrue_(oop unit)
{
  oop stream= unit->outputStream();
  stream->format("  for (;;) {\n");
  mReceiver->sequence()->genBody(unit, 0);
  stream->format("  if (!_%d) break;\n", mLocation);
  mArguments->at(0)->sequence()->genBody(unit, 0);
  stream->format("  };\n");
  return this;
}

oop SendNode::gen_whileFalse(oop unit)
{
  oop stream= unit->outputStream();
  stream->format("  do {\n");
  mReceiver->sequence()->genBody(unit, 0);
  stream->format("  } while (!_%d);\n", mLocation);
  return this;
}

oop SendNode::gen_whileFalse_(oop unit)
{
  oop stream= unit->outputStream();
  stream->format("  for (;;) {\n");
  mReceiver->sequence()->genBody(unit, 0);
  stream->format("  if (_%d) break;\n", mLocation);
  mArguments->at(0)->sequence()->genBody(unit, 0);
  stream->format("  };\n");
  return this;
}

oop SendNode::gen(oop unit)
{
  if (mGenMacro)
    return (this->*mGenMacro)(unit);

  mReceiver->gen(unit);
  oop stream= unit->outputStream();
  for (oop send= this;  send;  send= send->cascade())
    {
      oop selector= unit->lookupSelector(send->selector());
      oop arguments= send->arguments();
      iterate(arguments, arg)
	arg.element()->gen(unit);
      stream->format("  ");
      if (!send->cascade())
	stream->format("_%d= ", mLocation);
      if (send->super())
	stream->format("_rebind(v_%s, %s)(_%d", send->super()->name()->cString(), selector->cString(), mLocation);
      else
	stream->format("_bind(_%d, %s)(_%d", mLocation, selector->cString(), mLocation);
      iterate(send->arguments(), arg)
	stream->format(", _%d", arg.element()->location());
      stream->format(");\n");
    }
  return this;
}

oop SendNode::printOnIndent(oop stream, int indent)
{
  mReceiver->printOnIndent(stream, indent);
  for (oop send= this;  send;  send= send->cascade())
    {
      stream->space((indent + 1) * 2)->print(send->selector())->nl();
      send->arguments()->printOnIndent(stream, indent + 1);
    }
  return this;
}
