public void VisitNode(JSWriteThroughPointerExpression wtpe) { JSExpression newPointer, offset; if (ExtractOffsetFromPointerExpression(wtpe.Left, TypeSystem, out newPointer, out offset)) { // HACK: Is this right? if (wtpe.OffsetInBytes != null) { offset = new JSBinaryOperatorExpression(JSOperator.Add, wtpe.OffsetInBytes, offset, TypeSystem.Int32); } var replacement = new JSWriteThroughPointerExpression(newPointer, wtpe.Right, wtpe.ActualType, offset); ParentNode.ReplaceChild(wtpe, replacement); VisitReplacement(replacement); } else if (JSPointerExpressionUtil.UnwrapExpression(wtpe.Pointer) is JSBinaryOperatorExpression) { var replacement = new JSUntranslatableExpression("Write through confusing pointer " + wtpe.Pointer); ParentNode.ReplaceChild(wtpe, replacement); VisitReplacement(replacement); } else { VisitChildren(wtpe); } }
public void VisitNode(JSUntranslatableExpression ue) { Output.Identifier("JSIL.UntranslatableInstruction", null); Output.LPar(); Output.Value((ue.Type ?? "").ToString()); Output.RPar(); }
public void VisitNode (JSWriteThroughPointerExpression wtpe) { JSExpression newPointer, offset; if (ExtractOffsetFromPointerExpression(wtpe.Left, TypeSystem, out newPointer, out offset)) { var replacement = new JSWriteThroughPointerExpression(newPointer, wtpe.Right, wtpe.ActualType, offset); ParentNode.ReplaceChild(wtpe, replacement); VisitReplacement(replacement); } else if (JSPointerExpressionUtil.UnwrapExpression(wtpe.Pointer) is JSBinaryOperatorExpression) { var replacement = new JSUntranslatableExpression("Write through confusing pointer " + wtpe.Pointer); ParentNode.ReplaceChild(wtpe, replacement); VisitReplacement(replacement); } else { VisitChildren(wtpe); } }
public void VisitNode (JSReadThroughPointerExpression rtpe) { JSExpression newPointer, offset; if (ExtractOffsetFromPointerExpression(rtpe.Pointer, TypeSystem, out newPointer, out offset)) { var replacement = new JSReadThroughPointerExpression(newPointer, rtpe.ElementType, offset); ParentNode.ReplaceChild(rtpe, replacement); VisitReplacement(replacement); } else if (JSPointerExpressionUtil.UnwrapExpression(rtpe.Pointer) is JSBinaryOperatorExpression) { var replacement = new JSUntranslatableExpression("Read through confusing pointer " + rtpe.Pointer); ParentNode.ReplaceChild(rtpe, replacement); VisitReplacement(replacement); } else { VisitChildren(rtpe); } }
public void VisitNode(JSReadThroughPointerExpression rtpe) { JSExpression newPointer, offset; if (ExtractOffsetFromPointerExpression(rtpe.Pointer, TypeSystem, out newPointer, out offset)) { var replacement = new JSReadThroughPointerExpression(newPointer, rtpe.ElementType, offset); ParentNode.ReplaceChild(rtpe, replacement); VisitReplacement(replacement); } else if (JSPointerExpressionUtil.UnwrapExpression(rtpe.Pointer) is JSBinaryOperatorExpression) { var replacement = new JSUntranslatableExpression("Read through confusing pointer " + rtpe.Pointer); ParentNode.ReplaceChild(rtpe, replacement); VisitReplacement(replacement); } else { VisitChildren(rtpe); } }
public void VisitNode(JSCastExpression ce) { var currentType = ce.Expression.GetActualType(TypeSystem); var targetType = ce.NewType; JSExpression newExpression = null; if (targetType.MetadataType == MetadataType.Char) { newExpression = JSInvocationExpression.InvokeStatic( JS.fromCharCode, new[] { ce.Expression }, true ); } else if ( (currentType.MetadataType == MetadataType.Char) && TypeUtil.IsIntegral(targetType) ) { newExpression = JSInvocationExpression.InvokeMethod( JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true ); } else if ( IntroduceEnumCasts.IsEnumOrNullableEnum(currentType) ) { var enumInfo = TypeInfo.Get(currentType); if (targetType.MetadataType == MetadataType.Boolean) { EnumMemberInfo enumMember; if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.NotEqual, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.Equal, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else { newExpression = new JSUntranslatableExpression(String.Format( "Could not cast enum of type '{0}' to boolean because it has no zero value or one value", currentType.FullName )); } } else if (TypeUtil.IsNumeric(targetType)) { newExpression = JSInvocationExpression.InvokeStatic( JS.Number(targetType), new[] { ce.Expression }, true ); } else if (targetType.FullName == "System.Enum") { newExpression = ce.Expression; } else { // Debugger.Break(); } } else if ( targetType.MetadataType == MetadataType.Boolean ) { newExpression = new JSBinaryOperatorExpression( JSBinaryOperator.NotEqual, ce.Expression, new JSDefaultValueLiteral(currentType), TypeSystem.Boolean ); } else if ( TypeUtil.IsNumeric(targetType) && TypeUtil.IsNumeric(currentType) ) { if ( TypeUtil.IsIntegral(currentType) || !TypeUtil.IsIntegral(targetType) ) newExpression = ce.Expression; else newExpression = JSInvocationExpression.InvokeStatic(JS.floor, new[] { ce.Expression }, true); } else { // newExpression = JSIL.Cast(ce.Expression, targetType); } if (newExpression != null) { ParentNode.ReplaceChild(ce, newExpression); VisitReplacement(newExpression); } else { // Debugger.Break(); VisitChildren(ce); } }
public void VisitNode(JSCastExpression ce) { var currentType = ce.Expression.GetActualType(TypeSystem); var targetType = ce.NewType; JSExpression newExpression = null; if (targetType.FullName == "System.ValueType") { var replacement = ce.Expression; ParentNode.ReplaceChild(ce, replacement); VisitReplacement(replacement); return; } else if (targetType.MetadataType == MetadataType.Char) { newExpression = JSInvocationExpression.InvokeStatic( JS.fromCharCode, new[] { ce.Expression }, true ); } else if ( (currentType.MetadataType == MetadataType.Char) && TypeUtil.IsIntegral(targetType) ) { newExpression = JSInvocationExpression.InvokeMethod( JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true ); } else if ( IntroduceEnumCasts.IsEnumOrNullableEnum(currentType) ) { var enumInfo = TypeInfo.Get(currentType); var isNullable = TypeUtil.IsNullable(currentType); if (targetType.MetadataType == MetadataType.Boolean) { EnumMemberInfo enumMember; if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.NotEqual, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.Equal, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else { newExpression = new JSUntranslatableExpression(String.Format( "Could not cast enum of type '{0}' to boolean because it has no zero value or one value", currentType.FullName )); } } else if (TypeUtil.IsNumeric(targetType)) { if (isNullable) { newExpression = JSIL.ValueOfNullable( ce.Expression ); } else { newExpression = JSInvocationExpression.InvokeMethod( JS.valueOf(targetType), ce.Expression, null, true ); } } else if (targetType.FullName == "System.Enum") { newExpression = ce.Expression; } else { // Debugger.Break(); } } else if ( (targetType.MetadataType == MetadataType.Boolean) && // A cast from Object to Boolean can occur in two forms: // An implied conversion, where an object expression is treated as a boolean (logicnot operation, etc). // In this case, we want to do 'obj != null' to make it a boolean. // An explicit conversion, where an object expression is unboxed to boolean. // In this case we want to leave it as-is. (ce.IsCoercion || (currentType.FullName != "System.Object")) ) { JSLiteral nullLiteral; // HACK: Necessary because we represent Char instances as JS strings. Issue #150 // Is this right? if (currentType.FullName == "System.Char") nullLiteral = new JSDefaultValueLiteral(currentType); else nullLiteral = new JSNullLiteral(currentType); newExpression = new JSBinaryOperatorExpression( JSBinaryOperator.NotEqual, ce.Expression, nullLiteral, TypeSystem.Boolean ); } else if ( TypeUtil.IsNumeric(targetType) && TypeUtil.IsNumeric(currentType) && !TypeUtil.TypesAreEqual(targetType, currentType, true) ) { if (currentType.MetadataType == MetadataType.Int64) { if (targetType.MetadataType == MetadataType.UInt64) { newExpression = JSInvocationExpression .InvokeMethod( TypeSystem.Int64, new JSFakeMethod("ToUInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory), ce.Expression); } else { newExpression = JSInvocationExpression .InvokeMethod( TypeSystem.Int64, new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory), ce.Expression); } } else if (currentType.MetadataType == MetadataType.UInt64) { if (targetType.MetadataType == MetadataType.Int64) { newExpression = JSInvocationExpression .InvokeMethod( TypeSystem.Int64, new JSFakeMethod("ToInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory), ce.Expression); } else { newExpression = JSInvocationExpression .InvokeMethod( TypeSystem.Int64, new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory), ce.Expression); } } else if (targetType.MetadataType == MetadataType.Int64) { newExpression = JSInvocationExpression.InvokeStatic( new JSType(TypeSystem.Int64), new JSFakeMethod("FromNumber", TypeSystem.Int64, new[] { currentType }, MethodTypeFactory), new[] { ce.Expression }, true); } else if (targetType.MetadataType == MetadataType.UInt64) { newExpression = JSInvocationExpression.InvokeStatic( new JSType(TypeSystem.UInt64), new JSFakeMethod("FromNumber", TypeSystem.UInt64, new[] { currentType }, MethodTypeFactory), new[] { ce.Expression }, true); } else if ( TypeUtil.IsIntegral(currentType) || !TypeUtil.IsIntegral(targetType)) { newExpression = ce.Expression; } else { newExpression = new JSTruncateExpression(ce.Expression); } } else { // newExpression = JSIL.Cast(ce.Expression, targetType); } if (newExpression != null) { ParentNode.ReplaceChild(ce, newExpression); VisitReplacement(newExpression); } else { // Debugger.Break(); VisitChildren(ce); } }
public void VisitNode(JSCastExpression ce) { var currentType = ce.Expression.GetActualType(TypeSystem); var targetType = ce.NewType; JSExpression newExpression = null; if (targetType.MetadataType == MetadataType.Char) { newExpression = JSInvocationExpression.InvokeStatic( JS.fromCharCode, new[] { ce.Expression }, true ); } else if ( (currentType.MetadataType == MetadataType.Char) && TypeUtil.IsIntegral(targetType) ) { newExpression = JSInvocationExpression.InvokeMethod( JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true ); } else if ( IntroduceEnumCasts.IsEnumOrNullableEnum(currentType) ) { var enumInfo = TypeInfo.Get(currentType); if (targetType.MetadataType == MetadataType.Boolean) { EnumMemberInfo enumMember; if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.NotEqual, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.Equal, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else { newExpression = new JSUntranslatableExpression(String.Format( "Could not cast enum of type '{0}' to boolean because it has no zero value or one value", currentType.FullName )); } } else if (TypeUtil.IsNumeric(targetType)) { newExpression = JSInvocationExpression.InvokeStatic( JS.Number(targetType), new[] { ce.Expression }, true ); } else if (targetType.FullName == "System.Enum") { newExpression = ce.Expression; } else { // Debugger.Break(); } } else if ( targetType.MetadataType == MetadataType.Boolean ) { newExpression = new JSBinaryOperatorExpression( JSBinaryOperator.NotEqual, ce.Expression, new JSDefaultValueLiteral(currentType), TypeSystem.Boolean ); } else if ( TypeUtil.IsNumeric(targetType) && TypeUtil.IsNumeric(currentType) ) { if ( TypeUtil.IsIntegral(currentType) || !TypeUtil.IsIntegral(targetType) ) { newExpression = ce.Expression; } else { newExpression = JSInvocationExpression.InvokeStatic(JS.floor, new[] { ce.Expression }, true); } } else { newExpression = JSIL.Cast(ce.Expression, targetType); } if (newExpression != null) { ParentNode.ReplaceChild(ce, newExpression); VisitReplacement(newExpression); } else { // Debugger.Break(); VisitChildren(ce); } }
public void VisitNode(JSCastExpression ce) { var currentType = ce.Expression.GetActualType(TypeSystem); var targetType = ce.NewType; JSExpression newExpression = null; if (targetType.FullName == "System.ValueType") { var replacement = ce.Expression; ParentNode.ReplaceChild(ce, replacement); VisitReplacement(replacement); return; } else if (targetType.MetadataType == MetadataType.Char) { newExpression = JSInvocationExpression.InvokeStatic( JS.fromCharCode, new[] { ce.Expression }, true ); } else if ( (currentType.MetadataType == MetadataType.Char) && TypeUtil.IsIntegral(targetType) ) { newExpression = JSInvocationExpression.InvokeMethod( JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true ); } else if ( IntroduceEnumCasts.IsEnumOrNullableEnum(currentType) ) { TypeInfo enumInfo; var isNullable = TypeUtil.IsNullable(currentType); if (isNullable) { int temp; var git = (GenericInstanceType)TypeUtil.FullyDereferenceType(currentType, out temp); enumInfo = TypeInfo.Get(git.GenericArguments[0]); } else { enumInfo = TypeInfo.Get(currentType); } if (enumInfo == null) throw new InvalidOperationException("Unable to extract enum type from typereference " + currentType); if (targetType.MetadataType == MetadataType.Boolean) { EnumMemberInfo enumMember; if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.NotEqual, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.Equal, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else { newExpression = new JSUntranslatableExpression(String.Format( "Could not cast enum of type '{0}' to boolean because it has no zero value or one value", currentType.FullName )); } } else if (TypeUtil.IsNumeric(targetType)) { if (isNullable) { newExpression = JSIL.ValueOfNullable( ce.Expression ); } else if ( ce.Expression is JSCastExpression && (((JSCastExpression)ce.Expression).Expression.GetActualType(TypeSystem).MetadataType == MetadataType.Int64 || ((JSCastExpression)ce.Expression).Expression.GetActualType(TypeSystem).MetadataType == MetadataType.UInt64) ) { newExpression = ce.Expression; } else { newExpression = JSInvocationExpression.InvokeMethod( JS.valueOf(targetType), ce.Expression, null, true ); } } else if (targetType.FullName == "System.Enum") { newExpression = ce.Expression; } else { // Debugger.Break(); } } else if ( (targetType.MetadataType == MetadataType.Boolean) && (ce.Expression is JSAsExpression) && ((JSAsExpression)ce.Expression).GetActualType(TypeSystem) is GenericParameter ) { // C# expressions such as (t is T) (where T is a generic parameter). See issue #150. // Tested with AsWithGenericParameter.cs newExpression = new JSBinaryOperatorExpression( JSBinaryOperator.NotEqual, ce.Expression, new JSNullLiteral(currentType), TypeSystem.Boolean ); } else if ( (targetType.MetadataType == MetadataType.Boolean) && // A cast from Object to Boolean can occur in two forms: // An implied conversion, where an object expression is treated as a boolean (logicnot operation, etc). // In this case, we want to do 'obj != null' to make it a boolean. // An explicit conversion, where an object expression is unboxed to boolean. // In this case we want to leave it as-is. (ce.IsCoercion || (currentType.FullName != "System.Object")) ) { newExpression = new JSBinaryOperatorExpression( JSBinaryOperator.NotEqual, ce.Expression, new JSDefaultValueLiteral(currentType), TypeSystem.Boolean ); } else if ( TypeUtil.IsNumeric(targetType) && TypeUtil.IsNumeric(currentType) && !TypeUtil.TypesAreEqual(targetType, currentType, true) ) { if (currentType.MetadataType == MetadataType.Int64) { if (targetType.MetadataType == MetadataType.UInt64) { newExpression = JSInvocationExpression .InvokeMethod( TypeSystem.Int64, new JSFakeMethod("ToUInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory), ce.Expression); } else { newExpression = JSInvocationExpression .InvokeMethod( TypeSystem.Int64, new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory), ce.Expression); } } else if (currentType.MetadataType == MetadataType.UInt64) { if (targetType.MetadataType == MetadataType.Int64) { newExpression = JSInvocationExpression .InvokeMethod( TypeSystem.Int64, new JSFakeMethod("ToInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory), ce.Expression); } else { newExpression = JSInvocationExpression .InvokeMethod( TypeSystem.Int64, new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory), ce.Expression); } } else if (targetType.MetadataType == MetadataType.Int64) { newExpression = JSInvocationExpression.InvokeStatic( new JSType(TypeSystem.Int64), new JSFakeMethod("FromNumber", TypeSystem.Int64, new[] { currentType }, MethodTypeFactory), new[] { ce.Expression }, true); } else if (targetType.MetadataType == MetadataType.UInt64) { newExpression = JSInvocationExpression.InvokeStatic( new JSType(TypeSystem.UInt64), new JSFakeMethod("FromNumber", TypeSystem.UInt64, new[] { currentType }, MethodTypeFactory), new[] { ce.Expression }, true); } else if ( TypeUtil.IsIntegral(currentType) || !TypeUtil.IsIntegral(targetType)) { newExpression = ce.Expression; } else { newExpression = new JSTruncateExpression(ce.Expression); } } else { // newExpression = JSIL.Cast(ce.Expression, targetType); } if (newExpression != null) { ParentNode.ReplaceChild(ce, newExpression); VisitReplacement(newExpression); } else { // Debugger.Break(); VisitChildren(ce); } }
public void VisitNode(JSCastExpression ce) { var currentType = ce.Expression.GetActualType(TypeSystem); var targetType = ce.NewType; JSExpression newExpression = null; if (targetType.FullName == "System.ValueType") { var replacement = ce.Expression; ParentNode.ReplaceChild(ce, replacement); VisitReplacement(replacement); return; } else if (targetType.MetadataType == MetadataType.Char) { newExpression = JSInvocationExpression.InvokeStatic( JS.fromCharCode, new[] { ce.Expression }, true ); } else if ( (currentType.MetadataType == MetadataType.Char) && TypeUtil.IsIntegral(targetType) ) { newExpression = JSInvocationExpression.InvokeMethod( JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true ); } else if ( IntroduceEnumCasts.IsEnumOrNullableEnum(currentType) ) { var enumInfo = TypeInfo.Get(currentType); var isNullable = TypeUtil.IsNullable(currentType); if (targetType.MetadataType == MetadataType.Boolean) { EnumMemberInfo enumMember; if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.NotEqual, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.Equal, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else { newExpression = new JSUntranslatableExpression(String.Format( "Could not cast enum of type '{0}' to boolean because it has no zero value or one value", currentType.FullName )); } } else if (TypeUtil.IsNumeric(targetType)) { if (isNullable) { newExpression = JSIL.ValueOfNullable( ce.Expression ); } else { newExpression = JSInvocationExpression.InvokeMethod( JS.valueOf(targetType), ce.Expression, null, true ); } } else if (targetType.FullName == "System.Enum") { newExpression = ce.Expression; } else { // Debugger.Break(); } } else if ( (targetType.MetadataType == MetadataType.Boolean) && // A cast from Object to Boolean can occur in two forms: // An implied conversion, where an object expression is treated as a boolean (logicnot operation, etc). // In this case, we want to do 'obj != null' to make it a boolean. // An explicit conversion, where an object expression is unboxed to boolean. // In this case we want to leave it as-is. (ce.IsCoercion || (currentType.FullName != "System.Object")) ) { newExpression = new JSBinaryOperatorExpression( JSBinaryOperator.NotEqual, ce.Expression, new JSDefaultValueLiteral(currentType), TypeSystem.Boolean ); } else if ( TypeUtil.IsNumeric(targetType) && TypeUtil.IsNumeric(currentType) ) { if ( TypeUtil.IsIntegral(currentType) || !TypeUtil.IsIntegral(targetType) ) { newExpression = ce.Expression; } else { newExpression = new JSTruncateExpression(ce.Expression); } } else { // newExpression = JSIL.Cast(ce.Expression, targetType); } if (newExpression != null) { ParentNode.ReplaceChild(ce, newExpression); VisitReplacement(newExpression); } else { // Debugger.Break(); VisitChildren(ce); } }
public void VisitNode(JSCastExpression ce) { var currentType = ce.Expression.GetExpectedType(TypeSystem); var targetType = ce.NewType; JSExpression newExpression = null; if (ILBlockTranslator.IsEnum(currentType)) { var enumInfo = TypeInfo.GetExisting(currentType); if (targetType.MetadataType == MetadataType.Boolean) { EnumMemberInfo enumMember; if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.NotEqual, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) { newExpression = new JSBinaryOperatorExpression( JSOperator.Equal, ce.Expression, new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean ); } else { newExpression = new JSUntranslatableExpression(String.Format( "Could not cast enum of type '{0}' to boolean because it has no zero value or one value", currentType.FullName )); } } } if (newExpression != null) { ParentNode.ReplaceChild(ce, newExpression); VisitReplacement(newExpression); } else { VisitChildren(ce); } }