Skip to content

Commit

Permalink
Finish the green factory generator.
Browse files Browse the repository at this point in the history
  • Loading branch information
GGG-KILLER committed Jan 29, 2024
1 parent 9cd6da5 commit f964c66
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public int SlotCount
{
var node = this.GetSlot(index);
Debug.Assert((object)node != null)
return node;
return node!;
}

protected virtual int GetSlotCount() => _slotCount;
Expand Down Expand Up @@ -177,6 +177,16 @@ internal BinaryOperationExpressionSample(global::Tsu.Trees.RedGreen.Sample.Sampl

public override global::Tsu.Trees.RedGreen.Sample.SampleNode CreateRed(global::Tsu.Trees.RedGreen.Sample.SampleNode? parent) =>
new global::Tsu.Trees.RedGreen.Sample.BinaryOperationExpressionSample(this, parent);

public global::Tsu.Trees.RedGreen.Sample.Internal.BinaryOperationExpressionSample Update(global::Tsu.Trees.RedGreen.Sample.SampleKind kind, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample left, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample right)
{
if (kind != this.Kind && left != this.Left && right != this.Right)
{
return global::Tsu.Trees.RedGreen.Sample.Internal.SampleFactory.BinaryOperationExpression(kind, left, right);
}

return this;
}
}

partial class FunctionCallExpressionSample : global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample
Expand Down Expand Up @@ -215,5 +225,71 @@ internal FunctionCallExpressionSample(global::Tsu.Trees.RedGreen.Sample.SampleKi
return this;
}
}

internal static class SampleFactory
{
public static global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample IdentifierExpression(string name)
{
#if DEBUG
if ((object)name == null) throw new global::System.ArgumentNullException(nameof(name))
#endif // DEBUG

return new global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample(
global::Tsu.Trees.RedGreen.Sample.SampleKind.IdentifierExpression, name);
}

public static global::Tsu.Trees.RedGreen.Sample.Internal.NumericalLiteralExpressionSample NumericalLiteralExpression(double value)
{
#if DEBUG
#endif // DEBUG

return new global::Tsu.Trees.RedGreen.Sample.Internal.NumericalLiteralExpressionSample(
global::Tsu.Trees.RedGreen.Sample.SampleKind.NumericalLiteralExpression, value);
}

public static global::Tsu.Trees.RedGreen.Sample.Internal.BinaryOperationExpressionSample BinaryOperationExpression(global::Tsu.Trees.RedGreen.Sample.SampleKind kind, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample left, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample right)
{
#if DEBUG
if ((object)left == null) throw new global::System.ArgumentNullException(nameof(left))
if ((object)right == null) throw new global::System.ArgumentNullException(nameof(right))
switch (kind)
{
case Tsu.Trees.RedGreen.Sample.SampleKind.AdditionExpression:
case Tsu.Trees.RedGreen.Sample.SampleKind.DivisionExpression:
case Tsu.Trees.RedGreen.Sample.SampleKind.MultiplicationExpression:
case Tsu.Trees.RedGreen.Sample.SampleKind.SubtractionExpression:
break;
default:
throw new global::System.ArgumentException("Kind not accepted for this node.", nameof(kind));
}
#endif // DEBUG

return new global::Tsu.Trees.RedGreen.Sample.Internal.BinaryOperationExpressionSample(
kind, left, right);
}

public static global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample FunctionCallExpression(global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample identifier, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample firstArg)
{
#if DEBUG
if ((object)identifier == null) throw new global::System.ArgumentNullException(nameof(identifier))
if ((object)firstArg == null) throw new global::System.ArgumentNullException(nameof(firstArg))
#endif // DEBUG

return new global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample(
global::Tsu.Trees.RedGreen.Sample.SampleKind.FunctionCallExpression, identifier, firstArg);
}

public static global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample FunctionCallExpression(global::Tsu.Trees.RedGreen.Sample.Internal.IdentifierExpressionSample identifier, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample firstArg, global::Tsu.Trees.RedGreen.Sample.Internal.ExpressionSample secondArg)
{
#if DEBUG
if ((object)identifier == null) throw new global::System.ArgumentNullException(nameof(identifier))
if ((object)firstArg == null) throw new global::System.ArgumentNullException(nameof(firstArg))
if ((object)secondArg == null) throw new global::System.ArgumentNullException(nameof(secondArg))
#endif // DEBUG

return new global::Tsu.Trees.RedGreen.Sample.Internal.FunctionCallExpressionSample(
global::Tsu.Trees.RedGreen.Sample.SampleKind.FunctionCallExpression, identifier, firstArg, secondArg);
}
}
}

