Permalink
Browse files

Checkpoint work on supporting 'ref this' for structs.

  • Loading branch information...
1 parent 7f0daf8 commit 723cc1d0d9204940f98dd4eb49ebbe7ae63589b7 @kg kg committed Jun 24, 2012
View
40 JSIL/Transforms/IntroduceVariableReferences.cs
@@ -31,6 +31,22 @@ public class IntroduceVariableReferences : JSAstVisitor {
return false;
}
+ protected JSVariable GetReferentVariable (JSPassByReferenceExpression pbr) {
+ JSVariable referentVariable;
+ JSExpression referent;
+
+ if (!JSReferenceExpression.TryMaterialize(JSIL, pbr.Referent, out referent)) {
+ if (JSReferenceExpression.TryDereference(JSIL, pbr.Referent, out referent)) {
+ referentVariable = referent as JSVariable;
+ return referentVariable;
+ } else
+ return null;
+ }
+
+ referentVariable = referent as JSVariable;
+ return referentVariable;
+ }
+
protected JSVariable GetConstructedReference (JSPassByReferenceExpression pbr) {
JSVariable referentVariable;
JSExpression referent;
@@ -60,12 +76,20 @@ public class IntroduceVariableReferences : JSAstVisitor {
// If the variable does not match the one in the dictionary, it is a constructed
// reference to a parameter.
- if (!referentVariable.Equals(Variables[referentVariable.Identifier])) {
+ var theVariable = Variables[referentVariable.Identifier];
+ if (!referentVariable.Equals(theVariable)) {
// If the parameter is a reference, we don't care about it.
- if (Variables[referentVariable.Identifier].IsReference)
- return null;
- else
+ if (theVariable.IsReference) {
+ // Unless it's the 'this' variable...
+ if (theVariable.IsThis) {
+ // But we handle that separately.
+ return referentVariable;
+ } else {
+ return null;
+ }
+
+ } else
return referentVariable;
}
@@ -185,6 +209,14 @@ public class IntroduceVariableReferences : JSAstVisitor {
continue;
}
+ // For 'ref this', we need to replace each individual expression, because we can't
+ // rename the this-variable.
+ if (cr.IsThis) {
+ var refThis = JSIL.NewReference(Variables["this"]);
+ fn.ReplaceChildRecursive(r, refThis);
+ continue;
+ }
+
var parameter = (from p in fn.Parameters
where p.Identifier == cr.Identifier
select p).FirstOrDefault();
View
24 JSIL/Transforms/StaticAnalysis/EmulateStructAssignment.cs
@@ -76,9 +76,29 @@ public class EmulateStructAssignment : JSAstVisitor {
value = ((JSReferenceExpression)value).Referent;
var valueType = value.GetActualType(TypeSystem);
+ var cte = value as JSChangeTypeExpression;
+ var cast = value as JSCastExpression;
+
+ TypeReference originalType;
+ int temp;
+
+ if (cte != null) {
+ originalType = cte.Expression.GetActualType(TypeSystem);
+ } else if (cast != null) {
+ originalType = cast.Expression.GetActualType(TypeSystem);
+ } else {
+ originalType = null;
+ }
- if (!TypeUtil.IsStruct(valueType))
- return false;
+ if (originalType != null) {
+ originalType = TypeUtil.FullyDereferenceType(originalType, out temp);
+
+ if (!TypeUtil.IsStruct(valueType) && !TypeUtil.IsStruct(originalType))
+ return false;
+ } else {
+ if (!TypeUtil.IsStruct(valueType))
+ return false;
+ }
if (valueType.FullName.StartsWith("System.Nullable"))
return false;
View
4 JSIL/TypeUtil.cs
@@ -37,6 +37,10 @@ public static class TypeUtil {
if (git != null)
return git.IsValueType;
+ var gp = type as GenericParameter;
+ if (gp != null)
+ return gp.Constraints.Any((tr) => IsStruct(tr));
+
return (etype == MetadataType.ValueType);
}
View
3 Tests/ComparisonTests.cs
@@ -147,7 +147,8 @@ public class ComparisonTests : GenericTestFixture {
@"TestCases\StructThisAssignment.cs",
@"TestCases\SingleDimStructArrays.cs",
@"TestCases\MultiDimStructArrays.cs",
- @"TestCases\StructLateDeclaration.cs" // This test demonstrates a bug in IntroduceVariableDeclarations
+ @"TestCases\StructLateDeclaration.cs", // This test demonstrates a bug in IntroduceVariableDeclarations
+ @"TestCases\RefStructThisWithInterface.cs"
}, null, defaultProvider
);
}
View
39 Tests/TestCases/RefStructThisWithInterface.cs
@@ -0,0 +1,39 @@
+
+
+using System;
+
+public interface I {
+ int Value { get; set; }
+ void Method ();
+}
+
+public struct A : I {
+ public int Value { get; set; }
+
+ public void Method () {
+ Method2(ref this);
+ I test = this;
+ test.Value = 12;
+ Console.WriteLine(this.Value);
+ }
+
+ public void Method2<T> (ref T a) where T : I {
+ I copy = a;
+ a.Value += 2;
+ Console.WriteLine(copy.Value);
+ }
+}
+
+public static class Program {
+ public static void Test<T> (ref T obj) where T : I {
+ obj.Value = 4;
+ obj.Method();
+ Console.WriteLine(obj.Value);
+ }
+
+ public static void Main (string[] args) {
+ var obj = new A();
+ Test(ref obj);
+ }
+}
+
View
1 Tests/Tests.csproj
@@ -176,6 +176,7 @@
<None Include="SpecialTestCases\OverloadedGenericMethodSignatures2.cs" />
<None Include="SpecialTestCases\CustomObjectMethods.cs" />
<None Include="SpecialTestCases\CustomEqualsDispatch.cs" />
+ <None Include="TestCases\RefStructThisWithInterface.cs" />
<Compile Include="XMLTests.cs" />
<Compile Include="ReflectionTests.cs" />
<Compile Include="DependencyTests.cs" />

0 comments on commit 723cc1d

Please sign in to comment.