Skip to content

Commit 47e9e69

Browse files
authored
Merge pull request #710 from stakx/refactor/simple-ast-reference-subclasses
Remove `SimpleAST`'s false `Reference` subtypes, and add a missing one
2 parents 4cbde53 + f2bc4a2 commit 47e9e69

17 files changed

+114
-170
lines changed

src/Castle.Core/DynamicProxy/Contributors/Delegates.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,4 @@ internal delegate MethodEmitter OverrideMethodDelegate(
2323
string name, MethodAttributes attributes, MethodInfo methodToOverride);
2424

2525
internal delegate IExpression GetTargetExpressionDelegate(ClassEmitter @class, MethodInfo method);
26-
27-
internal delegate Reference GetTargetReferenceDelegate(ClassEmitter @class, MethodInfo method);
2826
}

src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithOptionalTargetContributor.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2004-2021 Castle Project - http://www.castleproject.org/
1+
// Copyright 2004-2025 Castle Project - http://www.castleproject.org/
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -19,13 +19,9 @@ namespace Castle.DynamicProxy.Contributors
1919

2020
internal class InterfaceProxyWithOptionalTargetContributor : InterfaceProxyWithoutTargetContributor
2121
{
22-
private readonly GetTargetReferenceDelegate getTargetReference;
23-
24-
public InterfaceProxyWithOptionalTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget,
25-
GetTargetReferenceDelegate getTargetReference)
22+
public InterfaceProxyWithOptionalTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget)
2623
: base(namingScope, getTarget)
2724
{
28-
this.getTargetReference = getTargetReference;
2925
canChangeTarget = true;
3026
}
3127

@@ -34,7 +30,7 @@ protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEm
3430
{
3531
if (!method.Proxyable)
3632
{
37-
return new OptionallyForwardingMethodGenerator(method, overrideMethod, getTargetReference);
33+
return new OptionallyForwardingMethodGenerator(method, overrideMethod, getTarget);
3834
}
3935

4036
return base.GetMethodGenerator(method, @class, overrideMethod);

src/Castle.Core/DynamicProxy/Contributors/InterfaceProxyWithoutTargetContributor.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ namespace Castle.DynamicProxy.Contributors
2626

2727
internal class InterfaceProxyWithoutTargetContributor : CompositeTypeContributor
2828
{
29-
private readonly GetTargetExpressionDelegate getTargetExpression;
29+
protected readonly GetTargetExpressionDelegate getTarget;
3030
protected bool canChangeTarget = false;
3131

3232
public InterfaceProxyWithoutTargetContributor(INamingScope namingScope, GetTargetExpressionDelegate getTarget)
3333
: base(namingScope)
3434
{
35-
getTargetExpression = getTarget;
35+
this.getTarget = getTarget;
3636
}
3737

3838
protected override IEnumerable<MembersCollector> GetCollectors()
@@ -56,7 +56,7 @@ protected override MethodGenerator GetMethodGenerator(MetaMethod method, ClassEm
5656
return new MethodWithInvocationGenerator(method,
5757
@class.GetField("__interceptors"),
5858
invocation,
59-
getTargetExpression,
59+
getTarget,
6060
overrideMethod,
6161
null);
6262
}

src/Castle.Core/DynamicProxy/Contributors/MixinContributor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2004-2021 Castle Project - http://www.castleproject.org/
1+
// Copyright 2004-2025 Castle Project - http://www.castleproject.org/
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -114,7 +114,7 @@ private GetTargetExpressionDelegate BuildGetTargetExpression()
114114
}
115115

116116
return (c, m) => new NullCoalescingOperatorExpression(
117-
new AsTypeReference(c.GetField("__target"), m.DeclaringType),
117+
new AsTypeExpression(c.GetField("__target"), m.DeclaringType),
118118
fields[m.DeclaringType]);
119119
}
120120