102 changes: 101 additions & 1 deletion Tsu.Trees.RedGreen/sourcegen/GreenTreeWriter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.CodeDom.Compiler;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Tsu.Trees.RedGreen.SourceGenerator.Model;

namespace Tsu.Trees.RedGreen.SourceGenerator;
Expand Down Expand Up @@ -51,6 +52,9 @@ public static void RegisterGreenOutput(this IncrementalGeneratorInitializationCo
writer.WriteGreenNode(tree, node);
}

writer.WriteLineNoTabs("");
writer.WriteGreenFactory(tree);

writer.Indent--;
writer.WriteLine('}');
writer.WriteLineNoTabs("");
Expand Down Expand Up @@ -395,8 +399,104 @@ private static void WriteGreenConstructor(this IndentedTextWriter writer, Node n
writer.WriteLine('}');
}

public static void WriteGreenFactory(this IncrementalGeneratorInitializationContext context, IncrementalValuesProvider<Tree> trees)
public static void WriteGreenFactory(this IndentedTextWriter writer, Tree tree)
{
writer.WriteLine("{0} static class {1}Factory", tree.GreenBase.DeclaredAccessibility.ToCSharpString(), tree.Suffix);
writer.WriteLine('{');
writer.Indent++;
{
var queue = new Queue<Node>();
foreach (var desc in tree.Root.Descendants)
queue.Enqueue(desc);

var first = true;
while (queue.Count > 0)
{
var node = queue.Dequeue();
if (node.Descendants.Any())
{
foreach (var desc in node.Descendants)
queue.Enqueue(desc);
}
else
{
if (!first) writer.WriteLineNoTabs("");
first = false;
writer.WriteGreenFactoryMethods(tree, node);
}
}
}
writer.Indent--;
writer.WriteLine('}');
}

private static void WriteGreenFactoryMethods(this IndentedTextWriter writer, Tree tree, Node node)
{
if (node.RequiredComponents.Any(x => x.IsOptional))
{
var nonOptionalRequired = node.RequiredComponents.Where(x => !x.IsOptional);
writeMethod(writer, tree, node, nonOptionalRequired);
writer.WriteLineNoTabs("");
}
writeMethod(writer, tree, node, node.RequiredComponents);

static void writeMethod(IndentedTextWriter writer, Tree tree, Node node, IEnumerable<Component> components)
{
writer.Write("public static {0} {1}(", node.TypeSymbol.ToCSharpString(), node.TypeSymbol.Name.WithoutSuffix(tree.Suffix));
var first = true;
foreach (var component in components)
{
if (!first) writer.Write(", ");
first = false;
writer.Write("{0} {1}", component.Type.ToCSharpString(), component.ParameterName);
}
writer.WriteLine(')');
writer.WriteLine('{');
writer.Indent++;
{
writer.WriteLineNoTabs("#if DEBUG");
foreach (var component in components.Where(x => !x.Type.IsValueType))
writer.WriteLine("if ((object){0} == null) throw new global::System.ArgumentNullException(nameof({0}))", component.ParameterName);
if (node.Kinds.Length != 1)
{
writer.WriteLine("switch (kind)");
writer.WriteLine('{');
writer.Indent++;
{
foreach (var kind in node.Kinds)
writer.WriteLine("case {0}:", kind.ToCSharpString());
writer.Indent++;
writer.WriteLine("break;");
writer.Indent--;
writer.WriteLine("default:");
writer.Indent++;
writer.WriteLine("throw new global::System.ArgumentException(\"Kind not accepted for this node.\", nameof(kind));");
writer.Indent--;
}
writer.Indent--;
writer.WriteLine('}');
}
writer.WriteLineNoTabs("#endif // DEBUG");
writer.WriteLineNoTabs("");

writer.WriteLine("return new {0}(", node.TypeSymbol.ToCSharpString());
first = true;
if (node.Kinds.Length == 1)
{
first = false;
writer.Write("global::{0}", node.Kinds[0].ToCSharpString());
}
foreach (var component in components)
{
if (!first) writer.Write(", ");
first = false;
writer.Write(component.ParameterName);
}
writer.WriteLine(");");
}
writer.Indent--;
writer.WriteLine('}');
}
}

private static string WithoutSuffix(this string name, string suffix)
Expand Down

0 comments on commit f964c66

Please sign in to comment.