Templates are working, but the code is ugly af
This commit is contained in:
@@ -10,6 +10,17 @@ func main(args: []cstring): i64
|
|||||||
value = "bob"
|
value = "bob"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let box2 = alloc Box<cstring>
|
||||||
|
{
|
||||||
|
value = "bob"
|
||||||
|
}
|
||||||
|
|
||||||
|
let box3 = alloc Box<u8>
|
||||||
|
{
|
||||||
|
value = 23
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
c::puts(box.value)
|
c::puts(box.value)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using NubLang.CLI;
|
using NubLang.CLI;
|
||||||
using NubLang;
|
using NubLang;
|
||||||
|
using NubLang.Common;
|
||||||
using NubLang.Diagnostics;
|
using NubLang.Diagnostics;
|
||||||
using NubLang.Generation;
|
using NubLang.Generation;
|
||||||
using NubLang.Generation.QBE;
|
using NubLang.Generation.QBE;
|
||||||
@@ -8,6 +9,7 @@ using NubLang.Syntax.Binding;
|
|||||||
using NubLang.Syntax.Binding.Node;
|
using NubLang.Syntax.Binding.Node;
|
||||||
using NubLang.Syntax.Parsing;
|
using NubLang.Syntax.Parsing;
|
||||||
using NubLang.Syntax.Parsing.Node;
|
using NubLang.Syntax.Parsing.Node;
|
||||||
|
using NubLang.Syntax.Templating;
|
||||||
using NubLang.Syntax.Tokenization;
|
using NubLang.Syntax.Tokenization;
|
||||||
using Binder = NubLang.Syntax.Binding.Binder;
|
using Binder = NubLang.Syntax.Binding.Binder;
|
||||||
|
|
||||||
@@ -93,6 +95,15 @@ foreach (var file in options.Files)
|
|||||||
syntaxTrees[file] = syntaxTree;
|
syntaxTrees[file] = syntaxTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var templateTable = new TemplateTable(syntaxTrees.Values);
|
||||||
|
|
||||||
|
foreach (var (file, syntaxTree) in syntaxTrees)
|
||||||
|
{
|
||||||
|
var templateGenerator = new TemplateGenerator(syntaxTree, templateTable);
|
||||||
|
var definitions = templateGenerator.Generate();
|
||||||
|
syntaxTrees[file] = syntaxTree with { Definitions = syntaxTree.Definitions.Concat(definitions).ToList() };
|
||||||
|
}
|
||||||
|
|
||||||
var definitionTable = new DefinitionTable(syntaxTrees.Values);
|
var definitionTable = new DefinitionTable(syntaxTrees.Values);
|
||||||
|
|
||||||
var boundSyntaxTrees = new Dictionary<string, BoundSyntaxTree>();
|
var boundSyntaxTrees = new Dictionary<string, BoundSyntaxTree>();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace NubLang.CLI;
|
namespace NubLang.Common;
|
||||||
|
|
||||||
internal static class HexString
|
public static class HexString
|
||||||
{
|
{
|
||||||
private static readonly HashSet<string> _used = [];
|
private static readonly HashSet<string> _used = [];
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
if (boundExpression.Type is NubCustomType customType)
|
if (boundExpression.Type is NubCustomType customType)
|
||||||
{
|
{
|
||||||
var traits = _definitionTable.LookupTrait(customType.Namespace, customType.Name).ToArray();
|
var traits = _definitionTable.LookupTrait(customType).ToArray();
|
||||||
if (traits.Length > 0)
|
if (traits.Length > 0)
|
||||||
{
|
{
|
||||||
if (traits.Length > 1)
|
if (traits.Length > 1)
|
||||||
@@ -433,7 +433,7 @@ public sealed class Binder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var structs = _definitionTable.LookupStruct(customType.Namespace, customType.Name).ToArray();
|
var structs = _definitionTable.LookupStruct(customType).ToArray();
|
||||||
if (structs.Length > 0)
|
if (structs.Length > 0)
|
||||||
{
|
{
|
||||||
if (structs.Length > 1)
|
if (structs.Length > 1)
|
||||||
@@ -463,12 +463,14 @@ public sealed class Binder
|
|||||||
|
|
||||||
private BoundStructInitializer BindStructInitializer(StructInitializerSyntax expression)
|
private BoundStructInitializer BindStructInitializer(StructInitializerSyntax expression)
|
||||||
{
|
{
|
||||||
if (expression.StructType is not CustomTypeSyntax structType)
|
var boundType = BindType(expression.StructType);
|
||||||
|
|
||||||
|
if (boundType is not NubCustomType structType)
|
||||||
{
|
{
|
||||||
throw new BindException(Diagnostic.Error($"Cannot initialize non-struct type {expression.StructType}").Build());
|
throw new BindException(Diagnostic.Error($"Cannot initialize non-struct type {expression.StructType}").Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
var structs = _definitionTable.LookupStruct(structType.Namespace, structType.Name).ToArray();
|
var structs = _definitionTable.LookupStruct(structType).ToArray();
|
||||||
|
|
||||||
if (structs.Length == 0)
|
if (structs.Length == 0)
|
||||||
{
|
{
|
||||||
@@ -501,7 +503,7 @@ public sealed class Binder
|
|||||||
initializers[field] = BindExpression(initializer, BindType(fields[0].Type));
|
initializers[field] = BindExpression(initializer, BindType(fields[0].Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundStructInitializer(expression.Tokens, (NubCustomType)BindType(structType), initializers);
|
return new BoundStructInitializer(expression.Tokens, structType, initializers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundUnaryExpression BindUnaryExpression(UnaryExpressionSyntax expression)
|
private BoundUnaryExpression BindUnaryExpression(UnaryExpressionSyntax expression)
|
||||||
@@ -636,7 +638,7 @@ public sealed class Binder
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
}),
|
}),
|
||||||
StringTypeSyntax => new NubStringType(),
|
StringTypeSyntax => new NubStringType(),
|
||||||
TemplateTypeSyntax templateTypeSyntax => throw new NotImplementedException(),
|
TemplatedCustomTypeSyntax type => new NubCustomType(type.Namespace, type.MangledName()),
|
||||||
VoidTypeSyntax => new NubVoidType(),
|
VoidTypeSyntax => new NubVoidType(),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ public class DefinitionTable
|
|||||||
.Where(x => x.Namespace == @namespace && x.Name == name);
|
.Where(x => x.Namespace == @namespace && x.Name == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<StructSyntax> LookupStruct(string @namespace, string name)
|
public IEnumerable<StructSyntax> LookupStruct(NubCustomType type)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<StructSyntax>()
|
.OfType<StructSyntax>()
|
||||||
.Where(x => x.Namespace == @namespace && x.Name == name);
|
.Where(x => x.Namespace == type.Namespace && x.Name == type.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<StructFieldSyntax> LookupStructField(StructSyntax structNode, string field)
|
public IEnumerable<StructFieldSyntax> LookupStructField(StructSyntax structNode, string field)
|
||||||
@@ -46,11 +46,11 @@ public class DefinitionTable
|
|||||||
// .Where(x => x.Name == name);
|
// .Where(x => x.Name == name);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public IEnumerable<TraitSyntax> LookupTrait(string @namespace, string name)
|
public IEnumerable<TraitSyntax> LookupTrait(NubCustomType type)
|
||||||
{
|
{
|
||||||
return _definitions
|
return _definitions
|
||||||
.OfType<TraitSyntax>()
|
.OfType<TraitSyntax>()
|
||||||
.Where(x => x.Namespace == @namespace && x.Name == name);
|
.Where(x => x.Namespace == type.Namespace && x.Name == type.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<TraitFuncSyntax> LookupTraitFunc(TraitSyntax trait, string name)
|
public IEnumerable<TraitFuncSyntax> LookupTraitFunc(TraitSyntax trait, string name)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using NubLang.Syntax.Tokenization;
|
|||||||
|
|
||||||
namespace NubLang.Syntax.Parsing.Node;
|
namespace NubLang.Syntax.Parsing.Node;
|
||||||
|
|
||||||
public record SyntaxTree(string Namespace, IReadOnlyList<DefinitionSyntax> Definitions, IReadOnlyList<TemplateSyntax> Templates, IReadOnlyList<Diagnostic> Diagnostics);
|
public record SyntaxTree(string Namespace, IReadOnlyList<DefinitionSyntax> Definitions, IReadOnlyList<TemplateSyntax> Templates, IReadOnlyList<TemplatedCustomTypeSyntax> ReferencedTemplatedCustomTypes, IReadOnlyList<Diagnostic> Diagnostics);
|
||||||
|
|
||||||
public abstract record SyntaxNode(IReadOnlyList<Token> Tokens);
|
public abstract record SyntaxNode(IReadOnlyList<Token> Tokens);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,26 @@ public enum PrimitiveTypeSyntaxKind
|
|||||||
Bool
|
Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract record TypeSyntax(IReadOnlyList<Token> Tokens) : SyntaxNode(Tokens);
|
public abstract record TypeSyntax(IReadOnlyList<Token> Tokens) : SyntaxNode(Tokens)
|
||||||
|
{
|
||||||
|
public string MangledName()
|
||||||
|
{
|
||||||
|
return this switch
|
||||||
|
{
|
||||||
|
PrimitiveTypeSyntax primitive => primitive.SyntaxKind.ToString().ToLower(),
|
||||||
|
VoidTypeSyntax => "void",
|
||||||
|
CStringTypeSyntax => "cstring",
|
||||||
|
StringTypeSyntax => "string",
|
||||||
|
PointerTypeSyntax ptr => $"ptr_{ptr.BaseType.MangledName()}",
|
||||||
|
ArrayTypeSyntax arr => $"arr_{arr.BaseType.MangledName()}",
|
||||||
|
CustomTypeSyntax custom => $"{custom.Namespace}_{custom.Name}",
|
||||||
|
TemplateTypeSyntax template => $"tmpl_{template.Name}",
|
||||||
|
TemplatedCustomTypeSyntax tmpl => $"{tmpl.Namespace}_{tmpl.Name}_{string.Join("_", tmpl.Arguments.Select(x => x.MangledName()))}",
|
||||||
|
FuncTypeSyntax func => $"func_{string.Join("_", func.Parameters.Select(x => x.MangledName()))}_to_{func.ReturnType.MangledName()}",
|
||||||
|
_ => throw new NotSupportedException($"Unknown type syntax: {GetType().Name}")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public record FuncTypeSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<TypeSyntax> Parameters, TypeSyntax ReturnType) : TypeSyntax(Tokens);
|
public record FuncTypeSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<TypeSyntax> Parameters, TypeSyntax ReturnType) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
@@ -33,6 +52,8 @@ public record StringTypeSyntax(IReadOnlyList<Token> Tokens) : TypeSyntax(Tokens)
|
|||||||
|
|
||||||
public record CustomTypeSyntax(IReadOnlyList<Token> Tokens, string Name, string Namespace) : TypeSyntax(Tokens);
|
public record CustomTypeSyntax(IReadOnlyList<Token> Tokens, string Name, string Namespace) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
public record TemplateTypeSyntax(IReadOnlyList<Token> Tokens, string Name, string Namespace, IReadOnlyList<TypeSyntax> Arguments) : TypeSyntax(Tokens);
|
public record TemplatedCustomTypeSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name, IReadOnlyList<TypeSyntax> Arguments) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
|
public record TemplateTypeSyntax(IReadOnlyList<Token> Tokens, string Name) : TypeSyntax(Tokens);
|
||||||
|
|
||||||
public record ArrayTypeSyntax(IReadOnlyList<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
|
public record ArrayTypeSyntax(IReadOnlyList<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using NubLang.Common;
|
using NubLang.Common;
|
||||||
using NubLang.Diagnostics;
|
using NubLang.Diagnostics;
|
||||||
using NubLang.Syntax.Binding;
|
|
||||||
using NubLang.Syntax.Parsing.Node;
|
using NubLang.Syntax.Parsing.Node;
|
||||||
using NubLang.Syntax.Tokenization;
|
using NubLang.Syntax.Tokenization;
|
||||||
|
|
||||||
@@ -13,6 +12,8 @@ public sealed class Parser
|
|||||||
private readonly IReadOnlyList<Token> _tokens;
|
private readonly IReadOnlyList<Token> _tokens;
|
||||||
|
|
||||||
private readonly List<Diagnostic> _diagnostics = [];
|
private readonly List<Diagnostic> _diagnostics = [];
|
||||||
|
private readonly List<TemplatedCustomTypeSyntax> _referencedTemplates = [];
|
||||||
|
private List<string> _templateParameters = [];
|
||||||
private int _tokenIndex;
|
private int _tokenIndex;
|
||||||
|
|
||||||
public Parser(IReadOnlyList<Token> tokens)
|
public Parser(IReadOnlyList<Token> tokens)
|
||||||
@@ -23,7 +24,9 @@ public sealed class Parser
|
|||||||
|
|
||||||
public SyntaxTree Parse()
|
public SyntaxTree Parse()
|
||||||
{
|
{
|
||||||
|
_referencedTemplates.Clear();
|
||||||
_diagnostics.Clear();
|
_diagnostics.Clear();
|
||||||
|
_templateParameters = [];
|
||||||
_tokenIndex = 0;
|
_tokenIndex = 0;
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Namespace))
|
if (TryExpectSymbol(Symbol.Namespace))
|
||||||
@@ -42,18 +45,16 @@ public sealed class Parser
|
|||||||
{
|
{
|
||||||
if (TryExpectSymbol(Symbol.Template))
|
if (TryExpectSymbol(Symbol.Template))
|
||||||
{
|
{
|
||||||
var templateArguments = new List<string>();
|
|
||||||
|
|
||||||
ExpectSymbol(Symbol.LessThan);
|
ExpectSymbol(Symbol.LessThan);
|
||||||
while (!TryExpectSymbol(Symbol.GreaterThan))
|
while (!TryExpectSymbol(Symbol.GreaterThan))
|
||||||
{
|
{
|
||||||
templateArguments.Add(ExpectIdentifier().Value);
|
_templateParameters.Add(ExpectIdentifier().Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpectSymbol(Symbol.Struct);
|
ExpectSymbol(Symbol.Struct);
|
||||||
|
|
||||||
var definition = ParseStruct(_tokenIndex);
|
var definition = ParseStruct(_tokenIndex);
|
||||||
templates.Add(new StructTemplateSyntax(GetTokens(startIndex), _namespace, templateArguments, definition));
|
templates.Add(new StructTemplateSyntax(GetTokens(startIndex), _namespace, _templateParameters, definition));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -68,7 +69,7 @@ public sealed class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SyntaxTree(_namespace, definitions, templates, _diagnostics);
|
return new SyntaxTree(_namespace, definitions, templates, _referencedTemplates, _diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefinitionSyntax ParseDefinition(int startIndex)
|
private DefinitionSyntax ParseDefinition(int startIndex)
|
||||||
@@ -656,6 +657,11 @@ public sealed class Parser
|
|||||||
|
|
||||||
if (TryExpectIdentifier(out var name))
|
if (TryExpectIdentifier(out var name))
|
||||||
{
|
{
|
||||||
|
if (_templateParameters.Contains(name.Value))
|
||||||
|
{
|
||||||
|
return new TemplateTypeSyntax(GetTokens(startIndex), name.Value);
|
||||||
|
}
|
||||||
|
|
||||||
return name.Value switch
|
return name.Value switch
|
||||||
{
|
{
|
||||||
"void" => new VoidTypeSyntax(GetTokens(startIndex)),
|
"void" => new VoidTypeSyntax(GetTokens(startIndex)),
|
||||||
@@ -692,10 +698,12 @@ public sealed class Parser
|
|||||||
parameters.Add(ParseType());
|
parameters.Add(ParseType());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TemplateTypeSyntax(GetTokens(startIndex), @namespace, name.Value, parameters);
|
var template = new TemplatedCustomTypeSyntax(GetTokens(startIndex), @namespace, name.Value, parameters);
|
||||||
|
_referencedTemplates.Add(template);
|
||||||
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CustomTypeSyntax(GetTokens(startIndex), @namespace, name.Value);
|
return new CustomTypeSyntax(GetTokens(startIndex), name.Value, @namespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using NubLang.Diagnostics;
|
||||||
using NubLang.Syntax.Parsing.Node;
|
using NubLang.Syntax.Parsing.Node;
|
||||||
|
|
||||||
namespace NubLang.Syntax.Templating;
|
namespace NubLang.Syntax.Templating;
|
||||||
@@ -7,8 +8,6 @@ public class TemplateGenerator
|
|||||||
private readonly SyntaxTree _syntaxTree;
|
private readonly SyntaxTree _syntaxTree;
|
||||||
private readonly TemplateTable _templateTable;
|
private readonly TemplateTable _templateTable;
|
||||||
|
|
||||||
private List<DefinitionSyntax> _definitions = [];
|
|
||||||
|
|
||||||
public TemplateGenerator(SyntaxTree syntaxTree, TemplateTable templateTable)
|
public TemplateGenerator(SyntaxTree syntaxTree, TemplateTable templateTable)
|
||||||
{
|
{
|
||||||
_syntaxTree = syntaxTree;
|
_syntaxTree = syntaxTree;
|
||||||
@@ -17,7 +16,50 @@ public class TemplateGenerator
|
|||||||
|
|
||||||
public IReadOnlyList<DefinitionSyntax> Generate()
|
public IReadOnlyList<DefinitionSyntax> Generate()
|
||||||
{
|
{
|
||||||
_definitions.Clear();
|
var definitions = new List<DefinitionSyntax>();
|
||||||
return _definitions;
|
|
||||||
|
foreach (var type in _syntaxTree.ReferencedTemplatedCustomTypes)
|
||||||
|
{
|
||||||
|
definitions.Add(CreateDefinition(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
return definitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefinitionSyntax CreateDefinition(TemplatedCustomTypeSyntax type)
|
||||||
|
{
|
||||||
|
var structTemplates = _templateTable.LookupStructTemplate(type.Namespace, type.Name).ToArray();
|
||||||
|
if (structTemplates.Length > 0)
|
||||||
|
{
|
||||||
|
if (structTemplates.Length > 1)
|
||||||
|
{
|
||||||
|
throw new TemplateGeneratorException(Diagnostic.Error($"Struct template {type.Namespace}::{type.Name} has multiple definitions").Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
var structTemplate = structTemplates[0];
|
||||||
|
|
||||||
|
var transformations = new Dictionary<string, TypeSyntax>();
|
||||||
|
|
||||||
|
for (var i = 0; i < structTemplate.TemplateParameters.Count; i++)
|
||||||
|
{
|
||||||
|
transformations[structTemplate.TemplateParameters[i]] = type.Arguments[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
var transformer = new TypeTransformer(transformations);
|
||||||
|
var transformed = transformer.TransformStruct(structTemplate.Struct);
|
||||||
|
return transformed with { Name = type.MangledName() };
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new TemplateGeneratorException(Diagnostic.Error($"Template {type.Namespace}::{type.Name} is not defined").Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TemplateGeneratorException : Exception
|
||||||
|
{
|
||||||
|
public Diagnostic Diagnostic { get; }
|
||||||
|
|
||||||
|
public TemplateGeneratorException(Diagnostic diagnostic) : base(diagnostic.Message)
|
||||||
|
{
|
||||||
|
Diagnostic = diagnostic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,20 @@
|
|||||||
|
using NubLang.Syntax.Parsing.Node;
|
||||||
|
|
||||||
namespace NubLang.Syntax.Templating;
|
namespace NubLang.Syntax.Templating;
|
||||||
|
|
||||||
public class TemplateTable
|
public class TemplateTable
|
||||||
{
|
{
|
||||||
|
private readonly List<TemplateSyntax> _templates;
|
||||||
|
|
||||||
|
public TemplateTable(IEnumerable<SyntaxTree> syntaxTrees)
|
||||||
|
{
|
||||||
|
_templates = syntaxTrees.SelectMany(x => x.Templates).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<StructTemplateSyntax> LookupStructTemplate(string @namespace, string name)
|
||||||
|
{
|
||||||
|
return _templates
|
||||||
|
.OfType<StructTemplateSyntax>()
|
||||||
|
.Where(x => x.Struct.Namespace == @namespace && x.Struct.Name == @name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
280
src/compiler/NubLang/Syntax/Templating/TypeTransformer.cs
Normal file
280
src/compiler/NubLang/Syntax/Templating/TypeTransformer.cs
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
using NubLang.Common;
|
||||||
|
using NubLang.Syntax.Parsing.Node;
|
||||||
|
|
||||||
|
namespace NubLang.Syntax.Templating;
|
||||||
|
|
||||||
|
public class TypeTransformer
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, TypeSyntax> _transformations;
|
||||||
|
|
||||||
|
public TypeTransformer(Dictionary<string, TypeSyntax> transformations)
|
||||||
|
{
|
||||||
|
_transformations = transformations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefinitionSyntax TransformDefinition(DefinitionSyntax definition)
|
||||||
|
{
|
||||||
|
return definition switch
|
||||||
|
{
|
||||||
|
ExternFuncSyntax node => TransformExternFunc(node),
|
||||||
|
LocalFuncSyntax node => TransformLocalFunc(node),
|
||||||
|
StructSyntax node => TransformStruct(node),
|
||||||
|
TraitImplSyntax node => TransformTraitImpl(node),
|
||||||
|
TraitSyntax node => TransformTrait(node),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(definition))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public FuncSignatureSyntax TransformFuncSignature(FuncSignatureSyntax node)
|
||||||
|
{
|
||||||
|
var parameters = new List<FuncParameterSyntax>();
|
||||||
|
|
||||||
|
foreach (var parameter in node.Parameters)
|
||||||
|
{
|
||||||
|
parameters.Add(new FuncParameterSyntax(parameter.Tokens, parameter.Name, TransformType(parameter.Type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FuncSignatureSyntax(node.Tokens, parameters, TransformType(node.ReturnType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExternFuncSyntax TransformExternFunc(ExternFuncSyntax node)
|
||||||
|
{
|
||||||
|
return new ExternFuncSyntax(node.Tokens, node.Namespace, node.Name, node.CallName, TransformFuncSignature(node.Signature));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalFuncSyntax TransformLocalFunc(LocalFuncSyntax node)
|
||||||
|
{
|
||||||
|
return new LocalFuncSyntax(node.Tokens, node.Namespace, node.Name, TransformFuncSignature(node.Signature), TransformBlock(node.Body));
|
||||||
|
}
|
||||||
|
|
||||||
|
public StructSyntax TransformStruct(StructSyntax node)
|
||||||
|
{
|
||||||
|
var fields = new List<StructFieldSyntax>();
|
||||||
|
|
||||||
|
foreach (var field in node.Fields)
|
||||||
|
{
|
||||||
|
var value = Optional.Empty<ExpressionSyntax>();
|
||||||
|
if (field.Value.HasValue)
|
||||||
|
{
|
||||||
|
value = TransformExpression(field.Value.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.Add(new StructFieldSyntax(field.Tokens, field.Index, field.Name, TransformType(field.Type), value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StructSyntax(node.Tokens, node.Namespace, node.Name, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TraitImplSyntax TransformTraitImpl(TraitImplSyntax node)
|
||||||
|
{
|
||||||
|
var functions = new List<TraitFuncImplSyntax>();
|
||||||
|
|
||||||
|
foreach (var function in node.Functions)
|
||||||
|
{
|
||||||
|
functions.Add(new TraitFuncImplSyntax(function.Tokens, function.Name, TransformFuncSignature(function.Signature), TransformBlock(function.Body)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TraitImplSyntax(node.Tokens, node.Namespace, TransformType(node.TraitType), TransformType(node.ForType), functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TraitSyntax TransformTrait(TraitSyntax node)
|
||||||
|
{
|
||||||
|
var functions = new List<TraitFuncSyntax>();
|
||||||
|
|
||||||
|
foreach (var function in node.Functions)
|
||||||
|
{
|
||||||
|
functions.Add(new TraitFuncSyntax(function.Tokens, function.Name, TransformFuncSignature(function.Signature)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TraitSyntax(node.Tokens, node.Namespace, node.Name, functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockSyntax TransformBlock(BlockSyntax block)
|
||||||
|
{
|
||||||
|
var statements = new List<StatementSyntax>();
|
||||||
|
|
||||||
|
foreach (var statement in block.Statements)
|
||||||
|
{
|
||||||
|
statements.Add(TransformStatement(statement));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BlockSyntax(block.Tokens, statements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StatementSyntax TransformStatement(StatementSyntax statement)
|
||||||
|
{
|
||||||
|
return statement switch
|
||||||
|
{
|
||||||
|
AssignmentSyntax node => TransformAssignment(node),
|
||||||
|
BreakSyntax node => new BreakSyntax(node.Tokens),
|
||||||
|
ContinueSyntax node => new ContinueSyntax(node.Tokens),
|
||||||
|
IfSyntax node => TransformIf(node),
|
||||||
|
ReturnSyntax node => TransformReturn(node),
|
||||||
|
StatementExpressionSyntax node => new StatementExpressionSyntax(node.Tokens, TransformExpression(node.Expression)),
|
||||||
|
VariableDeclarationSyntax node => TransformVariableDeclaration(node),
|
||||||
|
WhileSyntax node => new WhileSyntax(node.Tokens, TransformExpression(node.Condition), TransformBlock(node.Body)),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(statement))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssignmentSyntax TransformAssignment(AssignmentSyntax node)
|
||||||
|
{
|
||||||
|
return new AssignmentSyntax(node.Tokens, TransformExpression(node.Target), TransformExpression(node.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfSyntax TransformIf(IfSyntax node)
|
||||||
|
{
|
||||||
|
var elseStatement = Optional.Empty<Variant<IfSyntax, BlockSyntax>>();
|
||||||
|
if (node.Else.HasValue)
|
||||||
|
{
|
||||||
|
elseStatement = node.Else.Value.Match<Variant<IfSyntax, BlockSyntax>>(x => TransformIf(x), x => TransformBlock(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new IfSyntax(node.Tokens, TransformExpression(node.Condition), TransformBlock(node.Body), elseStatement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReturnSyntax TransformReturn(ReturnSyntax node)
|
||||||
|
{
|
||||||
|
var value = Optional<ExpressionSyntax>.Empty();
|
||||||
|
if (node.Value.HasValue)
|
||||||
|
{
|
||||||
|
value = TransformExpression(node.Value.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ReturnSyntax(node.Tokens, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VariableDeclarationSyntax TransformVariableDeclaration(VariableDeclarationSyntax node)
|
||||||
|
{
|
||||||
|
var explicitType = Optional<TypeSyntax>.Empty();
|
||||||
|
if (node.ExplicitType.HasValue)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var assignment = Optional.Empty<ExpressionSyntax>();
|
||||||
|
if (node.Assignment.HasValue)
|
||||||
|
{
|
||||||
|
assignment = TransformExpression(node.Assignment.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new VariableDeclarationSyntax(node.Tokens, node.Name, explicitType, assignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExpressionSyntax TransformExpression(ExpressionSyntax expression)
|
||||||
|
{
|
||||||
|
return expression switch
|
||||||
|
{
|
||||||
|
AddressOfSyntax node => TransformAddressOf(node),
|
||||||
|
ArrayIndexAccessSyntax node => TransformArrayIndexAccess(node),
|
||||||
|
ArrayInitializerSyntax node => TransformArrayInitializer(node),
|
||||||
|
ArrowFuncParameterSyntax node => TransformArrowFuncParameter(node),
|
||||||
|
ArrowFuncSyntax node => TransformArrowFunc(node),
|
||||||
|
BinaryExpressionSyntax node => TransformBinaryExpression(node),
|
||||||
|
DereferenceSyntax node => TransformDereference(node),
|
||||||
|
FuncCallSyntax node => TransformFuncCall(node),
|
||||||
|
IdentifierSyntax node => TransformIdentifier(node),
|
||||||
|
LiteralSyntax node => TransformLiteral(node),
|
||||||
|
MemberAccessSyntax node => TransformMemberAccess(node),
|
||||||
|
StructInitializerSyntax node => TransformStructInitializer(node),
|
||||||
|
UnaryExpressionSyntax node => TransformUnaryExpression(node),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddressOfSyntax TransformAddressOf(AddressOfSyntax node)
|
||||||
|
{
|
||||||
|
return new AddressOfSyntax(node.Tokens, TransformExpression(node.Expression));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayIndexAccessSyntax TransformArrayIndexAccess(ArrayIndexAccessSyntax node)
|
||||||
|
{
|
||||||
|
return new ArrayIndexAccessSyntax(node.Tokens, TransformExpression(node.Target), TransformExpression(node.Index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayInitializerSyntax TransformArrayInitializer(ArrayInitializerSyntax node)
|
||||||
|
{
|
||||||
|
return new ArrayInitializerSyntax(node.Tokens, TransformExpression(node.Capacity), TransformType(node.ElementType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrowFuncParameterSyntax TransformArrowFuncParameter(ArrowFuncParameterSyntax node)
|
||||||
|
{
|
||||||
|
return new ArrowFuncParameterSyntax(node.Tokens, node.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrowFuncSyntax TransformArrowFunc(ArrowFuncSyntax node)
|
||||||
|
{
|
||||||
|
var parameters = new List<ArrowFuncParameterSyntax>();
|
||||||
|
|
||||||
|
foreach (var parameter in node.Parameters)
|
||||||
|
{
|
||||||
|
parameters.Add(TransformArrowFuncParameter(parameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrowFuncSyntax(node.Tokens, parameters, TransformBlock(node.Body));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BinaryExpressionSyntax TransformBinaryExpression(BinaryExpressionSyntax node)
|
||||||
|
{
|
||||||
|
return new BinaryExpressionSyntax(node.Tokens, TransformExpression(node.Left), node.Operator, TransformExpression(node.Right));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DereferenceSyntax TransformDereference(DereferenceSyntax node)
|
||||||
|
{
|
||||||
|
return new DereferenceSyntax(node.Tokens, TransformExpression(node.Expression));
|
||||||
|
}
|
||||||
|
|
||||||
|
public FuncCallSyntax TransformFuncCall(FuncCallSyntax node)
|
||||||
|
{
|
||||||
|
var parameters = new List<ExpressionSyntax>();
|
||||||
|
|
||||||
|
foreach (var parameter in node.Parameters)
|
||||||
|
{
|
||||||
|
parameters.Add(TransformExpression(parameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FuncCallSyntax(node.Tokens, TransformExpression(node.Expression), parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentifierSyntax TransformIdentifier(IdentifierSyntax node)
|
||||||
|
{
|
||||||
|
return new IdentifierSyntax(node.Tokens, node.Namespace, node.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiteralSyntax TransformLiteral(LiteralSyntax node)
|
||||||
|
{
|
||||||
|
return new LiteralSyntax(node.Tokens, node.Literal, node.Kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemberAccessSyntax TransformMemberAccess(MemberAccessSyntax node)
|
||||||
|
{
|
||||||
|
return new MemberAccessSyntax(node.Tokens, TransformExpression(node.Target), node.Member);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StructInitializerSyntax TransformStructInitializer(StructInitializerSyntax node)
|
||||||
|
{
|
||||||
|
var initializers = new Dictionary<string, ExpressionSyntax>();
|
||||||
|
|
||||||
|
foreach (var (field, value) in node.Initializers)
|
||||||
|
{
|
||||||
|
initializers.Add(field, TransformExpression(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StructInitializerSyntax(node.Tokens, TransformType(node.StructType), initializers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnaryExpressionSyntax TransformUnaryExpression(UnaryExpressionSyntax node)
|
||||||
|
{
|
||||||
|
return new UnaryExpressionSyntax(node.Tokens, node.Operator, TransformExpression(node.Operand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeSyntax TransformType(TypeSyntax node)
|
||||||
|
{
|
||||||
|
if (node is TemplateTypeSyntax templateType)
|
||||||
|
{
|
||||||
|
return _transformations[templateType.Name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user