diff --git a/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.GreenRoot.g.cs b/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.GreenRoot.g.cs
new file mode 100644
index 0000000..519bafd
--- /dev/null
+++ b/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.GreenRoot.g.cs
@@ -0,0 +1,98 @@
+//
+
+#nullable enable
+
+namespace Tsu.Trees.RedGreen.Sample.Internal
+{
+ abstract partial class GreenNode
+ {
+ private readonly global::Tsu.Trees.RedGreen.Sample.SampleKind _kind;
+ private byte _slotCount;
+
+ protected GreenNode(global::Tsu.Trees.RedGreen.Sample.SampleKind kind)
+ {
+ this._kind = kind;
+ }
+
+ public global::Tsu.Trees.RedGreen.Sample.SampleKind Kind => this._kind;
+
+ public int SlotCount
+ {
+ get
+ {
+ int count = this._slotCount;
+ if (count == byte.MaxValue)
+ count = this.GetSlotCount();
+ return count;
+ }
+ protected set => _slotCount = (byte) value;
+ }
+
+ public abstract global::Tsu.Trees.RedGreen.Sample.Internal.GreenNode? GetSlot(int index);
+
+ public global::Tsu.Trees.RedGreen.Sample.Internal.GreenNode GetRequiredSlot(int index)
+ {
+ var node = this.GetSlot(index);
+ Debug.Assert(node != null);
+ return node!;
+ }
+
+ protected virtual int GetSlotCount() => _slotCount;
+
+ public global::System.Collections.Generic.IEnumerable ChildNodes()
+ {
+ var count = this.SlotCount;
+ for (var index = 0; index < count; index++)
+ yield return this.GetRequiredSlot(index);
+ }
+
+ public global::System.Collections.Generic.IEnumerable EnumerateDescendants()
+ {
+ var stack = new Stack(24);
+ stack.Push(this);
+
+ while (stack.Count > 0)
+ {
+ var current = stack.Pop();
+
+ yield return current;
+
+ foreach (var child in current.ChildNodes().Reverse())
+ {
+ stack.Push(child);
+ }
+ }
+ }
+
+ public virtual bool IsEquivalentTo([global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] global::Tsu.Trees.RedGreen.Sample.Internal.GreenNode? other)
+ {
+ if (this == other) return true;
+ if (other == null) return false;
+ if (this.Kind != other.Kind) return false;
+
+ var n = this.SlotCount;
+ if (n != other.SlotCount) return false;
+
+ for (int i = 0; i < n; i++)
+ {
+ var thisChild = this.GetSlot(i);
+ var otherChild = other.GetSlot(i);
+ if (thisChild != null && otherChild != null && !thisChild.IsEquivalentTo(otherChild))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public global::Tsu.Trees.RedGreen.Sample.SampleNode CreateRed() => this.CreateRed(null);
+ public abstract global::Tsu.Trees.RedGreen.Sample.SampleNode CreateRed(global::Tsu.Trees.RedGreen.Sample.SampleNode? parent);
+
+ public abstract void Accept(global::Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor);
+ public abstract TResult? Accept(global::Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor);
+ public abstract TResult? Accept(global::Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor, T1 arg1);
+ public abstract TResult? Accept(global::Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor, T1 arg1, T2 arg2);
+ public abstract TResult? Accept(global::Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor, T1 arg1, T2 arg2, T3 arg3);
+ }
+}
\ No newline at end of file
diff --git a/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.g.cs b/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.g.cs
index 8a3556e..59ada0d 100644
--- a/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.g.cs
+++ b/Tsu.Trees.RedGreen/sample/Generated/Tsu.Trees.RedGreen/Tsu.Trees.RedGreen.SourceGenerator.Generator/Sample.Internal.g.cs
@@ -8,96 +8,6 @@
namespace Tsu.Trees.RedGreen.Sample.Internal
{
- abstract partial class GreenNode
- {
- private readonly global::Tsu.Trees.RedGreen.Sample.SampleKind _kind;
- private byte _slotCount;
-
- protected GreenNode(global::Tsu.Trees.RedGreen.Sample.SampleKind kind)
- {
- this._kind = kind;
- }
-
- public global::Tsu.Trees.RedGreen.Sample.SampleKind Kind => this._kind;
-
- public int SlotCount
- {
- get
- {
- int count = this._slotCount;
- if (count == byte.MaxValue)
- count = this.GetSlotCount();
- return count;
- }
- protected set => _slotCount = (byte) value;
- }
-
- public abstract global::Tsu.Trees.RedGreen.Sample.Internal.GreenNode? GetSlot(int index);
-
- public global::Tsu.Trees.RedGreen.Sample.Internal.GreenNode GetRequiredSlot(int index)
- {
- var node = this.GetSlot(index);
- Debug.Assert(node != null);
- return node!;
- }
-
- protected virtual int GetSlotCount() => _slotCount;
-
- public global::System.Collections.Generic.IEnumerable ChildNodes()
- {
- var count = this.SlotCount;
- for (var index = 0; index < count; index++)
- yield return this.GetRequiredSlot(index);
- }
-
- public global::System.Collections.Generic.IEnumerable EnumerateDescendants()
- {
- var stack = new Stack(24);
- stack.Push(this);
-
- while (stack.Count > 0)
- {
- var current = stack.Pop();
-
- yield return current;
-
- foreach (var child in current.ChildNodes().Reverse())
- {
- stack.Push(child);
- }
- }
- }
-
- public virtual bool IsEquivalentTo([NotNullWhen(true)] global::Tsu.Trees.RedGreen.Sample.Internal.GreenNode? other)
- {
- if (this == other) return true;
- if (other == null) return false;
- if (this.Kind != other.Kind) return false;
-
- var n = this.SlotCount;
- if (n != other.SlotCount) return false;
-
- for (int i = 0; i < n; i++)
- {
- var thisChild = this.GetSlot(i);
- var otherChild = other.GetSlot(i);
- if (thisChild != null && otherChild != null && !thisChild.IsEquivalentTo(otherChild))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public global::Tsu.Trees.RedGreen.Sample.SampleNode CreateRed() => this.CreateRed(null);
- public abstract global::Tsu.Trees.RedGreen.Sample.SampleNode CreateRed(global::Tsu.Trees.RedGreen.Sample.SampleNode? parent);
- public abstract void Accept(Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor);
- public abstract TResult? Accept(Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor);
- public abstract TResult? Accept(Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor, T1 arg1);
- public abstract TResult? Accept(Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor, T1 arg1, T2 arg2);
- public abstract TResult? Accept(Tsu.Trees.RedGreen.Sample.Internal.SampleVisitor visitor, T1 arg1, T2 arg2, T3 arg3);
- }
partial class SemicolonTokenSample : global::Tsu.Trees.RedGreen.Sample.Internal.GreenNode
{
diff --git a/Tsu.Trees.RedGreen/src/GreenTreeGenerator.cs b/Tsu.Trees.RedGreen/src/GreenTreeGenerator.cs
index c856a15..04fb071 100644
--- a/Tsu.Trees.RedGreen/src/GreenTreeGenerator.cs
+++ b/Tsu.Trees.RedGreen/src/GreenTreeGenerator.cs
@@ -53,8 +53,6 @@ public static void RegisterGreenOutput(this IncrementalGeneratorInitializationCo
writer.WriteLine('{');
writer.Indent++;
- writer.WriteGreenRoot(tree, tree.Root);
-
var queue = new Queue();
foreach (var node in tree.Root.Descendants)
queue.Enqueue(node);
@@ -98,168 +96,6 @@ public static void RegisterGreenOutput(this IncrementalGeneratorInitializationCo
});
}
- private static void WriteGreenRoot(this IndentedTextWriter writer, Tree tree, Node root)
- {
- writer.WriteLine("abstract partial class {0}", root.TypeSymbol.Name);
- writer.WriteLine('{');
- writer.Indent++;
- {
- writer.WriteLine("private readonly {0} _kind;", tree.KindEnum.ToCSharpString());
- writer.WriteLine("private byte _slotCount;");
- writer.WriteLineNoTabs("");
-
- writer.WriteGreenConstructor(root);
- writer.WriteLineNoTabs("");
-
- foreach (var component in root.Components)
- {
- writer.WriteLine("public {0} {1} => this.{2};", component.Type.ToCSharpString(), component.PropertyName, component.FieldName);
- }
- writer.WriteLineNoTabs("");
-
- #region int SlotCount
- writer.WriteLine("public int SlotCount");
- writer.WriteLine('{');
- writer.Indent++;
- {
- writer.WriteLine("get");
- writer.WriteLine('{');
- writer.Indent++;
- {
- writer.WriteLine("int count = this._slotCount;");
- writer.WriteLine("if (count == byte.MaxValue)");
- writer.Indent++;
- writer.WriteLine("count = this.GetSlotCount();");
- writer.Indent--;
- writer.WriteLine("return count;");
- }
- writer.Indent--;
- writer.WriteLine('}');
- writer.WriteLine("protected set => _slotCount = (byte) value;");
- }
- writer.Indent--;
- writer.WriteLine('}');
- writer.WriteLineNoTabs("");
- #endregion int SlotCount
-
- writer.WriteLine("public abstract {0}? GetSlot(int index);", tree.GreenBase.ToCSharpString());
- writer.WriteLineNoTabs("");
-
- #region TGreenRoot GetRequiredSlot(int index)
- writer.WriteLine("public {0} GetRequiredSlot(int index)", tree.GreenBase.ToCSharpString());
- writer.WriteLine('{');
- writer.Indent++;
- {
- writer.WriteLine("var node = this.GetSlot(index);");
- writer.WriteLine("Debug.Assert(node != null);");
- writer.WriteLine("return node!;");
- }
- writer.Indent--;
- writer.WriteLine('}');
- writer.WriteLineNoTabs("");
- #endregion TGreenRoot GetRequiredSlot(int index)
-
- writer.WriteLine("protected virtual int GetSlotCount() => _slotCount;");
- writer.WriteLineNoTabs("");
-
- #region IEnumerable ChildNodes()
- writer.WriteLine("public global::System.Collections.Generic.IEnumerable<{0}> ChildNodes()", tree.GreenBase.ToCSharpString());
- writer.WriteLine('{');
- writer.Indent++;
- {
- writer.WriteLine("var count = this.SlotCount;");
- writer.WriteLine("for (var index = 0; index < count; index++)");
- writer.Indent++;
- writer.WriteLine("yield return this.GetRequiredSlot(index);");
- writer.Indent--;
- }
- writer.Indent--;
- writer.WriteLine('}');
- writer.WriteLineNoTabs("");
- #endregion IEnumerable ChildNodes()
-
- #region IEnumerable EnumerateDescendants()
- writer.WriteLine("public global::System.Collections.Generic.IEnumerable<{0}> EnumerateDescendants()", tree.GreenBase.ToCSharpString());
- writer.WriteLine('{');
- writer.Indent++;
- {
- writer.WriteLine("var stack = new Stack<{0}>(24);", tree.GreenBase.ToCSharpString());
- writer.WriteLine("stack.Push(this);");
- writer.WriteLineNoTabs("");
- writer.WriteLine("while (stack.Count > 0)");
- writer.WriteLine('{');
- writer.Indent++;
- {
- writer.WriteLine("var current = stack.Pop();");
- writer.WriteLineNoTabs("");
- writer.WriteLine("yield return current;");
- writer.WriteLineNoTabs("");
- writer.WriteLine("foreach (var child in current.ChildNodes().Reverse())");
- writer.WriteLine('{');
- writer.Indent++;
- writer.WriteLine("stack.Push(child);");
- writer.Indent--;
- writer.WriteLine('}');
- }
- writer.Indent--;
- writer.WriteLine('}');
- }
- writer.Indent--;
- writer.WriteLine('}');
- writer.WriteLineNoTabs("");
- #endregion IEnumerable EnumerateDescendants()
-
- #region bool IsEquivalentTo(TGreenRoot? other)
- writer.WriteLine("public virtual bool IsEquivalentTo([NotNullWhen(true)] {0}? other)", tree.GreenBase.ToCSharpString());
- writer.WriteLine('{');
- writer.Indent++;
- {
- writer.WriteLine("if (this == other) return true;");
- writer.WriteLine("if (other == null) return false;");
- foreach (var extraData in root.ExtraData)
- {
- writer.WriteLine("if (this.{0} != other.{0}) return false;", extraData.PropertyName);
- }
- writer.WriteLineNoTabs("");
- writer.WriteLine("var n = this.SlotCount;");
- writer.WriteLine("if (n != other.SlotCount) return false;");
- writer.WriteLineNoTabs("");
- writer.WriteLine("for (int i = 0; i < n; i++)");
- writer.WriteLine('{');
- writer.Indent++;
- {
- writer.WriteLine("var thisChild = this.GetSlot(i);");
- writer.WriteLine("var otherChild = other.GetSlot(i);");
- writer.WriteLine("if (thisChild != null && otherChild != null && !thisChild.IsEquivalentTo(otherChild))");
- writer.WriteLine('{');
- writer.Indent++;
- writer.WriteLine("return false;");
- writer.Indent--;
- writer.WriteLine('}');
- }
- writer.Indent--;
- writer.WriteLine('}');
- writer.WriteLineNoTabs("");
- writer.WriteLine("return true;");
- }
- writer.Indent--;
- writer.WriteLine('}');
- writer.WriteLineNoTabs("");
- #endregion bool IsEquivalentTo(TGreenRoot? other)
-
- #region TRedRoot CreateRed()
- writer.WriteLine("public {0} CreateRed() => this.CreateRed(null);", tree.RedBase.ToCSharpString());
- writer.WriteLine("public abstract {0} CreateRed({0}? parent);", tree.RedBase.ToCSharpString());
- #endregion TRedRoot CreateRed()
-
- #region T Accept(Visitor visitor)
- writer.WriteAbstractAcceptMethods(tree, tree.GreenBase.ContainingNamespace);
- #endregion T Accept(Visitor visitor)
- }
- writer.Indent--;
- writer.WriteLine('}');
- }
-
private static void WriteGreenNode(this IndentedTextWriter writer, Tree tree, Node node)
{
if (node.TypeSymbol.IsAbstract)
diff --git a/Tsu.Trees.RedGreen/src/Templates/Internal/GreenRoot.sbn-cs b/Tsu.Trees.RedGreen/src/Templates/Internal/GreenRoot.sbn-cs
new file mode 100644
index 0000000..ae40355
--- /dev/null
+++ b/Tsu.Trees.RedGreen/src/Templates/Internal/GreenRoot.sbn-cs
@@ -0,0 +1,114 @@
+//
+
+#nullable enable
+
+namespace {{ green_base.namespace_no_global }}
+{
+ abstract partial class {{ green_base.name }}
+ {
+{{~ for component in root.components ~}}
+ private readonly {{ component.type.csharp }} {{ component.field_name }};
+{{~ end ~}}
+ private byte _slotCount;
+
+ protected {{ green_base.name }}({{- for component in root.components -}}
+ {{ if !for.first }}, {{ end }}{{ component.type.csharp }} {{ component.parameter_name }}
+{{- end -}})
+ {
+{{~ for component in root.components ~}}
+ this.{{ component.field_name }} = {{ component.parameter_name }};
+{{~ end ~}}
+ }
+
+{{ for component in root.components ~}}
+ public {{ component.type.csharp }} {{ component.property_name }} => this.{{ component.field_name }};
+{{~ end ~}}
+
+ public int SlotCount
+ {
+ get
+ {
+ int count = this._slotCount;
+ if (count == byte.MaxValue)
+ count = this.GetSlotCount();
+ return count;
+ }
+ protected set => _slotCount = (byte) value;
+ }
+
+ public abstract {{ green_base.csharp_no_nullable }}? GetSlot(int index);
+
+ public {{ green_base.csharp_no_nullable }} GetRequiredSlot(int index)
+ {
+ var node = this.GetSlot(index);
+ Debug.Assert(node != null);
+ return node!;
+ }
+
+ protected virtual int GetSlotCount() => _slotCount;
+
+ public global::System.Collections.Generic.IEnumerable<{{ green_base.csharp_no_nullable }}> ChildNodes()
+ {
+ var count = this.SlotCount;
+ for (var index = 0; index < count; index++)
+ yield return this.GetRequiredSlot(index);
+ }
+
+ public global::System.Collections.Generic.IEnumerable<{{ green_base.csharp_no_nullable }}> EnumerateDescendants()
+ {
+ var stack = new Stack<{{ green_base.csharp_no_nullable }}>(24);
+ stack.Push(this);
+
+ while (stack.Count > 0)
+ {
+ var current = stack.Pop();
+
+ yield return current;
+
+ foreach (var child in current.ChildNodes().Reverse())
+ {
+ stack.Push(child);
+ }
+ }
+ }
+
+ public virtual bool IsEquivalentTo([global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] {{ green_base.csharp_no_nullable }}? other)
+ {
+ if (this == other) return true;
+ if (other == null) return false;
+{{~ for component in root.components ~}}
+ if (this.{{ component.property_name }} != other.{{ component.property_name }}) return false;
+{{~ end ~}}
+
+ var n = this.SlotCount;
+ if (n != other.SlotCount) return false;
+
+ for (int i = 0; i < n; i++)
+ {
+ var thisChild = this.GetSlot(i);
+ var otherChild = other.GetSlot(i);
+ if (thisChild != null && otherChild != null && !thisChild.IsEquivalentTo(otherChild))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public {{ red_base.csharp_no_nullable }} CreateRed() => this.CreateRed(null);
+ public abstract {{ red_base.csharp_no_nullable }} CreateRed({{ red_base.csharp_no_nullable }}? parent);
+
+{{~ if create_visitors || create_walker ~}}
+ public abstract void Accept({{ green_base.namespace }}.{{ suffix }}Visitor visitor);
+{{~ end ~}}
+{{~ if create_visitors || create_rewriter ~}}
+ public abstract TResult? Accept({{ green_base.namespace }}.{{ suffix }}Visitor visitor);
+{{~ end ~}}
+{{~ if create_visitors ~}}
+ public abstract TResult? Accept({{ green_base.namespace }}.{{ suffix }}Visitor visitor, T1 arg1);
+ public abstract TResult? Accept({{ green_base.namespace }}.{{ suffix }}Visitor visitor, T1 arg1, T2 arg2);
+ public abstract TResult? Accept({{ green_base.namespace }}.{{ suffix }}Visitor visitor, T1 arg1, T2 arg2, T3 arg3);
+{{~ end ~}}
+ }
+}
\ No newline at end of file