Skip to content

Commit 788d771

Browse files
committed
wip: implement SystemReflectionMetadataDefinitionsFactory.Method() factory
1 parent e63ab1a commit 788d771

8 files changed

Lines changed: 106 additions & 18 deletions

File tree

Cecilifier.ApiDriver.MonoCecil/MonoCecilDefinitionsFactory.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ public IEnumerable<string> Type(
2929
return CecilDefinitionsFactory.Type(context, typeVar, typeNamespace, typeName, attrs, resolvedBaseType, outerTypeVariable, isStructWithNoFields, interfaces, ownTypeParameters, outerTypeParameters, properties);
3030
}
3131

32-
public IEnumerable<string> Method(IVisitorContext context, string methodVar, string methodName, string methodModifiers, ITypeSymbol returnType, bool refReturn, IList<TypeParameterSyntax> typeParameters)
32+
public IEnumerable<string> Method(IVisitorContext context, MemberDefinitionContext memberDefinitionContext, string methodName, string methodModifiers, ITypeSymbol returnType, bool refReturn,
33+
IParameterSymbol[] resolvedParameterTypes, IList<TypeParameterSyntax> typeParameters)
3334
{
34-
return CecilDefinitionsFactory.Method(context, methodVar, methodName, methodModifiers, returnType, refReturn, typeParameters);
35+
return CecilDefinitionsFactory.Method(context, memberDefinitionContext.MemberDefinitionVariableName, methodName, methodModifiers, returnType, refReturn, typeParameters);
3536
}
3637