src/Castle.Core/DynamicProxy/Contributors/SerializableContributor.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2004-2021 Castle Project - http://www.castleproject.org/
1+
// Copyright 2004-2025 Castle Project - http://www.castleproject.org/
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -90,9 +90,8 @@ protected void ImplementGetObjectData(ClassEmitter emitter)
9090
for (var i = 0; i < interfaces.Length; i++)
9191
{
9292
getObjectData.CodeBuilder.AddStatement(
93-
new AssignArrayStatement(
94-
interfacesLocal,
95-
i,
93+
new AssignStatement(
94+
new ArrayElementReference(interfacesLocal, i),
9695
new LiteralStringExpression(interfaces[i].AssemblyQualifiedName)));
9796
}
9897

src/Castle.Core/DynamicProxy/Generators/BaseProxyGenerator.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2004-2021 Castle Project - http://www.castleproject.org/
1+
// Copyright 2004-2025 Castle Project - http://www.castleproject.org/
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -331,7 +331,9 @@ protected void GenerateParameterlessConstructor(ClassEmitter emitter, Type baseC
331331
constructor.CodeBuilder.AddStatement(new AssignStatement(interceptorField,
332332
new NewArrayExpression(1, typeof(IInterceptor))));
333333
constructor.CodeBuilder.AddStatement(
334-
new AssignArrayStatement(interceptorField, 0, new NewInstanceExpression(typeof(StandardInterceptor))));
334+
new AssignStatement(
335+
new ArrayElementReference(interceptorField, 0),
336+
new NewInstanceExpression(typeof(StandardInterceptor))));
335337

336338
// Invoke base constructor
337339

src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/LoadRefArrayElementExpression.cs renamed to src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AddressOfExpression.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,22 @@
1616

1717
namespace Castle.DynamicProxy.Generators.Emitters.SimpleAST
1818
{
19+
using System.Diagnostics;
1920
using System.Reflection.Emit;
2021

21-
internal class LoadRefArrayElementExpression : IExpression
22+
[DebuggerDisplay("&{reference}")]
23+
internal class AddressOfExpression : IExpression
2224
{
23-
private readonly Reference arrayReference;
24-
private readonly LiteralIntExpression index;
25+
private readonly Reference reference;
2526

26-
public LoadRefArrayElementExpression(int index, Reference arrayReference)
27+
public AddressOfExpression(Reference reference)
2728
{
28-
this.index = new LiteralIntExpression(index);
29-
this.arrayReference = arrayReference;
29+
this.reference = reference;
3030
}
3131

3232
public void Emit(ILGenerator gen)
3333
{
34-
arrayReference.Emit(gen);
35-
index.Emit(gen);
36-
gen.Emit(OpCodes.Ldelem_Ref);
34+
reference.EmitAddress(gen);
3735
}
3836
}
3937
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2004-2025 Castle Project - http://www.castleproject.org/
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#nullable enable
16+
17+
namespace Castle.DynamicProxy.Generators.Emitters.SimpleAST
18+
{
19+
using System.Diagnostics;
20+
using System.Reflection.Emit;
21+
22+
internal sealed class ArrayElementReference : Reference
23+
{
24+
private readonly Reference array;
25+
private readonly int index;
26+
27+
public ArrayElementReference(Reference array, int index)
28+
: base(array.Type.GetElementType()!)
29+
{
30+
Debug.Assert(array.Type.IsArray);
31+
32+
// The below methods have the `ldelem.ref` and `stelem.ref` opcodes hardcoded,
33+
// which is only correct for reference types. Once we start using this class
34+
// for arrays of primitive types, enums, value types, or generic parameters,
35+
// we will need to revisit this.
36+
Debug.Assert(array.Type.GetElementType()!.IsClass || array.Type.GetElementType()!.IsInterface);
37+
38+
this.array = array;
39+
this.index = index;
40+
}
41+
42+
public override void Emit(ILGenerator gen)
43+
{
44+
array.Emit(gen);
45+
gen.Emit(OpCodes.Ldc_I4, index);
46+
gen.Emit(OpCodes.Ldelem_Ref);
47+
}
48+
49+
public override void EmitAddress(ILGenerator gen)
50+
{
51+
array.Emit(gen);
52+
gen.Emit(OpCodes.Ldc_I4, index);
53+
gen.Emit(OpCodes.Ldelema);
54+
}
55+
56+
public override void EmitStore(IExpression value, ILGenerator gen)
57+
{
58+
array.Emit(gen);
59+
gen.Emit(OpCodes.Ldc_I4, index);
60+
value.Emit(gen);
61+
gen.Emit(OpCodes.Stelem_Ref);
62+
}
63+
}
64+
}

src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AsTypeReference.cs renamed to src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AsTypeExpression.cs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,21 @@ namespace Castle.DynamicProxy.Generators.Emitters.SimpleAST
2121
using System.Reflection.Emit;
2222

2323
[DebuggerDisplay("{reference} as {type}")]
24-
internal class AsTypeReference : Reference
24+
internal class AsTypeExpression : IExpression
2525
{
2626
private readonly Reference reference;
2727
private readonly Type type;
2828

29-
public AsTypeReference(Reference reference, Type type)
30-
: base(type)
29+
public AsTypeExpression(Reference reference, Type type)
3130
{
3231
this.reference = reference;
3332
this.type = type;
3433
}
3534

36-
public override void EmitAddress(ILGenerator gen)
37-
{
38-
// It does not make sense to take the address of a cast expression.
39-
// The C# language would also forbid address-taking of the form `&(x as T)`.
40-
throw new NotSupportedException();
41-
}
42-
43-
public override void Emit(ILGenerator gen)
35+
public void Emit(ILGenerator gen)
4436
{
4537
reference.Emit(gen);
4638
gen.Emit(OpCodes.Isinst, type);
4739
}
48-
49-
public override void EmitStore(IExpression value, ILGenerator gen)
50-
{
51-
// It does not make sense to assign a value to the result of a cast expression.
52-
// The C# language would also forbid assignments of the form `(x as T) = y`.
53-
throw new NotSupportedException();
54-
}
5540
}
5641
}

src/Castle.Core/DynamicProxy/Generators/Emitters/SimpleAST/AssignArrayStatement.cs

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)