139 lines
5.3 KiB
C#
139 lines
5.3 KiB
C#
//-----------------------------------------------------------------------
|
|
// -----------------------------------------------------------------------
|
|
// file="ManagedParameterPlanner"
|
|
// Project: StgSharp
|
|
// Copyright (c) Nitload.
|
|
// SPDX-License-Identifier: MIT
|
|
// -----------------------------------------------------------------------
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace GenerateGL.CodeGen
|
|
{
|
|
internal enum ManagedParameterKind
|
|
{
|
|
|
|
Value,
|
|
RawPointer,
|
|
ReadOnlySpan,
|
|
Span,
|
|
Out
|
|
|
|
}
|
|
|
|
internal sealed record ManagedParameterPlan(
|
|
GlParam Source,
|
|
string PublicType,
|
|
ManagedParameterKind Kind,
|
|
string? ElementType
|
|
)
|
|
{
|
|
|
|
public bool IsSpan => Kind is ManagedParameterKind.ReadOnlySpan or
|
|
ManagedParameterKind.Span;
|
|
|
|
}
|
|
|
|
internal sealed class ManagedCommandPlan
|
|
{
|
|
|
|
private readonly Dictionary<string, ManagedParameterPlan> _allParameters;
|
|
private readonly Dictionary<string, string> _derivedLengthSources;
|
|
|
|
private ManagedCommandPlan(
|
|
IReadOnlyList<ManagedParameterPlan> publicParameters,
|
|
Dictionary<string, ManagedParameterPlan> allParameters,
|
|
Dictionary<string, string> derivedLengthSources
|
|
)
|
|
{
|
|
PublicParameters = publicParameters;
|
|
_allParameters = allParameters;
|
|
_derivedLengthSources = derivedLengthSources;
|
|
}
|
|
|
|
public IReadOnlyList<ManagedParameterPlan> PublicParameters { get; }
|
|
|
|
public IReadOnlyDictionary<string, string> DerivedLengthSources =>
|
|
_derivedLengthSources;
|
|
|
|
public static ManagedCommandPlan Create(
|
|
GlCommand command
|
|
)
|
|
{
|
|
Dictionary<string, ManagedParameterPlan> all = new(StringComparer.Ordinal);
|
|
foreach (GlParam parameter in command.Parameters)
|
|
{
|
|
ManagedParameterPlan plan;
|
|
if (CsTypeMapper.TryMapPointerElement(parameter, out string elementType) &&
|
|
(parameter.IsConst || !string.IsNullOrWhiteSpace(parameter.Length) ||
|
|
command.Name.StartsWith("glGet", StringComparison.Ordinal)))
|
|
{
|
|
if (!parameter.IsConst && parameter.Length == "1")
|
|
{
|
|
plan = new ManagedParameterPlan(
|
|
parameter, $"out {elementType}", ManagedParameterKind.Out,
|
|
elementType);
|
|
} else
|
|
{
|
|
ManagedParameterKind kind = parameter.IsConst
|
|
? ManagedParameterKind.ReadOnlySpan
|
|
: ManagedParameterKind.Span;
|
|
string container = parameter.IsConst ? "ReadOnlySpan" : "Span";
|
|
plan = new ManagedParameterPlan(
|
|
parameter, $"{container}<{elementType}>", kind, elementType);
|
|
}
|
|
} else
|
|
{
|
|
string mapped = CsTypeMapper.MapParameter(parameter);
|
|
ManagedParameterKind kind = parameter.PointerLevel == 0
|
|
? ManagedParameterKind.Value
|
|
: ManagedParameterKind.RawPointer;
|
|
plan = new ManagedParameterPlan(parameter, mapped, kind, null);
|
|
}
|
|
all.Add(parameter.Name, plan);
|
|
}
|
|
|
|
Dictionary<string, string> derivedLengths = new(StringComparer.Ordinal);
|
|
foreach (GlParam scalar in command.Parameters.Where(p => p.PointerLevel == 0))
|
|
{
|
|
List<ManagedParameterPlan> spans = command.Parameters
|
|
.Select(p => all[p.Name])
|
|
.Where(p => p.IsSpan &&
|
|
string.Equals(p.Source.Length, scalar.Name,
|
|
StringComparison.Ordinal))
|
|
.ToList();
|
|
if (spans.Count == 0) {
|
|
continue;
|
|
}
|
|
|
|
bool lengthAlsoControlsRawPointer = command.Parameters
|
|
.Select(p => all[p.Name]).Any(p =>
|
|
p.Kind == ManagedParameterKind.RawPointer &&
|
|
string.Equals(p.Source.Length, scalar.Name, StringComparison.Ordinal));
|
|
if (lengthAlsoControlsRawPointer) {
|
|
continue;
|
|
}
|
|
|
|
string scalarType = all[scalar.Name].PublicType;
|
|
if (scalarType is not ("int" or "uint" or "nint" or "nuint")) {
|
|
continue;
|
|
}
|
|
|
|
derivedLengths.Add(scalar.Name, spans[0].Source.Name);
|
|
}
|
|
|
|
IReadOnlyList<ManagedParameterPlan> publicParameters = command.Parameters
|
|
.Where(p => !derivedLengths.ContainsKey(p.Name))
|
|
.Select(p => all[p.Name])
|
|
.ToArray();
|
|
return new ManagedCommandPlan(publicParameters, all, derivedLengths);
|
|
}
|
|
|
|
public ManagedParameterPlan GetParameter(
|
|
string name
|
|
) => _allParameters[name];
|
|
|
|
}
|
|
}
|