public override bool Visit(
     UnifiedReferenceType element, VisitorArgument arg)
 {
     Writer.Write("/* & */");
     element.Type.TryAccept(this, arg);
     return false;
 }
 public override bool Visit(
     UnifiedConstType element, VisitorArgument arg)
 {
     Writer.Write("final ");
     element.Type.TryAccept(this, arg);
     return false;
 }
 public override bool Visit(
     UnifiedGenericType element, VisitorArgument arg)
 {
     element.Type.TryAccept(this, arg);
     element.Arguments.TryAccept(this, arg);
     return false;
 }
 public override bool Visit(UnifiedImport element, VisitorArgument arg)
 {
     Writer.Write("import ");
     element.Modifiers.TryAccept(this, arg);
     element.Name.TryAccept(this, arg);
     return false;
 }
 public override bool Visit(UnifiedProgram element, VisitorArgument arg)
 {
     element.MagicComment.TryAccept(this, arg);
     Writer.WriteLine();
     element.Body.TryAccept(this, arg);
     return false;
 }
        // ブロック(UnifiedBlock)
        public override bool Visit(UnifiedBlock element, VisitorArgument arg)
        {
            // 要素の左端に記述すべきものがある場合はそれを出力する
            // プログラム全体の場合は何も出力しないが、関数の場合には中括弧が必要になるなど
            if (!string.IsNullOrEmpty(arg.Decoration.MostLeft)) {
                Writer.WriteLine(arg.Decoration.MostLeft);
                arg = arg.IncrementDepth();
            }

            // ブロック内の要素を列挙する
            // セミコロンが必要な要素の場合にはセミコロンを出力する
            foreach (var stmt in element) {
                WriteIndent(arg);
                if (stmt.TryAccept(this, arg)) {
                    Writer.Write(";");
                }
                Writer.Write(arg.Decoration.EachRight);
            }

            // 要素の右端に記述すべきものがある場合はインデントを元に戻しそれを出力する
            if (!string.IsNullOrEmpty(arg.Decoration.MostRight)) {
                arg = arg.DecrementDepth();
                WriteIndent(arg);
                Writer.Write(arg.Decoration.MostRight);
            }
            return false;
        }
 public override bool Visit(UnifiedImport element, VisitorArgument arg)
 {
     Writer.Write(ImportKeyword);
     element.Modifiers.TryAccept(this, arg);
     element.Name.TryAccept(this, arg);
     return true;
 }
 public override bool Visit(UnifiedLambda element, VisitorArgument arg)
 {
     element.Parameters.TryAccept(this, arg);
     Writer.Write(" => ");
     element.Body.Accept(this, arg);
     return true;
 }
 //単項演算子
 public override bool Visit(
         UnifiedUnaryOperator element, VisitorArgument arg)
 {
     var kind = element.Kind;
     switch (kind) {
     case (UnifiedUnaryOperatorKind.Negate):
         Writer.Write("-");
         break;
     case (UnifiedUnaryOperatorKind.Not):
         Writer.Write("!");
         break;
     case (UnifiedUnaryOperatorKind.PostDecrementAssign):
     case (UnifiedUnaryOperatorKind.PreDecrementAssign):
         Writer.Write("--");
         break;
     case (UnifiedUnaryOperatorKind.PostIncrementAssign):
     case (UnifiedUnaryOperatorKind.PreIncrementAssign):
         Writer.Write("++");
         break;
     case (UnifiedUnaryOperatorKind.UnaryPlus):
         Writer.Write("+");
         break;
     case (UnifiedUnaryOperatorKind.OnesComplement):
         Writer.Write("~");
         break;
     case (UnifiedUnaryOperatorKind.Unknown):
         Writer.Write(element.Sign);
         break;
     default:
         throw new InvalidOperationException();
     }
     return false;
 }
 public override bool Visit(
     UnifiedVolatileType element, VisitorArgument arg)
 {
     Writer.Write("volatile ");
     element.Type.TryAccept(this, arg);
     return false;
 }
 // e.g. (Int)a  or (int)(a + b)
 public override bool Visit(UnifiedCast element, VisitorArgument arg)
 {
     Writer.Write("(");
     element.Type.TryAccept(this, arg);
     Writer.Write(")");
     element.Expression.TryAccept(this, arg.Set(Paren));
     return false;
 }
 //goto文
 public override bool Visit(UnifiedGoto element, VisitorArgument arg)
 {
     //JavaScriptではgoto文はサポートされていない
     Writer.Write("/* goto ");
     element.Target.TryAccept(this, arg);
     Writer.Write("*/");
     return true;
 }
 public override bool Visit(
         UnifiedNamespaceDefinition element, VisitorArgument arg)
 {
     Writer.Write("package ");
     element.Name.TryAccept(this, arg);
     Writer.WriteLine(";");
     element.Body.TryAccept(this, arg);
     return false;
 }
 //キャスト式
 public override bool Visit(UnifiedCast element, VisitorArgument arg)
 {
     Writer.Write("(");
     element.Type.TryAccept(this, arg);
     Writer.Write(")");
     //TODO ここのarg.Set(Paren)が不要な気がするので、後ではずしてテストしてみる
     element.Expression.TryAccept(this, arg.Set(Paren));
     return true;
 }
 public override bool Visit(
     UnifiedNamespaceDefinition element, VisitorArgument arg)
 {
     element.Annotations.TryAccept(this, arg);
     Writer.Write("namespace ");
     element.Name.Accept(this, arg);
     Writer.Write(" ");
     element.Body.Accept(this, arg.Set(ForBlock));
     return false;
 }
 public override bool Visit(
         UnifiedSet<UnifiedCase> element, VisitorArgument arg)
 {
     arg = arg.IncrementDepth();
     foreach (var caseElement in element) {
         WriteIndent(arg.IndentDepth);
         caseElement.TryAccept(this, arg);
     }
     return false;
 }
 public override bool Visit(
         UnifiedNamespaceDefinition element, VisitorArgument arg)
 {
     // パッケージはディレクトリ構造で表現
     Writer.Write("# ");
     element.Modifiers.TryAccept(this, arg);
     Writer.Write("package");
     Writer.Write(" ");
     element.Name.TryAccept(this, arg);
     return false;
 }
 // e.g. (Int)a  or (int)(a + b)
 public override bool Visit(UnifiedCast element, VisitorArgument arg)
 {
     // ((TestCase)(test)).setName(name); などに対応するため括弧を出力
     Writer.Write("(");
     Writer.Write("(");
     element.Type.TryAccept(this, arg);
     Writer.Write(")");
     element.Expression.TryAccept(this, arg.Set(Paren));
     Writer.Write(")");
     return true;
 }
        // enum定義(UnifiedEnumDefinition)
        public override bool Visit(
				UnifiedEnumDefinition element, VisitorArgument arg)
        {
            // enum COLOR {RED, BLUE, YELLOW};
            element.Modifiers.TryAccept(this, arg);
            Writer.Write("enum ");
            element.Name.TryAccept(this, arg);
            Writer.Write(" ");
            element.Body.TryAccept(this, arg.Set(ForBlock));
            return true;
        }
 public override bool Visit(
         UnifiedParameter element, VisitorArgument arg)
 {
     element.Annotations.TryAccept(this, arg);
     element.Modifiers.TryAccept(this, arg);
     element.Names.TryAccept(this, arg.Set(CommaDelimiter));
     if (element.DefaultValue != null) {
         Writer.Write(" = ");
         element.DefaultValue.TryAccept(this, arg);
     }
     return false;
 }
        // 関数定義(UnifiedFunctionDefinition)
        public override bool Visit(
				UnifiedFunctionDefinition element, VisitorArgument arg)
        {
            // int main(int param) { ... };
            element.Modifiers.TryAccept(this, arg);
            element.Type.TryAccept(this, arg);
            Writer.Write(" ");
            element.Name.TryAccept(this, arg);
            element.Parameters.TryAccept(this, arg);
            element.Body.TryAccept(this, arg.Set(ForBlock));
            return element.Body == null;
        }
        public override bool Visit(
                UnifiedFunctionDefinition element, VisitorArgument arg)
        {
            element.Annotations.TryAccept(this, arg);
            element.Modifiers.TryAccept(this, arg);
            Writer.Write("def ");
            element.Name.TryAccept(this, arg);
            element.Parameters.TryAccept(this, arg);
            Writer.WriteLine(":");

            element.Body.TryAccept(this, arg.IncrementDepth());
            return false;
        }
 public override bool Visit(
     UnifiedTernaryExpression element, VisitorArgument arg)
 {
     var paren = GetRequiredParen(element);
     Writer.Write(paren.Item1);
     element.Condition.TryAccept(this, arg.Set(Paren));
     Writer.Write(" ? ");
     element.TrueExpression.TryAccept(this, arg.Set(Paren));
     Writer.Write(" : ");
     element.FalseExpression.TryAccept(this, arg.Set(Paren));
     Writer.Write(paren.Item2);
     return false;
 }
 public override bool Visit(
     UnifiedBinaryExpression element, VisitorArgument arg)
 {
     var paren = GetRequiredParen(element);
     Writer.Write(paren.Item1);
     element.LeftHandSide.TryAccept(this, arg.Set(Paren));
     Writer.Write(" ");
     element.Operator.TryAccept(this, arg);
     Writer.Write(" ");
     element.RightHandSide.TryAccept(this, arg.Set(Paren));
     Writer.Write(paren.Item2);
     return false;
 }
 //配列orオブジェクトのインスタンス化式
 public override bool Visit(UnifiedNew element, VisitorArgument arg)
 {
     //配列 : e.g. var a = [1, 2, 3] の [1, 2, 3];
     if (element.InitialValue != null) {
         element.InitialValue.TryAccept(this, arg.Set(Brace));
         return true;
     }
     //オブジェクト : e.g. var a = new X();
     Writer.Write("new ");
     element.Target.TryAccept(this, arg);
     element.Arguments.TryAccept(this, arg.Set(Paren));
     return true;
 }
 public override bool Visit(
     UnifiedFunctionDefinition element, VisitorArgument arg)
 {
     element.Annotations.TryAccept(this, arg);
     element.Modifiers.TryAccept(this, arg);
     element.Type.TryAccept(this, arg);
     Writer.Write(" ");
     element.Name.TryAccept(this, arg);
     element.GenericParameters.TryAccept(this, arg);
     element.Parameters.TryAccept(this, arg);
     element.Throws.TryAccept(this, arg);
     element.Body.TryAccept(this, arg.Set(ForBlock));
     return element.Body == null;
 }
 // If文(UnifiedIf)
 public override bool Visit(UnifiedIf element, VisitorArgument arg)
 {
     Writer.Write("if (");
     element.Condition.TryAccept(this, arg);
     Writer.Write(")");
     element.Body.TryAccept(this, arg.Set(ForBlock));
     if (element.ElseBody != null) {
         Writer.WriteLine(); //if(cond){ }の後の改行
         WriteIndent(arg);
         Writer.Write("else");
         element.ElseBody.TryAccept(this, arg.Set(ForBlock));
     }
     return false;
 }
 //関数呼び出し
 public override bool Visit(UnifiedCall element, VisitorArgument arg)
 {
     //JavaScriptではTypeArgumentsが存在しない
     var prop = element.Function as UnifiedProperty;
     //呼び出し式がプロパティの場合
     if (prop != null) {
         prop.Owner.TryAccept(this, arg);
         Writer.Write(prop.Delimiter);
         prop.Name.TryAccept(this, arg);
     } else {
         element.Function.TryAccept(this, arg);
     }
     element.Arguments.TryAccept(this, arg.Set(Paren));
     return true;
 }
        public override bool Visit(
                UnifiedSet<UnifiedCatch> element, VisitorArgument arg)
        {
            //TODO VisitCollection()に置き換えられるか確認

            Writer.Write(arg.Decoration.MostLeft);
            var delimiter = "";
            foreach (var e in element) {
                Writer.Write(delimiter);
                e.TryAccept(this, arg);
                delimiter = arg.Decoration.Delimiter;
            }
            Writer.Write(arg.Decoration.MostRight);
            return false;
        }
        // 関数呼び出し(UnifiedCall)
        public override bool Visit(UnifiedCall element, VisitorArgument arg)
        {
            var prop = element.Function as UnifiedProperty;

            // TODO これに該当するケースがあるか調べる
            if (prop != null) {
                prop.Owner.TryAccept(this, arg);
                Writer.Write(prop.Delimiter);
                prop.Name.TryAccept(this, arg);
            } else {
                element.Function.TryAccept(this, arg);
            }
            element.Arguments.TryAccept(this, arg.Set(Paren));
            return true;
        }