protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var itype = this.Emitter.BridgeTypes.ToType(type); bool isCastAttr; string castCode = this.GetCastCode(expression, type, out isCastAttr); if (itype != null && castCode == null && method != CS.Ops.CAST && itype.GetDefinition() != null && this.Emitter.Validator.IsObjectLiteral(itype.GetDefinition())) { throw new EmitterException(expression, "The type " + itype.FullName + " cannot be used in cast operation because there is no way to check its type"); } var enumType = itype; if (NullableType.IsNullable(enumType)) { enumType = NullableType.GetUnderlyingType(enumType); } var castToEnum = enumType.Kind == TypeKind.Enum; if (castToEnum) { itype = enumType.GetDefinition().EnumUnderlyingType; var enumMode = this.Emitter.Validator.EnumEmitMode(enumType); if (enumMode >= 3 && enumMode < 7) { itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } } if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter))) { if (expression is ParenthesizedExpression) { expression = ((ParenthesizedExpression)expression).Expression; } expression.AcceptVisitor(this.Emitter); return; } if (method == CS.Ops.CAST) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == CS.Ops.IS && castToEnum) { this.Write("Bridge.is("); expression.AcceptVisitor(this.Emitter); this.Write(", "); this.Write(BridgeTypes.ToJsName(itype, this.Emitter)); this.Write(")"); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Equals(itype)) { if (method == CS.Ops.IS) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); } expression.AcceptVisitor(this.Emitter); if (method == CS.Ops.IS) { this.Write(")"); } return; } bool isResultNullable = NullableType.IsNullable(typerr.Type); if (castCode != null) { this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method); return; } bool isCast = method == CS.Ops.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == CS.Ops.CAST || method == CS.Ops.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == CS.Ops.IS) { hasValue = true; method = "hasValue"; } } bool unbox = !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion; if (unbox) { this.Write("System.Nullable.getValue("); } this.Write(JS.NS.BRIDGE); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); this.EmitCastType(itype); } if (isResultNullable && method != CS.Ops.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); if (unbox) { this.Write(")"); } }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var itype = this.Emitter.BridgeTypes.ToType(type); bool isCastAttr; string castCode = this.GetCastCode(expression, type, method, out isCastAttr); var enumType = itype; if (NullableType.IsNullable(enumType)) { enumType = NullableType.GetUnderlyingType(enumType); } var castToEnum = enumType.Kind == TypeKind.Enum; if (castToEnum) { itype = enumType.GetDefinition().EnumUnderlyingType; var enumMode = Helpers.EnumEmitMode(enumType); if (enumMode >= 3 && enumMode < 7) { itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } } if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter)) || this.IsExternalCast(itype)) { if (expression is ParenthesizedExpression) { expression = ((ParenthesizedExpression)expression).Expression; } expression.AcceptVisitor(this.Emitter); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Kind == TypeKind.Enum) { var enumMode = Helpers.EnumEmitMode(expressionrr.Type); if (enumMode >= 3 && enumMode < 7 && Helpers.IsIntegerType(itype, this.Emitter.Resolver)) { throw new EmitterException(this.CastExpression, "Enum underlying type is string and cannot be casted to number"); } } if (method == CS.Ops.CAST && expressionrr.Type.Kind != TypeKind.Enum) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == CS.Ops.IS && castToEnum) { this.Write(JS.Types.Bridge.IS); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); this.Write(", "); this.Write(BridgeTypes.ToJsName(itype, this.Emitter)); this.Write(")"); return; } if (expressionrr.Type.Equals(itype)) { if (method == CS.Ops.IS) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); } expression.AcceptVisitor(this.Emitter); if (method == CS.Ops.IS) { this.Write(")"); } return; } bool isResultNullable = NullableType.IsNullable(typerr.Type); if (castCode != null) { this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method); return; } bool isCast = method == CS.Ops.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == CS.Ops.CAST || method == CS.Ops.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == CS.Ops.IS) { hasValue = true; method = "hasValue"; } } bool unbox = this.Emitter.Rules.Boxing == BoxingRule.Managed && !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion; if (unbox) { this.Write("System.Nullable.getValue("); } var typeDef = itype.Kind == TypeKind.TypeParameter ? null : this.Emitter.GetTypeDefinition(type, true); if (typeDef != null && method == CS.Ops.IS && itype.Kind != TypeKind.Interface && this.Emitter.Validator.IsObjectLiteral(typeDef) && this.Emitter.Validator.GetObjectCreateMode(typeDef) == 0) { throw new EmitterException(type, $"ObjectLiteral type ({itype.FullName}) with Plain mode cannot be used in 'is' operator. Please define cast logic in Cast attribute or use Constructor mode."); } this.Write(JS.NS.BRIDGE); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); this.EmitCastType(itype); } if (isResultNullable && method != CS.Ops.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); if (unbox) { this.Write(")"); } }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var castToEnum = this.Emitter.BridgeTypes.ToType(type).Kind == TypeKind.Enum; if (method != Bridge.Translator.Emitter.IS && (Helpers.IsIgnoreCast(type, this.Emitter) || castToEnum)) { expression.AcceptVisitor(this.Emitter); return; } if (method == Bridge.Translator.Emitter.CAST) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == Bridge.Translator.Emitter.IS && castToEnum) { this.Write("Bridge.hasValue("); expression.AcceptVisitor(this.Emitter); this.Write(")"); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Equals(typerr.Type)) { if (method == Bridge.Translator.Emitter.IS) { this.WriteScript(true); } else { expression.AcceptVisitor(this.Emitter); } return; } bool isInlineCast; string castCode = this.GetCastCode(expression, type, out isInlineCast); bool isNullable = NullableType.IsNullable(expressionrr.Type); bool isResultNullable = NullableType.IsNullable(typerr.Type); if (isInlineCast) { this.EmitInlineCast(expression, type, castCode); return; } bool isCast = method == Bridge.Translator.Emitter.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == Bridge.Translator.Emitter.CAST || method == Bridge.Translator.Emitter.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == Bridge.Translator.Emitter.IS) { hasValue = true; method = "hasValue"; } } this.Write(Bridge.Translator.Emitter.ROOT); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); if (castCode != null) { this.Write(castCode); } else { this.EmitCastType(type); } } if (isResultNullable && method != Bridge.Translator.Emitter.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var castToEnum = this.Emitter.BridgeTypes.ToType(type).Kind == TypeKind.Enum; if (method != Bridge.Translator.Emitter.IS && (Helpers.IsIgnoreCast(type, this.Emitter) || castToEnum)) { expression.AcceptVisitor(this.Emitter); return; } if (method == Bridge.Translator.Emitter.IS && castToEnum) { this.Write("Bridge.hasValue("); expression.AcceptVisitor(this.Emitter); this.Write(")"); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Equals(typerr.Type)) { if (method == Bridge.Translator.Emitter.IS) { this.WriteScript(true); } else { expression.AcceptVisitor(this.Emitter); } return; } bool isInlineCast; string castCode = this.GetCastCode(expression, type, out isInlineCast); bool isNullable = NullableType.IsNullable(expressionrr.Type); bool isResultNullable = NullableType.IsNullable(typerr.Type); if (isInlineCast) { if (isNullable) { isNullable = !NullableType.GetUnderlyingType(expressionrr.Type).Equals(typerr.Type); } this.EmitInlineCast(expression, type, castCode, isNullable, isResultNullable); return; } if (method == Bridge.Translator.Emitter.CAST) { if (Helpers.IsIntegerType(typerr.Type, this.Emitter.Resolver)) { if (expressionrr.Type != null && Helpers.IsFloatType(expressionrr.Type, this.Emitter.Resolver)) { this.Write("Bridge.Int.trunc("); if (isNullable && !isResultNullable) { this.Write("Bridge.Nullable.getValue("); } expression.AcceptVisitor(this.Emitter); if (isNullable && !isResultNullable) { this.WriteCloseParentheses(); } this.Write(")"); return; } } if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression)) { expression.AcceptVisitor(this.Emitter); return; } } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == Bridge.Translator.Emitter.CAST || method == Bridge.Translator.Emitter.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == Bridge.Translator.Emitter.IS) { hasValue = true; method = "hasValue"; } } this.Write(Bridge.Translator.Emitter.ROOT); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); if (isNullable && !isResultNullable) { this.Write("Bridge.Nullable.getValue("); } expression.AcceptVisitor(this.Emitter); if (isNullable && !isResultNullable) { this.WriteCloseParentheses(); } if (!hasValue) { this.WriteComma(); if (castCode != null) { this.Write(castCode); } else { this.EmitCastType(type); } } if (isResultNullable && method != Bridge.Translator.Emitter.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { if (method != Bridge.Translator.Emitter.IS && Helpers.IsIgnoreCast(type, this.Emitter)) { expression.AcceptVisitor(this.Emitter); return; } bool isInlineCast; string castCode = this.GetCastCode(expression, type, out isInlineCast); if (isInlineCast) { this.EmitInlineCast(expression, type, castCode); return; } if (method == Bridge.Translator.Emitter.CAST) { var resolveResult = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (Helpers.IsIntegerType(resolveResult.Type, this.Emitter.Resolver)) { var fromType = this.Emitter.Resolver.ResolveNode(this.CastExpression.Expression, this.Emitter).Type; if (fromType != null && Helpers.IsFloatType(fromType, this.Emitter.Resolver)) { this.Write("Bridge.Int.trunc("); expression.AcceptVisitor(this.Emitter); this.Write(")"); return; } } if (ConversionBlock.IsUserDefinedConversion(this, expression)) { expression.AcceptVisitor(this.Emitter); return; } } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == Bridge.Translator.Emitter.CAST || method == Bridge.Translator.Emitter.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == Bridge.Translator.Emitter.IS) { hasValue = true; method = "hasValue"; } } this.Write(Bridge.Translator.Emitter.ROOT); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); if (castCode != null) { this.Write(castCode); } else { this.EmitCastType(type); } } this.WriteCloseParentheses(); }