Skip to content

Commit

Permalink
Lots more source generation
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse committed Feb 16, 2024
1 parent 2bb00f7 commit c0ced19
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 27 deletions.
81 changes: 65 additions & 16 deletions sourcegeneration/MonologueSourceGenerator/LogGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

namespace Monologue.SourceGenerator;

internal record ClassData(ImmutableArray<string> LoggedItems, string Name, string ClassDeclaration, string? Namespace);
internal record LogData(string? PreComputed, string? GetOperation, string? Path, string? Type);

internal record ClassData(ImmutableArray<LogData> LoggedItems, string Name, string ClassDeclaration, string? Namespace);

[Generator]
public class LogGenerator : IIncrementalGenerator
Expand All @@ -27,7 +29,7 @@ public class LogGenerator : IIncrementalGenerator

var classMembers = classSymbol.GetMembers();

var loggableMembers = ImmutableArray.CreateBuilder<string>(classMembers.Length);
var loggableMembers = ImmutableArray.CreateBuilder<LogData>(classMembers.Length);

foreach (var member in classMembers)
{
Expand Down Expand Up @@ -82,17 +84,7 @@ public class LogGenerator : IIncrementalGenerator
throw new InvalidOperationException("Field is not loggable");
}

string fullOperation;

if (logType.AllInterfaces.Where(x => x.ToDisplayString() == "Monologue.ILogged").Any())
{
fullOperation = $"{getOperation}.UpdateMonologue($\"{{path}}/{defaultPathName}\", logger);";
}
else
{
// TODO the rest of the types
fullOperation = "";
}
var fullOperation = ComputeOperation(logType, getOperation, defaultPathName);
token.ThrowIfCancellationRequested();
loggableMembers.Add(fullOperation);
break;
Expand All @@ -103,6 +95,37 @@ public class LogGenerator : IIncrementalGenerator
return new ClassData(loggableMembers.ToImmutable(), classSymbol.Name, typeBuilder.ToString(), ns);
}

private static LogData ComputeOperation(ITypeSymbol logType, string getOp, string path)
{
if (logType.GetAttributes().Where(x => x.AttributeClass?.ToDisplayString() == "Monologue.GenerateLogAttribute").Any())
{
return new($"{getOp}.UpdateMonologue($\"{{path}}/{path}\", logger);", null, null, null);
}
if (logType.AllInterfaces.Where(x => x.ToDisplayString() == "Monologue.ILogged").Any())
{
return new($"{getOp}.UpdateMonologue($\"{{path}}/{path}\", logger);", null, null, null);
//return $"{getOp}.UpdateMonologue($\"{{path}}/{path}\", logger);";
}
var fullName = logType.ToDisplayString();
var structName = $"WPIUtil.Serialization.Struct.IStructSerializable<{fullName}>";
var protobufName = $"WPIUtil.Serialization.Protobuf.IProtobufSerializable<{fullName}>";
foreach (var inf in logType.AllInterfaces)
{
var interfaceName = inf.ToDisplayString();
// For now prefer struct
if (interfaceName == structName)
{
return new($"logger.LogStruct($\"{{path}}/{path}\", LogType.Nt, {getOp});", null, null, null);
}
else if (interfaceName == protobufName)
{
return new($"logger.LogProto($\"{{path}}/{path}\", LogType.Nt, {getOp});", null, null, null);
}
}

return new(null, getOp, path, fullName);
}

public void Initialize(IncrementalGeneratorInitializationContext context)
{
var attributedTypes = context.SyntaxProvider
Expand All @@ -116,6 +139,33 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
static (spc, source) => Execute(source, spc));
}