3738
public IEnumerable<string> Method(IVisitorContext context, string declaringTypeName, string methodVar, string methodNameForParameterVariableRegistration, string methodName, string methodModifiers, IReadOnlyList<ParameterSpec> parameters,

Cecilifier.ApiDriver.SystemReflectionMetadata/SystemReflectionMetadataDefinitionsFactory.cs

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Cecilifier.Core.ApiDriver;
22
using Cecilifier.Core.AST;
3+
using Cecilifier.Core.Extensions;
34
using Cecilifier.Core.Misc;
45
using Cecilifier.Core.Naming;
56
using Cecilifier.Core.Variables;
@@ -26,8 +27,6 @@ public IEnumerable<string> Type(
2627
IEnumerable<TypeParameterSyntax> outerTypeParameters,
2728
params string[] properties)
2829
{
29-
//TODO: We need to pass the handle of the 1st field/method defined in the module so we need to postpone the type generation after we have visited
30-
// all types/members.
3130
yield return Format($"""
3231
// Add a type reference for the new type. Types/Member references to the new type uses this.
3332
var {typeVar} = metadata.AddTypeReference(
@@ -37,6 +36,8 @@ public IEnumerable<string> Type(
3736
3837
""");
3938

39+
// We need to pass the handle of the 1st field/method defined in the module so we need to postpone the type generation after we have visited
40+
// all types/members.
4041
((SystemReflectionMetadataContext) context).DelayedDefinitionsManager.RegisterTypeDefinition(typeVar, $"{typeNamespace}.{typeName}", (ctx, typeRecord) =>
4142
{
4243
ctx.Generate(Format($"""
@@ -52,9 +53,55 @@ public IEnumerable<string> Type(
5253
});
5354
}
5455

55-
public IEnumerable<string> Method(IVisitorContext context, string methodVar, string methodName, string methodModifiers, ITypeSymbol returnType, bool refReturn, IList<TypeParameterSyntax> typeParameters)
56+
public IEnumerable<string> Method(IVisitorContext context, MemberDefinitionContext memberDefinitionContext, string methodName, string methodModifiers, ITypeSymbol returnType, bool refReturn,
57+
IParameterSymbol[] resolvedParameterTypes, IList<TypeParameterSyntax> typeParameters)
5658
{
57-
throw new NotImplementedException();
59+
var methodSignatureVar = context.Naming.SyntheticVariable($"{methodName}Signature", ElementKind.LocalVariable);
60+
var methodBlobIndexVar = context.Naming.SyntheticVariable($"{methodName}BlobIndex", ElementKind.LocalVariable);
61+
62+
yield return Format(
63+
$$"""
64+
var {{methodSignatureVar}} = new BlobBuilder();
65+
new BlobEncoder({{methodSignatureVar}})
66+
.MethodSignature(isInstanceMethod: false)
67+
.Parameters(
68+
{{resolvedParameterTypes.Length}},
69+
returnType => returnType
70+
.Type(isByRef:false)
71+
.Type({{context.TypeResolver.Resolve(returnType)}}, IsValueType: {{returnType.IsValueType}}),
72+
parameters =>
73+
{
74+
{{string.Join('\n', resolvedParameterTypes.Select(p => $"""
75+
parameters.AddParameter()
76+
.Type(isByRef: {p.IsByRef()})
77+
.Type({context.TypeResolver.Resolve(p.Type)}, isValueType: {p.Type.IsValueType});
78+
"""))}}
79+
});
80+
81+
var {{methodBlobIndexVar}} = metadata.GetOrAddBlob({{methodSignatureVar}});
82+
83+
var {{context.Naming.SyntheticVariable($"{methodName}Ref", ElementKind.LocalVariable)}} = metadata.AddMemberReference(
84+
{{memberDefinitionContext.ParentDefinitionVariableName}},
85+
metadata.GetOrAddString("{{methodName}}"),
86+
{{methodBlobIndexVar}});
87+
""");
88+
89+
((SystemReflectionMetadataContext) context).DelayedDefinitionsManager.RegisterMethodDefinition(memberDefinitionContext.ParentDefinitionVariableName, (ctx, methodRecord) =>
90+
{
91+
var methodDefVar = ctx.Naming.SyntheticVariable(methodName, ElementKind.LocalVariable);
92+
ctx.Generate($"""
93+
var {methodDefVar} = metadata.AddMethodDefinition(
94+
{methodModifiers},
95+
MethodImplAttributes.IL | MethodImplAttributes.Managed,
96+
metadata.GetOrAddString("{methodName}"),
97+
metadata.GetOrAddBlob({methodSignatureVar}),
98+
methodBodyStream.AddMethodBody({memberDefinitionContext.IlContext.VariableName}),
99+
parameterList: {methodRecord.FirstParameterHandle});
100+
""");
101+
102+
ctx.WriteNewLine();
103+
return methodDefVar;
104+
});
58105
}
59106

60107
public IEnumerable<string> Method(IVisitorContext context, string declaringTypeName, string methodVar, string methodNameForParameterVariableRegistration, string methodName, string methodModifiers, IReadOnlyList<ParameterSpec> parameters,
@@ -95,9 +142,11 @@ public IEnumerable<string> Constructor(IVisitorContext context, MemberDefinition
95142
methodBodyStream.AddMethodBody({memberDefinitionContext.IlContext.VariableName}),
96143
parameterList: {methodRecord.FirstParameterHandle});
97144
""");
145+
146+
ctx.WriteNewLine();
98147
return ctorDefVar;
99148
});
100149
}
101150

102-
static string Format(CecilifierInterpolatedStringHandler handler) => handler.Result;
151+
static string Format(CecilifierInterpolatedStringHandler cecilFormattedString) => cecilFormattedString.Result;
103152
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Cecilifier.ApiDriver.MonoCecil;
2+
using Cecilifier.ApiDriver.SystemReflectionMetadata;
3+
using Cecilifier.Core.AST;
4+
using Cecilifier.Core.Tests.Framework;
5+
using NUnit.Framework;
6+
7+
namespace Cecilifier.Core.Tests.OutputBased;
8+
9+
[TestFixture(typeof(MonoCecilContext))]
10+
[TestFixture(typeof(SystemReflectionMetadataContext))]
11+
public class Simplest<TContext> : OutputBasedTestBase<TContext> where TContext : IVisitorContext
12+
{
13+
[Test]
14+
public void SimpleCallToConsoleWriteLine()
15+
{
16+
AssertOutput("""
17+
public class Foo
18+
{
19+
public static void Main()
20+
{
21+
System.Console.Write("Hello World!");
22+
}
23+
}
24+
""", "Hello World!");
25+
}
26+
}

Cecilifier.Core/AST/AssignmentVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ void LoadImplicitTargetForMemberReference(IdentifierNameSyntax node, ISymbol mem
179179
? OpCodes.Dup
180180
: OpCodes.Ldarg_0;
181181

182-
Context.WriteCilInstructionAfter<string>(ilVar, loadOpCode, null, null, InstructionPrecedingValueToLoad);
182+
Context.WriteCilInstructionAfter(ilVar, loadOpCode, InstructionPrecedingValueToLoad);
183183
}
184184
}
185185

Cecilifier.Core/AST/IVisitorContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public interface IVisitorContext
5151
// among the ApiDrivers
5252
void EmitCilInstruction(string ilVar, OpCode opCode);
5353
void EmitCilInstruction<T>(string ilVar, OpCode opCode, T operand, string comment = null);
54-
void WriteCilInstructionAfter<T>(string ilVar, OpCode opCode, T operand, string comment, LinkedListNode<string> after);
54+
void WriteCilInstructionAfter(string ilVar, OpCode opCode, LinkedListNode<string> after);
5555

5656
void Generate(CecilifierInterpolatedStringHandler expression);
5757
void Generate(string expression);

Cecilifier.Core/AST/MethodDeclarationVisitor.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Runtime.CompilerServices;
55
using System.Reflection.Emit;
6+
using Cecilifier.Core.ApiDriver;
67
using Microsoft.CodeAnalysis;
78
using Microsoft.CodeAnalysis.CSharp;
89
using Microsoft.CodeAnalysis.CSharp.Syntax;using Cecilifier.Core.Extensions;
@@ -164,7 +165,7 @@ private void ProcessMethodDeclarationInternal(
164165
}
165166

166167
// if the method is a local function use `simpleName` as the method name (instead of `methodName`) since, in this context,
167-
// the later is a `mangled name` and any reference to the method will use its `unmangled name` for lookups which would fail
168+
// the latter is a `mangled name` and any reference to the method will use its `unmangled name` for lookups which would fail
168169
// should we use `methodName` as the registered name.
169170
var nameUsedInRegisteredVariable = methodSymbol.MethodKind == MethodKind.LocalFunction ? simpleName : methodName;
170171
WithCurrentMethod(declaringTypeName, methodVar, nameUsedInRegisteredVariable, parameters.Select(p => Context.SemanticModel.GetDeclaredSymbol(p).Type.ToDisplayString()).ToArray(), methodSymbol.TypeParameters.Length, runWithCurrent);
@@ -191,7 +192,7 @@ private string AddOrUpdateMethodDefinition(string declaringTypeName, string vari
191192
return found.VariableName;
192193
}
193194

194-
AddMethodDefinition(Context, variableName, methodName, methodModifiers, returnType, refReturn, typeParameters);
195+
AddMethodDefinition(Context, variableName, methodName, methodModifiers, returnType, refReturn, parameters, typeParameters);
195196
return variableName;
196197
}
197198

