Update how or terms are handled

wip/source-generators
copygirl 12 months ago
parent 357e8b4bfa
commit c9a986f9bf
  1. 24
      src/gaemstone.SourceGen/ModuleGenerator.cs
  2. 21
      src/gaemstone.SourceGen/Structure/ParameterInfo.cs

@ -209,8 +209,10 @@ public class ModuleGenerator
sb.AppendLine("\t\t\t\tnew(");
foreach (var p in m.Parameters)
if (p.HasTerm) {
// TODO: Throw error if multiple Or terms appear next to each other.
foreach (var term in p.TermTypes) {
for (var i = 0; i < p.TermTypes.Count; i++) {
var term = p.TermTypes[i];
var isLastTerm = (i == p.TermTypes.Count - 1);
sb.Append($"\t\t\t\t\tnew Term(");
switch (term) {
case ITypeSymbol type:
@ -225,14 +227,17 @@ public class ModuleGenerator
$"Unexpected term type {term.GetType()}");
}
sb.Append(')');
if (p.Source != null) {
sb.Append("{ Source = ");
AppendTypeEntity(sb, module, p.Source);
sb.Append(" }");
}
// The last term in a group of OR terms must not have the TermOperKind.Or set.
if (p.IsOr && !isLastTerm) sb.Append(".Or");
sb.Append(p.Kind switch {
ParameterKind.Or => ".Or",
ParameterKind.HasOr => ".Or.None",
ParameterKind.Has => ".None",
ParameterKind.Not => ".None.Not",
ParameterKind.Ref => ".InOut",
@ -240,7 +245,9 @@ public class ModuleGenerator
_ when !p.IsValueType => ".InOut", // Reference types always imply writability.
_ => ".In",
});
if (p.IsNullable) sb.Append(".Optional");
sb.AppendLine(",");
}
}
@ -317,6 +324,9 @@ public class ModuleGenerator
if (method.IsGeneric) sb.Append("<T>");
sb.Append($"(");
foreach (var param in method.Parameters) {
// TODO: Support [Or<...>]
if (param.IsOr && (param.Kind != ParameterKind.Has))
throw new NotSupportedException($"Or<...> parameter not yet supported");
switch (param.Kind) {
case ParameterKind.Unique:
sb.Append(param.UniqueReplacement);
@ -338,13 +348,8 @@ public class ModuleGenerator
case ParameterKind.Has:
case ParameterKind.Not:
case ParameterKind.HasOr:
sb.Append("default");
break;
case ParameterKind.Or:
throw new NotSupportedException(
$"ParameterKind {param.Kind} not supported");
}
sb.Append(", ");
}
@ -363,6 +368,7 @@ public class ModuleGenerator
StringBuilder sb, ModuleEntityInfo module,
ITypeSymbol type)
{
// TODO: Cache entity lookup.
var found = module.Children.Where(c => !c.IsErrored)
.Any(c => SymbolEqualityComparer.Default.Equals(c.Symbol, type));
sb.Append(found ? $"_{type.Name}_Entity"

@ -35,9 +35,10 @@ public class ParameterInfo : BaseInfo
public IReadOnlyList<object> TermTypes { get; } // Either ITypeSymbol or Pair for relationships.
public ITypeSymbol? FieldType { get; }
public ParameterKind Kind { get; }
public bool IsOr { get; }
public bool HasTerm => (Kind != ParameterKind.Unique);
public bool HasField => HasTerm && !(Kind is ParameterKind.Has or ParameterKind.Not or ParameterKind.HasOr);
public bool HasField => HasTerm && !(Kind is ParameterKind.Has or ParameterKind.Not);
public ParameterInfo(ISymbol symbol)
: base(symbol)
@ -49,15 +50,16 @@ public class ParameterInfo : BaseInfo
var typeFullName = Symbol.Type.GetFullName(FullNameStyle.Metadata);
if (UniqueParameters.TryGetValue(typeFullName, out var replacement))
{
IsOr = false;
Kind = ParameterKind.Unique;
TermTypes = Array.Empty<ITypeSymbol>();
UniqueReplacement = replacement;
}
else
{
IsOr = typeFullName.StartsWith("gaemstone.ECS.Or");
var isHas = typeFullName.StartsWith("gaemstone.ECS.Has");
var isNot = typeFullName.StartsWith("gaemstone.ECS.Not");
var isOr = typeFullName.StartsWith("gaemstone.ECS.Or");
if (IsGeneric)
{
@ -71,7 +73,7 @@ public class ParameterInfo : BaseInfo
{
TermTypes = argType.TypeArguments.ToImmutableList();
FieldType = null;
isOr = true;
IsOr = true;
}
else if ((isHas || isNot) && (args is [ INamedTypeSymbol relation, INamedTypeSymbol target ]))
{
@ -90,11 +92,9 @@ public class ParameterInfo : BaseInfo
FieldType = Symbol.Type;
}
Kind = (isHas && isOr) ? ParameterKind.HasOr
: isHas ? ParameterKind.Has
: isOr ? ParameterKind.Or
: isNot ? ParameterKind.Not
: IsNullable ? ParameterKind.Nullable
Kind = isHas ? ParameterKind.Has
: isNot ? ParameterKind.Not
: IsNullable ? ParameterKind.Nullable
: Symbol.RefKind switch {
RefKind.In => ParameterKind.In,
RefKind.Out => ParameterKind.Out,
@ -141,8 +141,7 @@ public class ParameterInfo : BaseInfo
}
else
{
var isSpecial = Kind is ParameterKind.Has or ParameterKind.HasOr
or ParameterKind.Or or ParameterKind.Not;
var isSpecial = IsOr || (Kind is ParameterKind.Has or ParameterKind.Not);
if (isSpecial && IsByRef) yield return Diagnostic.Create(
Descriptors.SpecialMustNotBeByRef, Location);
if (isSpecial && IsNullable) yield return Diagnostic.Create(
@ -202,8 +201,6 @@ public enum ParameterKind
Ref, // Pass by reference (read/write)
Has, // Required present (no read/write)
Not, // Required missing (no read/write)
Or, // Only one of multiple terms is required
HasOr, // Both Has and Or at the same time
}
// public enum TermKind

Loading…
Cancel
Save