static void ConstructCall(LogData data, StringBuilder builder)
{
if (data.PreComputed is not null) {

builder.AppendLine($" {data.PreComputed}");
return;
}

var ret = data.Type switch {
"float" => ("LogFloat", ""),
"double" => ("LogDouble", ""),
"byte" => ("LogInteger", ""),
"sbyte" => ("LogInteger", ""),
"short" => ("LogInteger", ""),
"ushort" => ("LogInteger", ""),
"int" => ("LogInteger", ""),
"uint" => ("LogInteger", ""),
"long" => ("LogInteger", ""),
"ulong" => ("LogInteger", "(long)"),
"bool" => ("LogBoolean", ""),
"char" => ("LogChar", ""),
_ => (data.Type, "")
};

builder.AppendLine($" logger.{ret.Item1}($\"{{path}}/{data.Path}\", LogType.Nt, {ret.Item2}{data.GetOperation});");
}

static void Execute(ClassData? classData, SourceProductionContext context)
{
if (classData is { } value)
Expand All @@ -126,14 +176,13 @@ static void Execute(ClassData? classData, SourceProductionContext context)
builder.AppendLine($"namespace {value.Namespace};");
builder.AppendLine();

builder.Append(value.ClassDeclaration);
builder.AppendLine(" : ILogged");
builder.AppendLine(value.ClassDeclaration);
builder.AppendLine("{");
builder.AppendLine(" public void UpdateMonologue(string path, Monologue.Monologuer logger)");
builder.AppendLine(" {");
foreach (var call in value.LoggedItems)
{
builder.AppendLine($" {call}");
ConstructCall(call, builder);
}
builder.AppendLine(" }");
builder.AppendLine("}");
Expand Down
20 changes: 20 additions & 0 deletions src/thirdparty/Monologue/Monologuer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static void UpdateAll(ILogged logged)

private readonly DataLog log = null!;

private readonly Dictionary<string, (IIntegerPublisher? topic, IntegerLogEntry? logEntry)> integerLogs = [];
private readonly Dictionary<string, (IBooleanPublisher? topic, BooleanLogEntry? logEntry)> booleanLogs = [];
private readonly Dictionary<string, (object? topic, object? logEntry)> structLogs = [];

Expand All @@ -51,6 +52,25 @@ public void LogBoolean(string path, LogType logType, bool value)
}
}

public void LogInteger(string path, LogType logType, long value)
{
if (logType == LogType.None)
{
return;
}
ref var logs = ref CollectionsMarshal.GetValueRefOrAddDefault(integerLogs, path, out _);
if (logType.HasFlag(LogType.Nt))
{
logs.topic ??= NetworkTableInstance.Default.GetIntegerTopic(path).Publish(PubSubOptions.None);
logs.topic.Set(value);
}
if (logType.HasFlag(LogType.File))
{
logs.logEntry ??= new IntegerLogEntry(log, path);
logs.logEntry.Append(value);
}
}

public void LogStruct<T>(string path, LogType logType, in T value) where T : IStructSerializable<T>
{
if (logType == LogType.None)
Expand Down
23 changes: 12 additions & 11 deletions test/monologue.test/TestTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ public partial class GenerateGenericClass<T>
{
[Log]
public int Variable { get; }
[Log]
public Int32 Variable2 { get; }
}

[GenerateLog]
Expand Down Expand Up @@ -103,26 +105,25 @@ public partial class TestRootClass
public TestStruct TS { get; } = new();
}

public class TestClass : ILogged
[GenerateLog]
public partial class TestClass
{
[Log]
public TestStruct TS { get; } = new();

public void UpdateMonologue(string path, Monologuer logger)
{
TS.UpdateMonologue($"{path}/TS", logger);
}
}

public struct TestStruct : ILogged
[GenerateLog]
public partial struct TestStruct
{
[Log]
public Rotation2d Rotation { get; set; } = new();

public TestStruct() { }
}

public readonly void UpdateMonologue(string path, Monologuer logger)
{
logger.LogStruct($"{path}/Rotation", LogType.Nt, Rotation);
}
[GenerateLog]
public partial class TestDemo
{
[Log]
public Rotation2d Rotation { get; set; } = new();
}

0 comments on commit c0ced19

Please sign in to comment.