@@ -213,13 +214,24 @@ protected void ProcessMethodDeclaration<T>(T node, string variableName, string s
213214
typeParameters);
214215
}
215216

216-
public static void AddMethodDefinition(IVisitorContext context, string methodVar, string methodName, string methodModifiers, ITypeSymbol returnType, bool refReturn, IList<TypeParameterSyntax> typeParameters)
217+
private static void AddMethodDefinition(
218+
IVisitorContext context,
219+
string methodVar,
220+
string methodName,
221+
string methodModifiers,
222+
ITypeSymbol returnType,
223+
bool refReturn,
224+
SeparatedSyntaxList<ParameterSyntax> parameters,
225+
IList<TypeParameterSyntax> typeParameters)
217226
{
218227
context.WriteNewLine();
219228
context.WriteComment($"Method : {methodName}");
220229

221-
TypeDeclarationVisitor.EnsureForwardedTypeDefinition(context, returnType, Array.Empty<TypeParameterSyntax>());
222-
var exps = CecilDefinitionsFactory.Method(context, methodVar, methodName, methodModifiers, returnType, refReturn, typeParameters);
230+
TypeDeclarationVisitor.EnsureForwardedTypeDefinition(context, returnType, []);
231+
var ilContext = context.ApiDriver.NewIlContext(context, methodName, methodVar);
232+
var declaringTypeVarName = context.DefinitionVariables.GetLastOf(VariableMemberKind.Type).VariableName;
233+
var parameterSymbols = parameters.Select(p => context.SemanticModel.GetDeclaredSymbol(p)).ToArray();
234+
var exps = context.ApiDefinitionsFactory.Method(context, new MemberDefinitionContext(methodVar, declaringTypeVarName, ilContext), methodName, methodModifiers, returnType, refReturn, parameterSymbols, typeParameters);
223235
AddCecilExpressions(context, exps);
224236

225237
HandleAttributesInTypeParameter(context, typeParameters);

Cecilifier.Core/ApiDriver/IApiDriverDefinitionsFactory.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ public IEnumerable<string> Type(
2626
IEnumerable<TypeParameterSyntax> outerTypeParameters,
2727
params string[] properties);
2828

29-
public IEnumerable<string> Method(IVisitorContext context, string methodVar, string methodName, string methodModifiers, ITypeSymbol returnType, bool refReturn, IList<TypeParameterSyntax> typeParameters);
29+
public IEnumerable<string> Method(IVisitorContext context, MemberDefinitionContext memberDefinitionContext, string methodName, string methodModifiers, ITypeSymbol returnType, bool refReturn,
30+
IParameterSymbol[] resolvedParameterTypes, IList<TypeParameterSyntax> typeParameters);
3031

3132
public IEnumerable<string> Method(
3233
IVisitorContext context,

Cecilifier.Core/Misc/CecilifierContextBase.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,9 @@ public void WriteNewLine()
147147
CecilifiedLineNumber++;
148148
}
149149

150-
public void WriteCilInstructionAfter<T>(string ilVar, OpCode opCode, T operand, string comment, LinkedListNode<string> after)
150+
public void WriteCilInstructionAfter(string ilVar, OpCode opCode, LinkedListNode<string> after)
151151
{
152-
var operandStr = operand == null ? string.Empty : $", {operand}";
153-
var toBeWritten = $"{ilVar}.Emit({opCode.ConstantName()}{operandStr});{(comment != null ? $" // {comment}" : string.Empty)}\n";
152+
var toBeWritten = $"{ilVar}.Emit({opCode.ConstantName()});\n";
154153

155154
output.AddAfter(after, $"{indentation}{toBeWritten}");
156155
CecilifiedLineNumber += toBeWritten.CountNewLines();

0 commit comments

Comments
 (0)