public void WriteNullableTypes1() { var engine = new FileHelperEngine<NullableType>(); var toWrite = new System.Collections.Generic.List<NullableType>(); NullableType record; record = new NullableType(); record.Field1 = new DateTime(1314, 12, 11); record.Field2 = "901"; record.Field3 = 234; toWrite.Add(record); record = new NullableType(); record.Field1 = null; record.Field2 = "012"; record.Field3 = null; toWrite.Add(record); record = new NullableType(); record.Field1 = new DateTime(1316, 5, 6); record.Field2 = "111"; record.Field3 = 4; toWrite.Add(record); NullableType[] res = engine.ReadString(engine.WriteString(toWrite)); Assert.AreEqual(3, res.Length); Assert.AreEqual(3, engine.TotalRecords); Assert.AreEqual(0, engine.ErrorManager.ErrorCount); Assert.AreEqual(new DateTime(1314, 12, 11), res[0].Field1); Assert.AreEqual("901", res[0].Field2); Assert.AreEqual(234, res[0].Field3); Assert.IsNull(res[1].Field1); Assert.AreEqual("012", res[1].Field2); Assert.IsNull(res[1].Field3); Assert.AreEqual(new DateTime(1316, 5, 6), res[2].Field1); Assert.AreEqual("", engine.WriteString(toWrite).Split(new string[] {Environment.NewLine}, StringSplitOptions.None)[1]. Substring(0, 8).Trim()); }
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 = !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(")"); } }
public static string ToTypeScriptName(IType type, IEmitter emitter, bool asDefinition = false, bool excludens = false, bool ignoreDependency = false) { if (type.Kind == TypeKind.Delegate) { var method = type.GetDelegateInvokeMethod(); StringBuilder sb = new StringBuilder(); sb.Append("{"); sb.Append("("); var last = method.Parameters.LastOrDefault(); foreach (var p in method.Parameters) { var ptype = BridgeTypes.ToTypeScriptName(p.Type, emitter); if (p.IsOut || p.IsRef) { ptype = "{v: " + ptype + "}"; } sb.Append(p.Name + ": " + ptype); if (p != last) { sb.Append(", "); } } sb.Append(")"); sb.Append(": "); sb.Append(BridgeTypes.ToTypeScriptName(method.ReturnType, emitter)); sb.Append("}"); return(sb.ToString()); } if (type.IsKnownType(KnownTypeCode.String)) { return("string"); } if (type.IsKnownType(KnownTypeCode.Boolean)) { return("boolean"); } if (type.IsKnownType(KnownTypeCode.Void)) { return("void"); } if (type.IsKnownType(KnownTypeCode.Byte) || type.IsKnownType(KnownTypeCode.Char) || type.IsKnownType(KnownTypeCode.Decimal) || type.IsKnownType(KnownTypeCode.Double) || type.IsKnownType(KnownTypeCode.Int16) || type.IsKnownType(KnownTypeCode.Int32) || type.IsKnownType(KnownTypeCode.Int64) || type.IsKnownType(KnownTypeCode.SByte) || type.IsKnownType(KnownTypeCode.Single) || type.IsKnownType(KnownTypeCode.UInt16) || type.IsKnownType(KnownTypeCode.UInt32) || type.IsKnownType(KnownTypeCode.UInt64)) { return("number"); } if (type.Kind == TypeKind.Array) { ICSharpCode.NRefactory.TypeSystem.ArrayType arrayType = (ICSharpCode.NRefactory.TypeSystem.ArrayType)type; return(BridgeTypes.ToTypeScriptName(arrayType.ElementType, emitter, asDefinition, excludens) + "[]"); } if (type.Kind == TypeKind.Dynamic) { return("any"); } if (type.Kind == TypeKind.Enum && type.DeclaringType != null && !excludens) { return("number"); } if (NullableType.IsNullable(type)) { return(BridgeTypes.ToTypeScriptName(NullableType.GetUnderlyingType(type), emitter, asDefinition, excludens)); } BridgeType bridgeType = emitter.BridgeTypes.Get(type, true); //string name = BridgeTypes.ConvertName(excludens ? type.Name : type.FullName); var name = excludens ? "" : type.Namespace; var hasTypeDef = bridgeType != null && bridgeType.TypeDefinition != null; if (hasTypeDef) { var typeDef = bridgeType.TypeDefinition; if (typeDef.IsNested && !excludens) { name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(typeDef); } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(typeDef.Name); } else { if (type.DeclaringType != null && !excludens) { name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(type); if (type.DeclaringType.TypeArguments.Count > 0) { name += "$" + type.TypeArguments.Count; } } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(type.Name); } bool isCustomName = false; if (bridgeType != null) { if (!ignoreDependency && emitter.AssemblyInfo.OutputBy != OutputBy.Project && bridgeType.TypeInfo != null && bridgeType.TypeInfo.Namespace != emitter.TypeInfo.Namespace) { var info = BridgeTypes.GetNamespaceFilename(bridgeType.TypeInfo, emitter); var ns = info.Item1; var fileName = info.Item2; if (!emitter.CurrentDependencies.Any(d => d.DependencyName == fileName)) { emitter.CurrentDependencies.Add(new ModuleDependency() { DependencyName = fileName }); } } name = BridgeTypes.AddModule(name, bridgeType, out isCustomName); } if (!hasTypeDef && !isCustomName && type.TypeArguments.Count > 0) { name += "$" + type.TypeArguments.Count; } if (!asDefinition && type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(type, emitter)) { StringBuilder sb = new StringBuilder(name); bool needComma = false; sb.Append("<"); foreach (var typeArg in type.TypeArguments) { if (needComma) { sb.Append(","); } needComma = true; sb.Append(BridgeTypes.ToTypeScriptName(typeArg, emitter, asDefinition, excludens)); } sb.Append(">"); name = sb.ToString(); } return(name); }
/// <summary> /// Determines whether a variable should be inlined in non-aggressive mode, even though it is not a generated variable. /// </summary> /// <param name="next">The next top-level expression</param> /// <param name="loadInst">The load within 'next'</param> /// <param name="inlinedExpression">The expression being inlined</param> static bool NonAggressiveInlineInto(ILInstruction next, ILInstruction loadInst, ILInstruction inlinedExpression, ILVariable v) { Debug.Assert(loadInst.IsDescendantOf(next)); // decide based on the source expression being inlined switch (inlinedExpression.OpCode) { case OpCode.DefaultValue: case OpCode.StObj: case OpCode.CompoundAssignmentInstruction: case OpCode.Await: return(true); case OpCode.LdLoc: if (v.StateMachineField == null && ((LdLoc)inlinedExpression).Variable.StateMachineField != null) { // Roslyn likes to put the result of fetching a state machine field into a temporary variable, // so inline more aggressively in such cases. return(true); } break; } var parent = loadInst.Parent; if (parent is ILiftableInstruction liftable && liftable.IsLifted) { return(true); // inline into lifted operators } if (parent is NullCoalescingInstruction && NullableType.IsNullable(v.Type)) { return(true); // inline nullables into ?? operator } // decide based on the target into which we are inlining switch (next.OpCode) { case OpCode.Leave: return(parent == next); case OpCode.IfInstruction: while (parent.MatchLogicNot(out _)) { parent = parent.Parent; } return(parent == next); case OpCode.BlockContainer: if (((BlockContainer)next).EntryPoint.Instructions[0] is SwitchInstruction switchInst) { next = switchInst; goto case OpCode.SwitchInstruction; } else { return(false); } case OpCode.SwitchInstruction: return(parent == next || (parent.MatchBinaryNumericInstruction(BinaryNumericOperator.Sub) && parent.Parent == next)); default: return(false); } }
public Expression ResolveBinaryOperator(ResolveContext rc, BinaryOperatorType op, Expression lhs, Expression rhs) { // V# 4.0 spec: §7.3.4 Binary operator overload resolution string overloadableOperatorName = ResolveContext.GetOverloadableOperatorName(op); if (overloadableOperatorName == null) { // Handle logical and/or exactly as bitwise and/or: // - If the user overloads a bitwise operator, that implicitly creates the corresponding logical operator. // - If both inputs are compile-time constants, it doesn't matter that we don't short-circuit. // - If inputs aren't compile-time constants, we don't evaluate anything, so again it doesn't matter that we don't short-circuit if (op == BinaryOperatorType.LogicalAnd) { overloadableOperatorName = ResolveContext.GetOverloadableOperatorName(BinaryOperatorType.BitwiseAnd); } else if (op == BinaryOperatorType.LogicalOr) { overloadableOperatorName = ResolveContext.GetOverloadableOperatorName(BinaryOperatorType.BitwiseOr); } else if (op == BinaryOperatorType.NullCoalescing) { // null coalescing operator is not overloadable and needs to be handled separately return(ResolveNullCoalescingOperator(rc, lhs, rhs)); } else { return(ErrorExpression.UnknownError); } } // If the type is nullable, get the underlying type: bool isNullable = NullableType.IsNullable(lhs.Type) || NullableType.IsNullable(rhs.Type); IType lhsType = NullableType.GetUnderlyingType(lhs.Type); IType rhsType = NullableType.GetUnderlyingType(rhs.Type); // the operator is overloadable: OverloadResolution userDefinedOperatorOR = rc.CreateOverloadResolution(new[] { lhs, rhs }); HashSet <IParameterizedMember> userOperatorCandidates = new HashSet <IParameterizedMember>(); userOperatorCandidates.UnionWith(rc.GetUserDefinedOperatorCandidates(lhsType, overloadableOperatorName)); userOperatorCandidates.UnionWith(rc.GetUserDefinedOperatorCandidates(rhsType, overloadableOperatorName)); foreach (var candidate in userOperatorCandidates) { userDefinedOperatorOR.AddCandidate(candidate); } if (userDefinedOperatorOR.FoundApplicableCandidate) { return(SetUserDefinedOperationInformations(rc, userDefinedOperatorOR)); } if (lhsType.Kind == TypeKind.Null && rhsType.IsReferenceType == false || lhsType.IsReferenceType == false && rhsType.Kind == TypeKind.Null) { isNullable = true; } if (op == BinaryOperatorType.LeftShift || op == BinaryOperatorType.RightShift) { // special case: the shift operators allow "var x = null << null", producing int?. if (lhsType.Kind == TypeKind.Null && rhsType.Kind == TypeKind.Null) { isNullable = true; } // for shift operators, do unary promotion independently on both arguments lhs = UnaryNumericPromotion(rc, UnaryOperatorType.UnaryPlus, ref lhsType, isNullable, lhs); rhs = UnaryNumericPromotion(rc, UnaryOperatorType.UnaryPlus, ref rhsType, isNullable, rhs); } else { bool allowNullableConstants = op == BinaryOperatorType.Equality || op == BinaryOperatorType.Inequality; if (!BinaryNumericPromotion(rc, isNullable, ref lhs, ref rhs, allowNullableConstants)) { return(new ErrorExpression(lhs.Type)); } } // re-read underlying types after numeric promotion lhsType = NullableType.GetUnderlyingType(lhs.Type); rhsType = NullableType.GetUnderlyingType(rhs.Type); IEnumerable <VSharpOperators.OperatorMethod> methodGroup; VSharpOperators operators = VSharpOperators.Get(rc.compilation); switch (op) { case BinaryOperatorType.Multiply: methodGroup = operators.MultiplicationOperators; break; case BinaryOperatorType.Division: methodGroup = operators.DivisionOperators; break; case BinaryOperatorType.Modulus: methodGroup = operators.RemainderOperators; break; case BinaryOperatorType.Addition: methodGroup = operators.AdditionOperators; { if (lhsType.Kind == TypeKind.Enum) { // E operator +(E x, U y); IType underlyingType = MakeNullable(rc, ResolveContext.GetEnumUnderlyingType(lhsType), isNullable); if (rc.TryConvertEnum(ref rhs, underlyingType, ref isNullable, ref lhs)) { return(HandleEnumOperator(rc, isNullable, lhsType, op, lhs, rhs)); } } if (rhsType.Kind == TypeKind.Enum) { // E operator +(U x, E y); IType underlyingType = MakeNullable(rc, ResolveContext.GetEnumUnderlyingType(rhsType), isNullable); if (rc.TryConvertEnum(ref lhs, underlyingType, ref isNullable, ref rhs)) { return(HandleEnumOperator(rc, isNullable, rhsType, op, lhs, rhs)); } } if (lhsType.Kind == TypeKind.Delegate && rc.TryConvert(ref rhs, lhsType)) { return(SetOperationInformations(rc, lhsType, lhs, op, rhs)); } else if (rhsType.Kind == TypeKind.Delegate && rc.TryConvert(ref lhs, rhsType)) { return(SetOperationInformations(rc, rhsType, lhs, op, rhs)); } if (lhsType is PointerTypeSpec) { methodGroup = new[] { PointerArithmeticOperator(rc, lhsType, lhsType, KnownTypeCode.Int32), PointerArithmeticOperator(rc, lhsType, lhsType, KnownTypeCode.UInt32), PointerArithmeticOperator(rc, lhsType, lhsType, KnownTypeCode.Int64), PointerArithmeticOperator(rc, lhsType, lhsType, KnownTypeCode.UInt64) }; } else if (rhsType is PointerTypeSpec) { methodGroup = new[] { PointerArithmeticOperator(rc, rhsType, KnownTypeCode.Int32, rhsType), PointerArithmeticOperator(rc, rhsType, KnownTypeCode.UInt32, rhsType), PointerArithmeticOperator(rc, rhsType, KnownTypeCode.Int64, rhsType), PointerArithmeticOperator(rc, rhsType, KnownTypeCode.UInt64, rhsType) }; } if (lhsType.Kind == TypeKind.Null && rhsType.Kind == TypeKind.Null) { return(new ErrorExpression(SpecialTypeSpec.NullType)); } } break; case BinaryOperatorType.Subtraction: methodGroup = operators.SubtractionOperators; { if (lhsType.Kind == TypeKind.Enum) { // U operator –(E x, E y); if (rc.TryConvertEnum(ref rhs, lhs.Type, ref isNullable, ref lhs, allowConversionFromConstantZero: false)) { return(HandleEnumSubtraction(rc, isNullable, lhsType, lhs, rhs)); } // E operator –(E x, U y); IType underlyingType = MakeNullable(rc, ResolveContext.GetEnumUnderlyingType(lhsType), isNullable); if (rc.TryConvertEnum(ref rhs, underlyingType, ref isNullable, ref lhs)) { return(HandleEnumOperator(rc, isNullable, lhsType, op, lhs, rhs)); } } if (rhsType.Kind == TypeKind.Enum) { // U operator –(E x, E y); if (rc.TryConvertEnum(ref lhs, rhs.Type, ref isNullable, ref rhs, allowConversionFromConstantZero: false)) { return(HandleEnumSubtraction(rc, isNullable, rhsType, lhs, rhs)); } // E operator -(U x, E y); IType underlyingType = MakeNullable(rc, ResolveContext.GetEnumUnderlyingType(rhsType), isNullable); if (rc.TryConvertEnum(ref lhs, underlyingType, ref isNullable, ref rhs)) { return(HandleEnumOperator(rc, isNullable, rhsType, op, lhs, rhs)); } } if (lhsType.Kind == TypeKind.Delegate && rc.TryConvert(ref rhs, lhsType)) { return(SetOperationInformations(rc, lhsType, lhs, op, rhs)); } else if (rhsType.Kind == TypeKind.Delegate && rc.TryConvert(ref lhs, rhsType)) { return(SetOperationInformations(rc, rhsType, lhs, op, rhs)); } if (lhsType is PointerTypeSpec) { if (rhsType is PointerTypeSpec) { IType int64 = rc.compilation.FindType(KnownTypeCode.Int64); if (lhsType.Equals(rhsType)) { return(SetOperationInformations(rc, int64, lhs, op, rhs)); } else { return(new ErrorExpression(int64)); } } methodGroup = new[] { PointerArithmeticOperator(rc, lhsType, lhsType, KnownTypeCode.Int32), PointerArithmeticOperator(rc, lhsType, lhsType, KnownTypeCode.UInt32), PointerArithmeticOperator(rc, lhsType, lhsType, KnownTypeCode.Int64), PointerArithmeticOperator(rc, lhsType, lhsType, KnownTypeCode.UInt64) }; } if (lhsType.Kind == TypeKind.Null && rhsType.Kind == TypeKind.Null) { return(new ErrorExpression(SpecialTypeSpec.NullType)); } } break; case BinaryOperatorType.LeftShift: methodGroup = operators.ShiftLeftOperators; break; case BinaryOperatorType.RightShift: methodGroup = operators.ShiftRightOperators; break; case BinaryOperatorType.RotateRight: methodGroup = operators.RotateRightOperators; break; case BinaryOperatorType.RotateLeft: methodGroup = operators.RotateLeftOperators; break; case BinaryOperatorType.Equality: case BinaryOperatorType.Inequality: case BinaryOperatorType.LessThan: case BinaryOperatorType.GreaterThan: case BinaryOperatorType.LessThanOrEqual: case BinaryOperatorType.GreaterThanOrEqual: { if (lhsType.Kind == TypeKind.Enum && rc.TryConvert(ref rhs, lhs.Type)) { // bool operator op(E x, E y); return(HandleEnumComparison(rc, op, lhsType, isNullable, lhs, rhs)); } else if (rhsType.Kind == TypeKind.Enum && rc.TryConvert(ref lhs, rhs.Type)) { // bool operator op(E x, E y); return(HandleEnumComparison(rc, op, rhsType, isNullable, lhs, rhs)); } else if (lhsType is PointerTypeSpec && rhsType is PointerTypeSpec) { return(SetOperationInformations(rc, rc.compilation.FindType(KnownTypeCode.Boolean), lhs, op, rhs)); } if (op == BinaryOperatorType.Equality || op == BinaryOperatorType.Inequality) { if (lhsType.IsReferenceType == true && rhsType.IsReferenceType == true) { // If it's a reference comparison if (op == BinaryOperatorType.Equality) { methodGroup = operators.ReferenceEqualityOperators; } else { methodGroup = operators.ReferenceInequalityOperators; } break; } else if (lhsType.Kind == TypeKind.Null && IsNullableTypeOrNonValueType(rhs.Type) || IsNullableTypeOrNonValueType(lhs.Type) && rhsType.Kind == TypeKind.Null) { // compare type parameter or nullable type with the null literal return(SetOperationInformations(rc, rc.compilation.FindType(KnownTypeCode.Boolean), lhs, op, rhs)); } } switch (op) { case BinaryOperatorType.Equality: methodGroup = operators.ValueEqualityOperators; break; case BinaryOperatorType.Inequality: methodGroup = operators.ValueInequalityOperators; break; case BinaryOperatorType.LessThan: methodGroup = operators.LessThanOperators; break; case BinaryOperatorType.GreaterThan: methodGroup = operators.GreaterThanOperators; break; case BinaryOperatorType.LessThanOrEqual: methodGroup = operators.LessThanOrEqualOperators; break; case BinaryOperatorType.GreaterThanOrEqual: methodGroup = operators.GreaterThanOrEqualOperators; break; default: throw new InvalidOperationException(); } } break; case BinaryOperatorType.BitwiseAnd: case BinaryOperatorType.BitwiseOr: case BinaryOperatorType.ExclusiveOr: { if (lhsType.Kind == TypeKind.Enum) { // bool operator op(E x, E y); if (rc.TryConvertEnum(ref rhs, lhs.Type, ref isNullable, ref lhs)) { return(HandleEnumOperator(rc, isNullable, lhsType, op, lhs, rhs)); } } if (rhsType.Kind == TypeKind.Enum) { // bool operator op(E x, E y); if (rc.TryConvertEnum(ref lhs, rhs.Type, ref isNullable, ref rhs)) { return(HandleEnumOperator(rc, isNullable, rhsType, op, lhs, rhs)); } } switch (op) { case BinaryOperatorType.BitwiseAnd: methodGroup = operators.BitwiseAndOperators; break; case BinaryOperatorType.BitwiseOr: methodGroup = operators.BitwiseOrOperators; break; case BinaryOperatorType.ExclusiveOr: methodGroup = operators.BitwiseXorOperators; break; default: throw new InvalidOperationException(); } } break; case BinaryOperatorType.LogicalAnd: methodGroup = operators.LogicalAndOperators; break; case BinaryOperatorType.LogicalOr: methodGroup = operators.LogicalOrOperators; break; default: throw new InvalidOperationException(); } OverloadResolution builtinOperatorOR = rc.CreateOverloadResolution(new[] { lhs, rhs }); foreach (var candidate in methodGroup) { builtinOperatorOR.AddCandidate(candidate); } VSharpOperators.BinaryOperatorMethod m = (VSharpOperators.BinaryOperatorMethod)builtinOperatorOR.BestCandidate; IType resultType = m.ReturnType; if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) { // If there are any user-defined operators, prefer those over the built-in operators. // It'll be a more informative error. if (userDefinedOperatorOR.BestCandidate != null) { return(SetUserDefinedOperationInformations(rc, userDefinedOperatorOR)); } else { return(new ErrorExpression(resultType)); } } else if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) { object val; try { val = m.Invoke(rc, lhs.ConstantValue, rhs.ConstantValue); } catch (ArithmeticException) { return(new ErrorExpression(resultType)); } return(Constant.CreateConstantFromValue(rc, resultType, val, loc)); } else { lhs = rc.Convert(lhs, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]); rhs = rc.Convert(rhs, m.Parameters[1].Type, builtinOperatorOR.ArgumentConversions[1]); return(SetOperationInformations(rc, resultType, lhs, op, rhs, builtinOperatorOR.BestCandidate is OverloadResolution.ILiftedOperator)); } }
bool MatchDisposeCheck(ILVariable objVar, ILInstruction checkInst, bool isReference, bool usingNull, out int numObjVarLoadsInCheck) { numObjVarLoadsInCheck = 2; CallVirt callVirt; if (objVar.Type.IsKnownType(KnownTypeCode.NullableOfT)) { if (checkInst.MatchIfInstruction(out var condition, out var disposeInst)) { if (!NullableLiftingTransform.MatchHasValueCall(condition, objVar)) { return(false); } if (!(disposeInst is Block disposeBlock) || disposeBlock.Instructions.Count != 1) { return(false); } callVirt = disposeBlock.Instructions[0] as CallVirt; } else if (checkInst.MatchNullableRewrap(out disposeInst)) { callVirt = disposeInst as CallVirt; } else { return(false); } if (callVirt == null) { return(false); } if (callVirt.Method.FullName != "System.IDisposable.Dispose") { return(false); } if (callVirt.Method.Parameters.Count > 0) { return(false); } if (callVirt.Arguments.Count != 1) { return(false); } var firstArg = callVirt.Arguments.FirstOrDefault(); if (!(firstArg.MatchUnboxAny(out var innerArg1, out var unboxType) && unboxType.IsKnownType(KnownTypeCode.IDisposable))) { if (!firstArg.MatchAddressOf(out var innerArg2)) { return(false); } return(NullableLiftingTransform.MatchGetValueOrDefault(innerArg2, objVar) || (innerArg2 is NullableUnwrap unwrap && unwrap.Argument.MatchLdLoc(objVar))); } else { if (!(innerArg1.MatchBox(out firstArg, out var boxType) && boxType.IsKnownType(KnownTypeCode.NullableOfT) && NullableType.GetUnderlyingType(boxType).Equals(NullableType.GetUnderlyingType(objVar.Type)))) { return(false); } return(firstArg.MatchLdLoc(objVar)); } }
/// <summary> /// Performs nullable lifting. /// /// Produces a lifted instruction with semantics equivalent to: /// (v1 != null && ... && vn != null) ? trueInst : falseInst, /// where the v1,...,vn are the <c>this.nullableVars</c>. /// If lifting fails, returns <c>null</c>. /// </summary> ILInstruction LiftNormal(ILInstruction trueInst, ILInstruction falseInst, Interval ilrange) { bool isNullCoalescingWithNonNullableFallback = false; if (!MatchNullableCtor(trueInst, out var utype, out var exprToLift)) { isNullCoalescingWithNonNullableFallback = true; utype = context.TypeSystem.Compilation.FindType(trueInst.ResultType.ToKnownTypeCode()); exprToLift = trueInst; if (nullableVars.Count == 1 && exprToLift.MatchLdLoc(nullableVars[0])) { // v.HasValue ? ldloc v : fallback // => v ?? fallback context.Step("v.HasValue ? v : fallback => v ?? fallback", trueInst); return(new NullCoalescingInstruction(NullCoalescingKind.Nullable, trueInst, falseInst) { UnderlyingResultType = NullableType.GetUnderlyingType(nullableVars[0].Type).GetStackType(), ILRange = ilrange }); } else if (trueInst is Call call && !call.IsLifted && CSharp.Resolver.CSharpOperators.IsComparisonOperator(call.Method) && call.Method.Name != "op_Equality" && call.Method.Name != "op_Inequality" && falseInst.MatchLdcI4(0)) { // (v1 != null && ... && vn != null) ? call op_LessThan(lhs, rhs) : ldc.i4(0) var liftedOperator = CSharp.Resolver.CSharpOperators.LiftUserDefinedOperator(call.Method); if (liftedOperator != null) { var(left, right, bits) = DoLiftBinary(call.Arguments[0], call.Arguments[1]); if (left != null && right != null && bits.All(0, nullableVars.Count)) { return(new Call(liftedOperator) { Arguments = { left, right }, ConstrainedTo = call.ConstrainedTo, ILRange = call.ILRange, ILStackWasEmpty = call.ILStackWasEmpty, IsTail = call.IsTail }); } } } } ILInstruction lifted; if (nullableVars.Count == 1 && MatchGetValueOrDefault(exprToLift, nullableVars[0])) { // v.HasValue ? call GetValueOrDefault(ldloca v) : fallback // => conv.nop.lifted(ldloc v) ?? fallback // This case is handled separately from DoLift() because // that doesn't introduce nop-conversions. context.Step("v.HasValue ? v.GetValueOrDefault() : fallback => v ?? fallback", trueInst); var inputUType = NullableType.GetUnderlyingType(nullableVars[0].Type); lifted = new LdLoc(nullableVars[0]); if (!inputUType.Equals(utype) && utype.ToPrimitiveType() != PrimitiveType.None) { // While the ILAst allows implicit conversions between short and int // (because both map to I4); it does not allow implicit conversions // between short? and int? (structs of different types). // So use 'conv.nop.lifted' to allow the conversion. lifted = new Conv( lifted, inputUType.GetStackType(), inputUType.GetSign(), utype.ToPrimitiveType(), checkForOverflow: false, isLifted: true ) { ILRange = ilrange }; } } else { context.Step("NullableLiftingTransform.DoLift", trueInst); BitSet bits; (lifted, bits) = DoLift(exprToLift); if (lifted == null) { return(null); } if (!bits.All(0, nullableVars.Count)) { // don't lift if a nullableVar doesn't contribute to the result return(null); } Debug.Assert(lifted is ILiftableInstruction liftable && liftable.IsLifted && liftable.UnderlyingResultType == exprToLift.ResultType); } if (isNullCoalescingWithNonNullableFallback) { lifted = new NullCoalescingInstruction(NullCoalescingKind.NullableWithValueFallback, lifted, falseInst) { UnderlyingResultType = exprToLift.ResultType, ILRange = ilrange }; } else if (!MatchNull(falseInst, utype)) { // Normal lifting, but the falseInst isn't `default(utype?)` // => use the `??` operator to provide the fallback value. lifted = new NullCoalescingInstruction(NullCoalescingKind.Nullable, lifted, falseInst) { UnderlyingResultType = exprToLift.ResultType, ILRange = ilrange }; } return(lifted); }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = this.IdentifierExpression; int pos = this.Emitter.Output.Length; ResolveResult resolveResult = null; this.isRefArg = this.Emitter.IsRefArg; this.Emitter.IsRefArg = false; resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); var id = identifierExpression.Identifier; var isResolved = resolveResult != null && !(resolveResult is ErrorResolveResult); var memberResult = resolveResult as MemberResolveResult; if (this.Emitter.Locals != null && this.Emitter.Locals.ContainsKey(id) && resolveResult is LocalResolveResult) { var lrr = (LocalResolveResult)resolveResult; if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(lrr.Variable) && !(identifierExpression.Parent is DirectionExpression)) { this.Write(this.Emitter.LocalsMap[lrr.Variable]); } else if (this.Emitter.LocalsNamesMap != null && this.Emitter.LocalsNamesMap.ContainsKey(id)) { this.Write(this.Emitter.LocalsNamesMap[id]); } else { this.Write(id); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); return; } if (resolveResult is TypeResolveResult) { this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); /*if (this.Emitter.Validator.IsExternalType(resolveResult.Type.GetDefinition()) || resolveResult.Type.Kind == TypeKind.Enum) * { * this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); * } * else * { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(resolveResult.Type, this.Emitter) + ")"); * }*/ return; } string inlineCode = memberResult != null?this.Emitter.GetInline(memberResult.Member) : null; var isInvoke = identifierExpression.Parent is InvocationExpression && (((InvocationExpression)(identifierExpression.Parent)).Target == identifierExpression); if (memberResult != null && memberResult.Member is IMethod && isInvoke) { var i_rr = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter) as CSharpInvocationResolveResult; if (i_rr != null && !i_rr.IsExpandedForm) { var tpl = this.Emitter.GetAttribute(memberResult.Member.Attributes, JS.NS.BRIDGE + ".TemplateAttribute"); if (tpl != null && tpl.PositionalArguments.Count == 2) { inlineCode = tpl.PositionalArguments[1].ConstantValue.ToString(); } } } if (string.IsNullOrEmpty(inlineCode) && memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { var method = (IMethod)memberResult.Member; if (method.TypeArguments.Count > 0) { inlineCode = MemberReferenceBlock.GenerateInlineForMethodReference(method, this.Emitter); } } bool hasInline = !string.IsNullOrEmpty(inlineCode); bool hasThis = hasInline && inlineCode.Contains("{this}"); if (hasInline && inlineCode.StartsWith("<self>")) { hasThis = true; inlineCode = inlineCode.Substring(6); } if (hasThis) { Emitter.ThisRefCounter++; this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (memberResult.Member.IsStatic) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); /*if (!this.Emitter.Validator.IsExternalType(memberResult.Member.DeclaringTypeDefinition) && memberResult.Member.DeclaringTypeDefinition.Kind != TypeKind.Enum) * { * this.Write("(Bridge.get(" + BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))"); * } * else * { * this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); * }*/ } else { this.WriteThis(); } var oldInline = inlineCode; var thisArg = this.Emitter.Output.ToString(); int thisIndex = inlineCode.IndexOf("{this}"); inlineCode = inlineCode.Replace("{this}", thisArg); this.Emitter.Output = oldBuilder; int[] range = null; if (thisIndex > -1) { range = new[] { thisIndex, thisIndex + thisArg.Length }; } if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode, null, thisArg, range); } else { if (memberResult.Member is IMethod) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.IdentifierExpression, resolveResult), oldInline, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else if (memberResult != null && memberResult.Member is IField && inlineCode.Contains("{0}")) { this.PushWriter(inlineCode, null, thisArg, range); } else { this.Write(inlineCode); } } return; } if (hasInline) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { if (memberResult.Member is IMethod) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.IdentifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else { this.Write(inlineCode); } } return; } string appendAdditionalCode = null; if (memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { if (!string.IsNullOrEmpty(inlineCode)) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, identifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else { var resolvedMethod = (IMethod)memberResult.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; if (!isStatic) { var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Write(isExtensionMethod ? JS.Funcs.BRIDGE_BIND_SCOPE : JS.Funcs.BRIDGE_BIND); this.WriteOpenParentheses(); this.WriteThis(); this.Write(", "); appendAdditionalCode = ")"; } } } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(memberResult.Member) && this.Emitter.IsInlineConst(memberResult.Member)) { this.WriteScript(memberResult.ConstantValue); return; } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous) { bool isStatement = false; string valueVar = null; if (this.Emitter.IsUnaryAccessor) { isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(memberResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } } this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { //this.Write(inlineCode); if (resolveResult is InvocationResolveResult || (memberResult.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } else if (Helpers.IsFieldProperty(memberResult.Member, this.Emitter)) { var name = Helpers.GetPropertyRef(memberResult.Member, this.Emitter); this.WriteIdentifier(name); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType); if (isStatement) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript(JS.Funcs.Math.INC); } else { this.WriteScript(JS.Funcs.Math.DEC); } this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write(JS.Funcs.Math.INC); } else { this.Write(JS.Funcs.Math.DEC); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript(JS.Funcs.Math.INC); } else { this.WriteScript(JS.Funcs.Math.DEC); } this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); } else { this.Write(valueVar); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write(JS.Funcs.Math.INC); } else { this.Write(JS.Funcs.Math.DEC); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement) { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { string trg; if (memberResult.Member.IsStatic) { trg = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter); } else { trg = "this"; } bool isBool = memberResult != null && NullableType.IsNullable(memberResult.Member.ReturnType) ? NullableType.GetUnderlyingType(memberResult.Member.ReturnType).IsKnownType(KnownTypeCode.Boolean) : memberResult.Member.ReturnType.IsKnownType(KnownTypeCode.Boolean); bool skipGet = false; var orr = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter) as OperatorResolveResult; bool special = orr != null && orr.IsLiftedOperator; if (!special && isBool && (this.Emitter.AssignmentType == AssignmentOperatorType.BitwiseAnd || this.Emitter.AssignmentType == AssignmentOperatorType.BitwiseOr)) { skipGet = true; } if (skipGet) { this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "({0})")); } else { this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "(", trg, ".", Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false), "()", "{0})")); } } else { this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + "({0})"); } } else if (memberResult != null && memberResult.Member is IEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else { this.Write(Helpers.GetAddOrRemove(this.Emitter.AssignmentType == AssignmentOperatorType.Add)); this.Write( OverloadsCollection.Create(this.Emitter, memberResult.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); } this.WriteOpenParentheses(); } else { this.WriteTarget(memberResult); this.Write(this.Emitter.GetEntityName(memberResult.Member, true)); } } else { if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (isResolved) { if (resolveResult is LocalResolveResult) { var localResolveResult = (LocalResolveResult)resolveResult; this.Write(localResolveResult.Variable.Name); } else if (memberResult != null) { this.WriteTarget(memberResult); string name = OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName(); if (isRefArg) { this.WriteScript(name); } else if (memberResult.Member is IField) { this.WriteIdentifier(name); } else { this.Write(name); } } else { this.Write(resolveResult.ToString()); } } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } if (appendAdditionalCode != null) { this.Write(appendAdditionalCode); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); }
internal static ITypeReference ConvertType(AstType type, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope, bool isInUsingDeclaration) { SimpleType s = type as SimpleType; if (s != null) { List <ITypeReference> typeArguments = new List <ITypeReference>(); foreach (var ta in s.TypeArguments) { typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration)); } if (typeArguments.Count == 0 && parentMethodDefinition != null) { // SimpleTypeOrNamespaceReference doesn't support method type parameters, // so we directly handle them here. foreach (ITypeParameter tp in parentMethodDefinition.TypeParameters) { if (tp.Name == s.Identifier) { return(tp); } } } return(new SimpleTypeOrNamespaceReference(s.Identifier, typeArguments, parentTypeDefinition, parentUsingScope, isInUsingDeclaration)); } PrimitiveType p = type as PrimitiveType; if (p != null) { switch (p.Keyword) { case "string": return(KnownTypeReference.String); case "int": return(KnownTypeReference.Int32); case "uint": return(KnownTypeReference.UInt32); case "object": return(KnownTypeReference.Object); case "bool": return(KnownTypeReference.Boolean); case "sbyte": return(KnownTypeReference.SByte); case "byte": return(KnownTypeReference.Byte); case "short": return(KnownTypeReference.Int16); case "ushort": return(KnownTypeReference.UInt16); case "long": return(KnownTypeReference.Int64); case "ulong": return(KnownTypeReference.UInt64); case "float": return(KnownTypeReference.Single); case "double": return(KnownTypeReference.Double); case "decimal": return(ReflectionHelper.ToTypeReference(TypeCode.Decimal)); case "char": return(KnownTypeReference.Char); case "void": return(KnownTypeReference.Void); default: return(SharedTypes.UnknownType); } } MemberType m = type as MemberType; if (m != null) { ITypeOrNamespaceReference t; if (m.IsDoubleColon) { SimpleType st = m.Target as SimpleType; if (st != null) { t = new AliasNamespaceReference(st.Identifier, parentUsingScope); } else { t = null; } } else { t = ConvertType(m.Target, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration) as ITypeOrNamespaceReference; } if (t == null) { return(SharedTypes.UnknownType); } List <ITypeReference> typeArguments = new List <ITypeReference>(); foreach (var ta in m.TypeArguments) { typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration)); } return(new MemberTypeOrNamespaceReference(t, m.MemberName, typeArguments, parentTypeDefinition, parentUsingScope)); } ComposedType c = type as ComposedType; if (c != null) { ITypeReference t = ConvertType(c.BaseType, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration); if (c.HasNullableSpecifier) { t = NullableType.Create(t); } for (int i = 0; i < c.PointerRank; i++) { t = PointerTypeReference.Create(t); } foreach (var a in c.ArraySpecifiers.Reverse()) { t = ArrayTypeReference.Create(t, a.Dimensions); } return(t); } Debug.WriteLine("Unknown node used as type: " + type); return(SharedTypes.UnknownType); }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = this.IdentifierExpression; int pos = this.Emitter.Output.Length; ResolveResult resolveResult = null; this.isRefArg = this.Emitter.IsRefArg; this.Emitter.IsRefArg = false; resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); var id = identifierExpression.Identifier; var isResolved = resolveResult != null && !(resolveResult is ErrorResolveResult); var memberResult = resolveResult as MemberResolveResult; if (this.Emitter.Locals != null && this.Emitter.Locals.ContainsKey(id) && resolveResult is LocalResolveResult) { if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(id) && !(identifierExpression.Parent is DirectionExpression)) { this.Write(this.Emitter.LocalsMap[id]); } else if (this.Emitter.LocalsNamesMap != null && this.Emitter.LocalsNamesMap.ContainsKey(id)) { this.Write(this.Emitter.LocalsNamesMap[id]); } else { this.Write(id); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); return; } if (resolveResult is TypeResolveResult) { this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); /*if (this.Emitter.Validator.IsIgnoreType(resolveResult.Type.GetDefinition()) || resolveResult.Type.Kind == TypeKind.Enum) * { * this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); * } * else * { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(resolveResult.Type, this.Emitter) + ")"); * }*/ return; } string inlineCode = memberResult != null?this.Emitter.GetInline(memberResult.Member) : null; bool hasInline = !string.IsNullOrEmpty(inlineCode); bool hasThis = hasInline && inlineCode.Contains("{this}"); if (hasInline && inlineCode.StartsWith("<self>")) { hasThis = true; inlineCode = inlineCode.Substring(6); } if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (memberResult.Member.IsStatic) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); /*if (!this.Emitter.Validator.IsIgnoreType(memberResult.Member.DeclaringTypeDefinition) && memberResult.Member.DeclaringTypeDefinition.Kind != TypeKind.Enum) * { * this.Write("(Bridge.get(" + BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))"); * } * else * { * this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); * }*/ } else { this.WriteThis(); } var thisArg = this.Emitter.Output.ToString(); inlineCode = inlineCode.Replace("{this}", thisArg); this.Emitter.Output = oldBuilder; if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode, null, thisArg); } else { this.Write(inlineCode); } return; } if (hasInline && memberResult.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } return; } string appendAdditionalCode = null; if (memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { var resolvedMethod = (IMethod)memberResult.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; if (!isStatic) { var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "("); this.WriteThis(); this.Write(", "); appendAdditionalCode = ")"; } } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(memberResult.Member) && this.Emitter.IsInlineConst(memberResult.Member)) { this.WriteScript(memberResult.ConstantValue); return; } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous) { bool isStatement = false; string valueVar = null; if (this.Emitter.IsUnaryAccessor) { isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(memberResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } } this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { //this.Write(inlineCode); if (resolveResult is InvocationResolveResult || (memberResult.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } else if (Helpers.IsFieldProperty(memberResult.Member, this.Emitter)) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType); if (isStatement) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); } else { this.Write(valueVar); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement) { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { string trg; if (memberResult.Member.IsStatic) { trg = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter); } else { trg = "this"; } this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "(", trg, ".", Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false), "()", "{0})")); } else { this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + "({0})"); } } else if (memberResult != null && memberResult.Member is DefaultResolvedEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else { this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove"); this.Write( OverloadsCollection.Create(this.Emitter, memberResult.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); } this.WriteOpenParentheses(); } else { this.WriteTarget(memberResult); this.Write(this.Emitter.GetEntityName(memberResult.Member, true)); } } else { if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (isResolved) { if (resolveResult is TypeResolveResult) { var typeResolveResult = (TypeResolveResult)resolveResult; var isNative = this.Emitter.Validator.IsIgnoreType(typeResolveResult.Type.GetDefinition()); this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); /*if (!isNative) * { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); * } * else * { * this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); * }*/ if (typeResolveResult.Type.TypeParameterCount > 0) { this.WriteOpenParentheses(); new TypeExpressionListBlock(this.Emitter, this.IdentifierExpression.TypeArguments).Emit(); this.WriteCloseParentheses(); } if (!isNative) { this.Write(")"); } } else if (resolveResult is LocalResolveResult) { var localResolveResult = (LocalResolveResult)resolveResult; this.Write(localResolveResult.Variable.Name); } else if (memberResult != null) { this.WriteTarget(memberResult); string name = OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName(); if (isRefArg) { this.WriteScript(name); } else { this.Write(name); } } else { this.Write(resolveResult.ToString()); } } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } if (appendAdditionalCode != null) { this.Write(appendAdditionalCode); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); }
/// <summary> /// The subject forgets about the news. May be able to regain memory by being reminded, but that's another story. /// <para/> /// May also be used by Alzheimers. /// </summary> public void Forget() { newsImportance = null; }
bool MatchDisposeBlock(BlockContainer container, ILVariable objVar, bool usingNull) { var entryPoint = container.EntryPoint; if (entryPoint.Instructions.Count < 2 || entryPoint.Instructions.Count > 3 || entryPoint.IncomingEdgeCount != 1) { return(false); } int leaveIndex = entryPoint.Instructions.Count == 2 ? 1 : 2; int checkIndex = entryPoint.Instructions.Count == 2 ? 0 : 1; int castIndex = entryPoint.Instructions.Count == 3 ? 0 : -1; bool isReference = objVar.Type.IsReferenceType != false; if (castIndex > -1) { if (!entryPoint.Instructions[castIndex].MatchStLoc(out var tempVar, out var isinst)) { return(false); } if (!isinst.MatchIsInst(out var load, out var disposableType) || !load.MatchLdLoc(objVar) || !disposableType.IsKnownType(KnownTypeCode.IDisposable)) { return(false); } if (tempVar.StoreCount != 1 || tempVar.LoadCount != 2) { return(false); } objVar = tempVar; isReference = true; } if (!entryPoint.Instructions[leaveIndex].MatchLeave(container, out var returnValue) || !returnValue.MatchNop()) { return(false); } CallVirt callVirt; if (objVar.Type.IsKnownType(KnownTypeCode.NullableOfT)) { if (!entryPoint.Instructions[checkIndex].MatchIfInstruction(out var condition, out var disposeInst)) { return(false); } if (!(NullableLiftingTransform.MatchHasValueCall(condition, out var v) && v == objVar)) { return(false); } if (!(disposeInst is Block disposeBlock) || disposeBlock.Instructions.Count != 1) { return(false); } if (!(disposeBlock.Instructions[0] is CallVirt cv)) { return(false); } callVirt = cv; if (callVirt.Method.FullName != "System.IDisposable.Dispose") { return(false); } if (callVirt.Method.Parameters.Count > 0) { return(false); } if (callVirt.Arguments.Count != 1) { return(false); } var firstArg = cv.Arguments.FirstOrDefault(); if (!(firstArg.MatchUnboxAny(out var innerArg1, out var unboxType) && unboxType.IsKnownType(KnownTypeCode.IDisposable))) { if (!firstArg.MatchAddressOf(out var innerArg2)) { return(false); } return(NullableLiftingTransform.MatchGetValueOrDefault(innerArg2, objVar)); } else { if (!(innerArg1.MatchBox(out firstArg, out var boxType) && boxType.IsKnownType(KnownTypeCode.NullableOfT) && NullableType.GetUnderlyingType(boxType).Equals(NullableType.GetUnderlyingType(objVar.Type)))) { return(false); } return(firstArg.MatchLdLoc(objVar)); } }
protected void VisitMemberReferenceExpression() { MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression; int pos = this.Emitter.Output.Length; bool isRefArg = this.Emitter.IsRefArg; this.Emitter.IsRefArg = false; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; string targetVar = null; string valueVar = null; bool isStatement = false; bool isConstTarget = false; var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter); if (targetrr is ConstantResolveResult) { isConstTarget = true; } var memberTargetrr = targetrr as MemberResolveResult; if (memberTargetrr != null && memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField && this.Emitter.Validator.EnumEmitMode(memberTargetrr.Type) == 2) { isConstTarget = true; } if (memberReferenceExpression.Target is ParenthesizedExpression || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Int64)) || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.UInt64)) || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Decimal))) { isConstTarget = false; } var isInvoke = memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression); if (isInvoke) { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); if (expressionResolveResult is InvocationResolveResult) { resolveResult = expressionResolveResult; } else if (expressionResolveResult is MemberResolveResult) { if (((MemberResolveResult)expressionResolveResult).Member is IProperty) { resolveResult = expressionResolveResult; } } } else { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); } bool oldIsAssignment = this.Emitter.IsAssignment; bool oldUnary = this.Emitter.IsUnaryAccessor; if (resolveResult == null) { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.WriteDot(); string name = memberReferenceExpression.MemberName; this.Write(name.ToLowerCamelCase()); return; } bool isDynamic = false; if (resolveResult is DynamicInvocationResolveResult) { var dynamicResolveResult = (DynamicInvocationResolveResult)resolveResult; var group = dynamicResolveResult.Target as MethodGroupResolveResult; if (group != null && group.Methods.Count() > 1) { var method = group.Methods.FirstOrDefault(m => { if (dynamicResolveResult.Arguments.Count != m.Parameters.Count) { return(false); } for (int i = 0; i < m.Parameters.Count; i++) { var argType = dynamicResolveResult.Arguments[i].Type; if (argType.Kind == TypeKind.Dynamic) { argType = this.Emitter.Resolver.Compilation.FindType(TypeCode.Object); } if (!m.Parameters[i].Type.Equals(argType)) { return(false); } } return(true); }) ?? group.Methods.Last(); isDynamic = true; resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); resolveResult = new InvocationResolveResult(resolveResult, method, dynamicResolveResult.Arguments); } } if (resolveResult is MethodGroupResolveResult) { var oldResult = (MethodGroupResolveResult)resolveResult; resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); if (resolveResult is DynamicInvocationResolveResult) { var method = oldResult.Methods.Last(); resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); } } MemberResolveResult member = resolveResult as MemberResolveResult; var globalTarget = member != null?this.Emitter.IsGlobalTarget(member.Member) : null; if (member != null && member.Member.Attributes.Any(a => a.AttributeType.FullName == "Bridge.NonScriptableAttribute")) { throw new EmitterException(this.MemberReferenceExpression, "Member " + member.ToString() + " is marked as not usable from script"); } if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { var interceptor = this.Emitter.Plugins.OnReference(this, this.MemberReferenceExpression, member); if (interceptor.Cancel) { return; } if (!string.IsNullOrEmpty(interceptor.Replacement)) { this.Write(interceptor.Replacement); return; } } if (globalTarget != null && globalTarget.Item1) { var target = globalTarget.Item2; if (!string.IsNullOrWhiteSpace(target)) { bool assign = false; var memberExpression = member.Member is IMethod ? memberReferenceExpression.Parent.Parent : memberReferenceExpression.Parent; var targetExpression = member.Member is IMethod ? memberReferenceExpression.Parent : memberReferenceExpression; var assignment = memberExpression as AssignmentExpression; if (assignment != null && assignment.Right == targetExpression) { assign = true; } else { var varInit = memberExpression as VariableInitializer; if (varInit != null && varInit.Initializer == targetExpression) { assign = true; } else if (memberExpression is InvocationExpression) { var targetInvocation = (InvocationExpression)memberExpression; if (targetInvocation.Arguments.Any(a => a == targetExpression)) { assign = true; } } } if (assign) { if (resolveResult is InvocationResolveResult) { this.PushWriter(target); } else { this.Write(target); } return; } } if (resolveResult is InvocationResolveResult) { this.PushWriter(""); } return; } Tuple <bool, bool, string> inlineInfo = member != null ? (isDynamic ? ((Emitter)this.Emitter).GetInlineCodeFromMember(member.Member, null) : this.Emitter.GetInlineCode(memberReferenceExpression)) : null; //string inline = member != null ? this.Emitter.GetInline(member.Member) : null; string inline = inlineInfo != null ? inlineInfo.Item3 : null; if (string.IsNullOrEmpty(inline) && member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var method = (IMethod)member.Member; if (method.TypeArguments.Count > 0) { inline = MemberReferenceBlock.GenerateInlineForMethodReference(method, this.Emitter); } } if (member != null && member.Member is IMethod && isInvoke) { var i_rr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter) as CSharpInvocationResolveResult; if (i_rr != null && !i_rr.IsExpandedForm) { var tpl = this.Emitter.GetAttribute(member.Member.Attributes, JS.NS.BRIDGE + ".TemplateAttribute"); if (tpl != null && tpl.PositionalArguments.Count == 2) { inline = tpl.PositionalArguments[1].ConstantValue.ToString(); } } } bool hasInline = !string.IsNullOrEmpty(inline); bool hasThis = hasInline && inline.Contains("{this}"); bool isInterfaceMember = false; if (hasInline && inline.StartsWith("<self>")) { hasThis = true; inline = inline.Substring(6); } bool nativeImplementation = true; bool isInterface = inline == null && member != null && member.Member.DeclaringTypeDefinition != null && member.Member.DeclaringTypeDefinition.Kind == TypeKind.Interface; var hasTypeParemeter = isInterface && Helpers.IsTypeParameterType(member.Member.DeclaringType); if (isInterface) { var ei = this.Emitter.Validator.IsExternalInterface(member.Member.DeclaringTypeDefinition); if (ei != null) { nativeImplementation = ei.IsNativeImplementation; } else { nativeImplementation = member.Member.DeclaringTypeDefinition.ParentAssembly.AssemblyName == CS.NS.ROOT || !this.Emitter.Validator.IsExternalType(member.Member.DeclaringTypeDefinition); } if (ei != null && ei.IsSimpleImplementation) { nativeImplementation = false; isInterfaceMember = false; } else if (ei != null || hasTypeParemeter) { if (hasTypeParemeter || !nativeImplementation) { isInterfaceMember = true; } } } string interfaceTempVar = null; if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; var oldInline = inline; string thisArg = null; bool isSimple = true; if (this.MemberReferenceExpression.Target is BaseReferenceExpression) { thisArg = "this"; } else { this.Emitter.Output = new StringBuilder(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } this.WriteSimpleTarget(resolveResult); if (isConstTarget) { this.Write(")"); } thisArg = this.Emitter.Output.ToString(); if (Regex.Matches(inline, @"\{(\*?)this\}").Count > 1) { var mrr = resolveResult as MemberResolveResult; bool isField = mrr != null && mrr.Member is IField && (mrr.TargetResult is ThisResolveResult || mrr.TargetResult is LocalResolveResult || mrr.TargetResult is MemberResolveResult && ((MemberResolveResult)mrr.TargetResult).Member is IField); isSimple = (mrr != null && (mrr.TargetResult is ThisResolveResult || mrr.TargetResult is ConstantResolveResult || mrr.TargetResult is LocalResolveResult)) || isField; } } int thisIndex; if (!isSimple) { StringBuilder sb = new StringBuilder(); sb.Append("("); var tempVar = this.GetTempVarName(); inline = inline.Replace("{this}", tempVar); thisIndex = tempVar.Length + 2; sb.Append(tempVar); sb.Append(" = "); sb.Append(thisArg); sb.Append(", "); sb.Append(inline); sb.Append(")"); inline = sb.ToString(); } else { thisIndex = inline.IndexOf("{this}", StringComparison.Ordinal); inline = inline.Replace("{this}", thisArg); } if (member != null && member.Member is IProperty) { this.Emitter.Output = new StringBuilder(); inline = inline.Replace("{0}", "[[0]]"); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); inline = this.Emitter.Output.ToString(); inline = inline.Replace("[[0]]", "{0}"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.Emitter.Output = oldBuilder; int[] range = null; if (thisIndex > -1) { range = new[] { thisIndex, thisIndex + thisArg.Length }; } if (resolveResult is InvocationResolveResult) { this.PushWriter(inline, null, thisArg, range); } else { if (member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), oldInline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (member != null && member.Member is IField && inline.Contains("{0}")) { this.PushWriter(inline, null, thisArg, range); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inline)) { this.PushWriter(inline, null, thisArg, range); } else { this.Write(inline); } } return; } if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && this.Emitter.IsInlineConst(member.Member)) { var parentExpression = memberReferenceExpression.Parent as MemberReferenceExpression; bool wrap = false; if (parentExpression != null) { var ii = this.Emitter.GetInlineCode(parentExpression); if (string.IsNullOrEmpty(ii.Item3)) { wrap = true; this.WriteOpenParentheses(); } } this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter)); if (wrap) { this.WriteCloseParentheses(); } } else if (hasInline && member.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); } } } else { if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum) { var typeDef = member.Member.DeclaringType as ITypeDefinition; if (typeDef != null) { var enumMode = this.Emitter.Validator.EnumEmitMode(typeDef); if ((this.Emitter.Validator.IsExternalType(typeDef) && enumMode == -1) || enumMode == 2) { this.WriteScript(member.ConstantValue); return; } if (enumMode >= 3 && enumMode < 7) { string enumStringName = member.Member.Name; var attr = Helpers.GetInheritedAttribute(member.Member, Translator.Bridge_ASSEMBLY + ".NameAttribute"); if (attr != null) { enumStringName = this.Emitter.GetEntityName(member.Member); } else { switch (enumMode) { case 3: enumStringName = Object.Net.Utilities.StringUtils.ToLowerCamelCase(member.Member.Name); break; case 4: enumStringName = member.Member.Name; break; case 5: enumStringName = enumStringName.ToLowerInvariant(); break; case 6: enumStringName = enumStringName.ToUpperInvariant(); break; } } this.WriteScript(enumStringName); return; } } } if (resolveResult is TypeResolveResult) { TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult; this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); return; } else if (member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { if (!string.IsNullOrEmpty(inline)) { if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else { var resolvedMethod = (IMethod)member.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (!isStatic) { this.Write(isExtensionMethod ? JS.Funcs.BRIDGE_BIND_SCOPE : JS.Funcs.BRIDGE_CACHE_BIND); this.WriteOpenParentheses(); if (memberReferenceExpression.Target is BaseReferenceExpression) { this.WriteThis(); } else { interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, false); } this.Write(", "); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (isExtensionMethod) { this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter)); } else { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } if (interfaceTempVar != null) { this.Write(interfaceTempVar); } else { this.WriteSimpleTarget(resolveResult); } if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar, member, false); } else { this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation)); } if (!isStatic) { this.Write(")"); } } return; } else { bool isProperty = false; if (member != null && member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition))) { isProperty = true; bool writeTargetVar = false; if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(member.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(targetrr is ThisResolveResult || targetrr is TypeResolveResult || targetrr is LocalResolveResult || isField)) { targetVar = this.GetTempVarName(); this.Write(targetVar); this.Write(" = "); } } } if (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } if (targetVar == null && isInterfaceMember) { interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, true); } else { this.WriteSimpleTarget(resolveResult); } if (member != null && targetrr != null && targetrr.Type.Kind == TypeKind.Delegate && (member.Member.Name == "Invoke")) { var method = member.Member as IMethod; if (!(method != null && method.IsExtensionMethod)) { return; } } if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (targetVar != null) { if (this.Emitter.IsUnaryAccessor && !isStatement) { this.WriteComma(false); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.Write(targetVar); } else { this.WriteSemiColon(); this.WriteNewLine(); this.Write(targetVar); } } } var targetResolveResult = targetrr as MemberResolveResult; if (targetResolveResult == null || this.Emitter.IsGlobalTarget(targetResolveResult.Member) == null) { if (isRefArg) { this.WriteComma(); } else if (!isInterfaceMember && !this.NoTarget) { this.WriteDot(); } } if (member == null) { if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic) { this.Write(memberReferenceExpression.MemberName); } else { this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase()); } } else if (!string.IsNullOrEmpty(inline)) { if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else if (member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || (!this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition) || member.Member.IsStatic))) { if (member.Member is IProperty && targetrr != null && targetrr.Type.GetDefinition() != null && this.Emitter.Validator.IsObjectLiteral(targetrr.Type.GetDefinition()) && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { this.Write(this.Emitter.GetEntityName(member.Member)); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var name = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation); var property = (IProperty)member.Member; var proto = member.IsVirtualCall || property.IsVirtual || property.IsOverride; if (this.MemberReferenceExpression.Target is BaseReferenceExpression && !property.IsIndexer && proto) { var alias = BridgeTypes.ToJsName(member.Member.DeclaringType, this.Emitter, isAlias: true); if (alias.StartsWith("\"")) { alias = alias.Insert(1, "$"); name = alias + "+\"$" + name + "\""; this.WriteIdentifier(name, false); } else { name = "$" + alias + "$" + name; this.WriteIdentifier(name); } } else { this.WriteIdentifier(name); } } } } else if (member.Member.SymbolKind == SymbolKind.Field) { bool isConst = this.Emitter.IsMemberConst(member.Member); if (isConst && this.Emitter.IsInlineConst(member.Member)) { this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter)); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var fieldName = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation); if (isRefArg) { this.WriteScript(fieldName); } else { this.WriteIdentifier(fieldName); } } } } else if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName(!nativeImplementation)); } else { this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName(!nativeImplementation)); } } else if (member.Member is IEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract, Helpers.GetAddOrRemove(this.Emitter.AssignmentType == AssignmentOperatorType.Add)); } else { this.Write(Helpers.GetEventRef(member.Member, this.Emitter, this.Emitter.AssignmentType != AssignmentOperatorType.Add, ignoreInterface: !nativeImplementation)); } this.WriteOpenParentheses(); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { this.Write(this.Emitter.GetEntityName(member.Member, true, ignoreInterface: !nativeImplementation)); } } } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { this.Write(this.Emitter.GetEntityName(member.Member, ignoreInterface: !nativeImplementation)); } } Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos); } }
private void HandleType(ResolveResult resolveOperator, string variable, string op_name, KnownTypeCode typeCode) { if (this.AssignmentExpression.Operator == AssignmentOperatorType.Assign) { if (variable != null) { this.Write(variable); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Right }, null, null, 0).Emit(); } return; } var orr = resolveOperator as OperatorResolveResult; var method = orr != null ? orr.UserDefinedOperatorMethod : null; var assigmentType = Helpers.TypeOfAssignment(this.AssignmentExpression.Operator); if (orr != null && method == null) { var name = Helpers.GetBinaryOperatorMethodName(assigmentType); var type = NullableType.IsNullable(orr.Type) ? NullableType.GetUnderlyingType(orr.Type) : orr.Type; method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (method != null) { var inline = this.Emitter.GetInline(method); if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT2; this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); if (variable != null) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left }, null, null, 0).Emit(); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null, null, 0).Emit(); } this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.AssignmentExpression, orr, method), inline).Emit(); } else if (!this.Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); if (variable != null) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left }, null, null, 0).Emit(); this.Write(", " + variable); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null, null, 0).Emit(); } this.WriteCloseParentheses(); } } else { if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT2; this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); if (variable != null) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left }, null, null, 0).Emit(); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null, null, 0).Emit(); } this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else { this.AssignmentExpression.Left.AcceptVisitor(this.Emitter); this.WriteDot(); this.Write(op_name); this.WriteOpenParentheses(); this.AssignmentExpression.Right.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } } }
protected void VisitAssignmentExpression() { AssignmentExpression assignmentExpression = this.AssignmentExpression; var oldAssigment = this.Emitter.IsAssignment; var oldAssigmentType = this.Emitter.AssignmentType; string variable = null; bool needReturnValue = !(assignmentExpression.Parent is ExpressionStatement); if (needReturnValue && assignmentExpression.Parent is LambdaExpression) { var lambdarr = this.Emitter.Resolver.ResolveNode(assignmentExpression.Parent, this.Emitter) as LambdaResolveResult; if (lambdarr != null && lambdarr.ReturnType.Kind == TypeKind.Void) { needReturnValue = false; } } var delegateAssigment = false; bool isEvent = false; var initCount = this.Emitter.Writers.Count; var asyncExpressionHandling = this.Emitter.AsyncExpressionHandling; this.WriteAwaiters(assignmentExpression.Left); this.WriteAwaiters(assignmentExpression.Right); var leftResolverResult = this.Emitter.Resolver.ResolveNode(assignmentExpression.Left, this.Emitter); var rightResolverResult = this.Emitter.Resolver.ResolveNode(assignmentExpression.Right, this.Emitter); var rr = this.Emitter.Resolver.ResolveNode(assignmentExpression, this.Emitter); var orr = rr as OperatorResolveResult; bool isDecimal = Helpers.IsDecimalType(rr.Type, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(rr.Type, this.Emitter.Resolver); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, this.Emitter.Resolver); bool isUserOperator = this.IsUserOperator(orr); bool isUint = rr.Type.IsKnownType(KnownTypeCode.UInt16) || rr.Type.IsKnownType(KnownTypeCode.UInt32) || rr.Type.IsKnownType(KnownTypeCode.UInt64); var charToString = -1; if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String)) { for (int i = 0; i < orr.Operands.Count; i++) { var crr = orr.Operands[i] as ConversionResolveResult; if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char)) { charToString = i; } } } var memberTargetrr = leftResolverResult as MemberResolveResult; bool isField = (memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult)) || leftResolverResult is ThisResolveResult || leftResolverResult is LocalResolveResult || leftResolverResult is ConstantResolveResult; var rightMemberTargetrr = rightResolverResult as MemberResolveResult; bool isRightSimple = (rightMemberTargetrr != null && rightMemberTargetrr.Member is IField && (rightMemberTargetrr.TargetResult is ThisResolveResult || rightMemberTargetrr.TargetResult is LocalResolveResult)) || rightResolverResult is ThisResolveResult || rightResolverResult is LocalResolveResult || rightResolverResult is ConstantResolveResult; var needTempVar = needReturnValue && (!isRightSimple && !isField || assignmentExpression.Operator != AssignmentOperatorType.Assign); /*if (assignmentExpression.Operator == AssignmentOperatorType.Any) * { * needTempVar = false; * }*/ if (needReturnValue) { if (needTempVar) { variable = this.GetTempVarName(); this.Write("(" + variable + " = "); var oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Write(", "); } else { this.Write("("); } } if (assignmentExpression.Operator == AssignmentOperatorType.Divide && this.Emitter.Rules.Integer == IntegerRule.Managed && !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, assignmentExpression)) && !isLong && !isLongExpected && ( (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Left), this.Emitter.Resolver) && Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Right), this.Emitter.Resolver)) )) { this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = AssignmentOperatorType.Assign; var oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); if (this.Emitter.Writers.Count == initCount) { this.Write(" = "); } this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AssignmentType = oldAssigmentType; this.Emitter.IsAssignment = oldAssigment; this.Write(JS.Types.BRIDGE_INT + "." + JS.Funcs.Math.DIV + "("); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Write(")"); this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needReturnValue && !isField) { if (needTempVar) { this.Write(", " + variable); } else { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } } if (needReturnValue) { this.Write(")"); } return; } if (assignmentExpression.Operator == AssignmentOperatorType.Multiply && this.Emitter.Rules.Integer == IntegerRule.Managed && !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, assignmentExpression)) && !isLong && !isLongExpected && ( (Helpers.IsInteger32Type(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsInteger32Type(rightResolverResult.Type, this.Emitter.Resolver) && Helpers.IsInteger32Type(rr.Type, this.Emitter.Resolver)) || (Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Left), this.Emitter.Resolver) && Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Right), this.Emitter.Resolver) && Helpers.IsInteger32Type(rr.Type, this.Emitter.Resolver)) )) { this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = AssignmentOperatorType.Assign; var oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); if (this.Emitter.Writers.Count == initCount) { this.Write(" = "); } this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AssignmentType = oldAssigmentType; this.Emitter.IsAssignment = oldAssigment; isUint = NullableType.GetUnderlyingType(rr.Type).IsKnownType(KnownTypeCode.UInt32); this.Write(JS.Types.BRIDGE_INT + "." + (isUint ? JS.Funcs.Math.UMUL : JS.Funcs.Math.MUL) + "("); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(this.Emitter); if (ConversionBlock.IsInCheckedContext(this.Emitter, assignmentExpression)) { this.Write(", 1"); } this.Write(")"); this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needReturnValue && !isField) { if (needTempVar) { this.Write(", " + variable); } else { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } } if (needReturnValue) { this.Write(")"); } return; } bool templateDelegateAssigment = false; if (assignmentExpression.Operator == AssignmentOperatorType.Add || assignmentExpression.Operator == AssignmentOperatorType.Subtract) { var add = assignmentExpression.Operator == AssignmentOperatorType.Add; if (this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult)) { delegateAssigment = true; var leftMemberResolveResult = leftResolverResult as MemberResolveResult; if (leftMemberResolveResult != null) { isEvent = leftMemberResolveResult.Member is IEvent; this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = assignmentExpression.Operator; templateDelegateAssigment = !string.IsNullOrWhiteSpace(this.Emitter.GetInline(leftMemberResolveResult.Member)); this.Emitter.IsAssignment = false; } if (!isEvent) { this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = AssignmentOperatorType.Assign; this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); this.Emitter.IsAssignment = false; if (this.Emitter.Writers.Count == initCount) { this.Write(" = "); } this.Write(add ? JS.Funcs.BRIDGE_COMBINE : JS.Funcs.BRIDGE_REMOVE); this.WriteOpenParentheses(); } } } bool nullable = orr != null && orr.IsLiftedOperator; string root = JS.Types.SYSTEM_NULLABLE + "."; bool special = nullable; this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = assignmentExpression.Operator; var oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; bool thisAssignment = leftResolverResult is ThisResolveResult; if (!thisAssignment) { if (special || (isDecimal && isDecimalExpected) || (isLong && isLongExpected) || isUserOperator) { this.Emitter.AssignmentType = AssignmentOperatorType.Assign; } if (delegateAssigment && !isEvent) { this.Emitter.IsAssignment = false; } this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); if (delegateAssigment) { this.Emitter.IsAssignment = true; } } else { this.Write("("); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AssignmentType = oldAssigmentType; this.Emitter.IsAssignment = oldAssigment; if (this.Emitter.Writers.Count == initCount && !delegateAssigment && !thisAssignment) { this.WriteSpace(); } if (isDecimal && isDecimalExpected) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.HandleDecimal(rr, variable); if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needTempVar) { this.Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } this.Write(")"); } this.Emitter.ReplaceAwaiterByVar = oldValue; return; } if (isLong && isLongExpected) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.HandleLong(rr, variable, isUint); if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needTempVar) { this.Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } this.Write(")"); } this.Emitter.ReplaceAwaiterByVar = oldValue; return; } if (this.ResolveOperator(assignmentExpression, orr, initCount, thisAssignment)) { if (thisAssignment) { this.Write(")." + JS.Funcs.CLONE + "(this)"); } else if (needReturnValue) { this.Write(")"); } return; } bool isBool = NullableType.IsNullable(rr.Type) ? NullableType.GetUnderlyingType(rr.Type).IsKnownType(KnownTypeCode.Boolean) : rr.Type.IsKnownType(KnownTypeCode.Boolean); if (!delegateAssigment) { if (!special) { switch (assignmentExpression.Operator) { case AssignmentOperatorType.Assign: break; case AssignmentOperatorType.Add: this.Write("+"); break; case AssignmentOperatorType.BitwiseAnd: if (!isBool) { this.Write("&"); } break; case AssignmentOperatorType.BitwiseOr: if (!isBool) { this.Write("|"); } break; case AssignmentOperatorType.Divide: this.Write("/"); break; case AssignmentOperatorType.ExclusiveOr: this.Write("^"); break; case AssignmentOperatorType.Modulus: this.Write("%"); break; case AssignmentOperatorType.Multiply: this.Write("*"); break; case AssignmentOperatorType.ShiftLeft: this.Write("<<"); break; case AssignmentOperatorType.ShiftRight: this.Write(isUint ? ">>>" : ">>"); break; case AssignmentOperatorType.Subtract: this.Write("-"); break; default: throw new EmitterException(assignmentExpression, "Unsupported assignment operator: " + assignmentExpression.Operator.ToString()); } } if (special) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } this.Write(root); switch (assignmentExpression.Operator) { case AssignmentOperatorType.Assign: break; case AssignmentOperatorType.Add: this.Write(JS.Funcs.Math.ADD); break; case AssignmentOperatorType.BitwiseAnd: this.Write(isBool ? JS.Funcs.Math.AND : JS.Funcs.Math.BAND); break; case AssignmentOperatorType.BitwiseOr: this.Write(isBool ? JS.Funcs.Math.OR : JS.Funcs.Math.BOR); break; case AssignmentOperatorType.Divide: this.Write(JS.Funcs.Math.DIV); break; case AssignmentOperatorType.ExclusiveOr: this.Write(JS.Funcs.Math.XOR); break; case AssignmentOperatorType.Modulus: this.Write(JS.Funcs.Math.MOD); break; case AssignmentOperatorType.Multiply: this.Write(JS.Funcs.Math.MUL); break; case AssignmentOperatorType.ShiftLeft: this.Write(JS.Funcs.Math.SL); break; case AssignmentOperatorType.ShiftRight: this.Write(isUint ? JS.Funcs.Math.SRR : JS.Funcs.Math.SR); break; case AssignmentOperatorType.Subtract: this.Write(JS.Funcs.Math.SUB); break; default: throw new EmitterException(assignmentExpression, "Unsupported assignment operator: " + assignmentExpression.Operator.ToString()); } this.WriteOpenParentheses(); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); } if (this.Emitter.Writers.Count == initCount && !thisAssignment && !special) { this.Write("= "); } } else if (!isEvent) { this.WriteComma(); } if (!special && isBool && (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd || assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr)) { this.Write("!!("); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd ? " & " : " | "); } oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; if (charToString == 1) { this.Write(JS.Funcs.STRING_FROMCHARCODE + "("); } if (needTempVar) { int pos = this.Emitter.Output.Length; this.Write(variable); Helpers.CheckValueTypeClone(rr, assignmentExpression.Right, this, pos); } else { var wrap = assignmentExpression.Operator != AssignmentOperatorType.Assign && this.Emitter.Writers.Count > initCount && !AssigmentExpressionHelper.CheckIsRightAssigmentExpression(assignmentExpression); if (wrap) { this.WriteOpenParentheses(); } assignmentExpression.Right.AcceptVisitor(this.Emitter); if (wrap) { this.WriteCloseParentheses(); } } if (!special && isBool && (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd || assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr)) { this.WriteCloseParentheses(); } if (charToString == 1) { this.WriteCloseParentheses(); } if (special) { this.WriteCloseParentheses(); } if (thisAssignment) { this.Write(")." + JS.Funcs.CLONE + "(this)"); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (this.Emitter.Writers.Count > initCount) { var writerCount = this.Emitter.Writers.Count; for (int i = initCount; i < writerCount; i++) { this.PopWriter(); } } if (delegateAssigment && !templateDelegateAssigment) { this.WriteCloseParentheses(); } if (needTempVar) { this.Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } this.Write(")"); } }
public static string ToJavascriptName(IType type, IEmitter emitter) { if (type.Kind == TypeKind.Delegate) { var delegateName = BridgeTypes.ConvertName(type.FullName); if (!emitter.JsDoc.Callbacks.Contains(delegateName)) { var method = type.GetDelegateInvokeMethod(); JsDocComment comment = new JsDocComment(); var parameters = method.Parameters; if (parameters != null && parameters.Count > 0) { foreach (var param in parameters) { var jsParam = new JsDocParam(); jsParam.Name = param.Name; jsParam.Type = XmlToJsDoc.ToJavascriptName(param.Type, emitter); comment.Parameters.Add(jsParam); } } comment.Returns.Add(new JsDocParam { Type = XmlToJsDoc.ToJavascriptName(method.ReturnType, emitter) }); comment.Callback = delegateName; comment.MemberOf = type.Namespace; if (!emitter.JsDoc.Namespaces.Contains(type.Namespace)) { emitter.JsDoc.Namespaces.Add(type.Namespace); comment.Namespace = type.Namespace; } emitter.JsDoc.Callbacks.Add(delegateName); emitter.Output.Insert(0, comment.ToString() + newLine + newLine); } return(delegateName); } if (type.IsKnownType(KnownTypeCode.String)) { return("string"); } if (type.IsKnownType(KnownTypeCode.Boolean)) { return("boolean"); } if (type.IsKnownType(KnownTypeCode.Void)) { return("void"); } if (type.IsKnownType(KnownTypeCode.Byte) || type.IsKnownType(KnownTypeCode.Char) || type.IsKnownType(KnownTypeCode.Decimal) || type.IsKnownType(KnownTypeCode.Double) || type.IsKnownType(KnownTypeCode.Int16) || type.IsKnownType(KnownTypeCode.Int32) || type.IsKnownType(KnownTypeCode.Int64) || type.IsKnownType(KnownTypeCode.SByte) || type.IsKnownType(KnownTypeCode.Single) || type.IsKnownType(KnownTypeCode.UInt16) || type.IsKnownType(KnownTypeCode.UInt32) || type.IsKnownType(KnownTypeCode.UInt64)) { return("number"); } if (type.Kind == TypeKind.Array) { ICSharpCode.NRefactory.TypeSystem.ArrayType arrayType = (ICSharpCode.NRefactory.TypeSystem.ArrayType)type; return("Array.<" + XmlToJsDoc.ToJavascriptName(arrayType.ElementType, emitter) + ">"); } if (type.Kind == TypeKind.Dynamic) { return("object"); } if (type.Kind == TypeKind.Enum && type.DeclaringType != null) { return("number"); } if (NullableType.IsNullable(type)) { return("?" + XmlToJsDoc.ToJavascriptName(NullableType.GetUnderlyingType(type), emitter)); } BridgeType bridgeType = emitter.BridgeTypes.Get(type, true); string name = BridgeTypes.ConvertName(type.FullName); bool isCustomName = false; if (bridgeType != null) { name = BridgeTypes.AddModule(name, bridgeType, out isCustomName); } if (!isCustomName && type.TypeArguments.Count > 0) { name += "$" + type.TypeArguments.Count; } return(name); }
public static void FloatToInt(ConversionBlock block, Expression expression, IType sourceType, IType targetType, bool isChecked) { NarrowingNumericOrEnumerationConversion(block, expression, NullableType.IsNullable(targetType) ? NullableType.GetUnderlyingType(targetType) : targetType, true, isChecked, NullableType.IsNullable(sourceType)); }
public LiftedUnaryOperatorMethod(CSharpOperators operators, UnaryOperatorMethod baseMethod) : base(operators.compilation) { this.baseMethod = baseMethod; this.ReturnType = NullableType.Create(baseMethod.Compilation, baseMethod.ReturnType); this.Parameters.Add(operators.MakeNullableParameter(baseMethod.Parameters[0])); }
ILInstruction Lift(IfInstruction ifInst, ILInstruction trueInst, ILInstruction falseInst) { ILInstruction condition = ifInst.Condition; while (condition.MatchLogicNot(out var arg)) { condition = arg; Swap(ref trueInst, ref falseInst); } if (AnalyzeCondition(condition)) { // (v1 != null && ... && vn != null) ? trueInst : falseInst // => normal lifting return(LiftNormal(trueInst, falseInst, ilrange: ifInst.ILRange)); } if (condition is Comp comp && !comp.IsLifted) { // This might be a C#-style lifted comparison // (C# checks the underlying value before checking the HasValue bits) if (comp.Kind.IsEqualityOrInequality()) { // for equality/inequality, the HasValue bits must also compare equal/inequal if (comp.Kind == ComparisonKind.Inequality) { // handle inequality by swapping one last time Swap(ref trueInst, ref falseInst); } if (falseInst.MatchLdcI4(0)) { // (a.GetValueOrDefault() == b.GetValueOrDefault()) ? (a.HasValue == b.HasValue) : false // => a == b return(LiftCSharpEqualityComparison(comp, ComparisonKind.Equality, trueInst)); } else if (falseInst.MatchLdcI4(1)) { // (a.GetValueOrDefault() == b.GetValueOrDefault()) ? (a.HasValue != b.HasValue) : true // => a != b return(LiftCSharpEqualityComparison(comp, ComparisonKind.Inequality, trueInst)); } else if (IsGenericNewPattern(condition, trueInst, falseInst)) { // (default(T) == null) ? Activator.CreateInstance<T>() : default(T) // => Activator.CreateInstance<T>() return(trueInst); } } else { // Not (in)equality, but one of < <= > >=. // Returns false unless all HasValue bits are true. if (falseInst.MatchLdcI4(0) && AnalyzeCondition(trueInst)) { // comp(lhs, rhs) ? (v1 != null && ... && vn != null) : false // => comp.lifted[C#](lhs, rhs) return(LiftCSharpComparison(comp, comp.Kind)); } else if (trueInst.MatchLdcI4(0) && AnalyzeCondition(falseInst)) { // comp(lhs, rhs) ? false : (v1 != null && ... && vn != null) return(LiftCSharpComparison(comp, comp.Kind.Negate())); } } } ILVariable v; if (MatchGetValueOrDefault(condition, out v) && NullableType.GetUnderlyingType(v.Type).IsKnownType(KnownTypeCode.Boolean)) { if (MatchHasValueCall(trueInst, v) && falseInst.MatchLdcI4(0)) { // v.GetValueOrDefault() ? v.HasValue : false // ==> v == true context.Step("NullableLiftingTransform: v == true", ifInst); return(new Comp(ComparisonKind.Equality, ComparisonLiftingKind.CSharp, StackType.I4, Sign.None, new LdLoc(v) { ILRange = trueInst.ILRange }, new LdcI4(1) { ILRange = falseInst.ILRange } ) { ILRange = ifInst.ILRange }); } else if (trueInst.MatchLdcI4(0) && MatchHasValueCall(falseInst, v)) { // v.GetValueOrDefault() ? false : v.HasValue // ==> v == false context.Step("NullableLiftingTransform: v == false", ifInst); return(new Comp(ComparisonKind.Equality, ComparisonLiftingKind.CSharp, StackType.I4, Sign.None, new LdLoc(v) { ILRange = falseInst.ILRange }, trueInst // LdcI4(0) ) { ILRange = ifInst.ILRange }); } else if (MatchNegatedHasValueCall(trueInst, v) && falseInst.MatchLdcI4(1)) { // v.GetValueOrDefault() ? !v.HasValue : true // ==> v != true context.Step("NullableLiftingTransform: v != true", ifInst); return(new Comp(ComparisonKind.Inequality, ComparisonLiftingKind.CSharp, StackType.I4, Sign.None, new LdLoc(v) { ILRange = trueInst.ILRange }, falseInst // LdcI4(1) ) { ILRange = ifInst.ILRange }); } else if (trueInst.MatchLdcI4(1) && MatchNegatedHasValueCall(falseInst, v)) { // v.GetValueOrDefault() ? true : !v.HasValue // ==> v != false context.Step("NullableLiftingTransform: v != false", ifInst); return(new Comp(ComparisonKind.Inequality, ComparisonLiftingKind.CSharp, StackType.I4, Sign.None, new LdLoc(v) { ILRange = falseInst.ILRange }, new LdcI4(0) { ILRange = trueInst.ILRange } ) { ILRange = ifInst.ILRange }); } } if (trueInst.MatchLdLoc(out v)) { if (MatchNullableCtor(falseInst, out var utype, out var arg) && utype.IsKnownType(KnownTypeCode.Boolean) && arg.MatchLdcI4(0)) { // condition ? v : (bool?)false // => condition & v context.Step("NullableLiftingTransform: 3vl.logic.and(bool, bool?)", ifInst); return(new ThreeValuedLogicAnd(condition, trueInst) { ILRange = ifInst.ILRange }); } if (falseInst.MatchLdLoc(out var v2)) { // condition ? v : v2 if (MatchThreeValuedLogicConditionPattern(condition, out var nullable1, out var nullable2)) { // (nullable1.GetValueOrDefault() || (!nullable2.GetValueOrDefault() && !nullable1.HasValue)) ? v : v2 if (v == nullable1 && v2 == nullable2) { context.Step("NullableLiftingTransform: 3vl.logic.or(bool?, bool?)", ifInst); return(new ThreeValuedLogicOr(trueInst, falseInst) { ILRange = ifInst.ILRange }); } else if (v == nullable2 && v2 == nullable1) { context.Step("NullableLiftingTransform: 3vl.logic.and(bool?, bool?)", ifInst); return(new ThreeValuedLogicAnd(falseInst, trueInst) { ILRange = ifInst.ILRange }); } } } } else if (falseInst.MatchLdLoc(out v)) { if (MatchNullableCtor(trueInst, out var utype, out var arg) && utype.IsKnownType(KnownTypeCode.Boolean) && arg.MatchLdcI4(1)) { // condition ? (bool?)true : v // => condition | v context.Step("NullableLiftingTransform: 3vl.logic.or(bool, bool?)", ifInst); return(new ThreeValuedLogicOr(condition, falseInst) { ILRange = ifInst.ILRange }); } } return(null); }
public static string ToJavascriptName(IType type, IEmitter emitter) { if (type.Kind == TypeKind.Delegate) { var delegateName = BridgeTypes.ConvertName(type.FullName); if (!emitter.JsDoc.Callbacks.Contains(delegateName)) { var method = type.GetDelegateInvokeMethod(); JsDocComment comment = new JsDocComment(); var parameters = method.Parameters; if (parameters != null && parameters.Count > 0) { foreach (var param in parameters) { var jsParam = new JsDocParam(); jsParam.Name = param.Name; jsParam.Type = XmlToJsDoc.ToJavascriptName(param.Type, emitter); comment.Parameters.Add(jsParam); } } comment.Returns.Add(new JsDocParam { Type = XmlToJsDoc.ToJavascriptName(method.ReturnType, emitter) }); comment.Callback = delegateName; comment.MemberOf = type.Namespace; if (!emitter.JsDoc.Namespaces.Contains(type.Namespace)) { emitter.JsDoc.Namespaces.Add(type.Namespace); comment.Namespace = type.Namespace; } emitter.JsDoc.Callbacks.Add(delegateName); emitter.WriteIndented(comment.ToString() + newLine + newLine, 0); } return(delegateName); } if (type.IsKnownType(KnownTypeCode.String)) { return("string"); } if (type.IsKnownType(KnownTypeCode.Boolean)) { return("boolean"); } if (type.IsKnownType(KnownTypeCode.Void)) { return("void"); } if (type.IsKnownType(KnownTypeCode.Byte) || type.IsKnownType(KnownTypeCode.Char) || type.IsKnownType(KnownTypeCode.Decimal) || type.IsKnownType(KnownTypeCode.Double) || type.IsKnownType(KnownTypeCode.Int16) || type.IsKnownType(KnownTypeCode.Int32) || type.IsKnownType(KnownTypeCode.Int64) || type.IsKnownType(KnownTypeCode.SByte) || type.IsKnownType(KnownTypeCode.Single) || type.IsKnownType(KnownTypeCode.UInt16) || type.IsKnownType(KnownTypeCode.UInt32) || type.IsKnownType(KnownTypeCode.UInt64)) { return("number"); } if (type.Kind == TypeKind.Array) { ICSharpCode.NRefactory.TypeSystem.ArrayType arrayType = (ICSharpCode.NRefactory.TypeSystem.ArrayType)type; return(JS.Types.ARRAY + ".<" + XmlToJsDoc.ToJavascriptName(arrayType.ElementType, emitter) + ">"); } if (type.Kind == TypeKind.Dynamic) { return("object"); } if (type.Kind == TypeKind.Enum && type.DeclaringType != null) { return("number"); } if (NullableType.IsNullable(type)) { return("?" + XmlToJsDoc.ToJavascriptName(NullableType.GetUnderlyingType(type), emitter)); } BridgeType bridgeType = emitter.BridgeTypes.Get(type, true); //string name = BridgeTypes.ConvertName(type.FullName); var name = type.Namespace; var hasTypeDef = bridgeType != null && bridgeType.TypeDefinition != null; if (hasTypeDef) { var typeDef = bridgeType.TypeDefinition; if (typeDef.IsNested) { name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(typeDef); } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(typeDef.Name); } else { if (type.DeclaringType != null) { name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(type); if (type.DeclaringType.TypeArguments.Count > 0) { name += Helpers.PrefixDollar(type.TypeArguments.Count); } } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(type.Name); } bool isCustomName = false; if (bridgeType != null) { name = BridgeTypes.AddModule(name, bridgeType, out isCustomName); } if (!hasTypeDef && !isCustomName && type.TypeArguments.Count > 0) { name += Helpers.PrefixDollar(type.TypeArguments.Count); } return(name); }
/// <summary> /// Recursive function that lifts the specified instruction. /// The input instruction is expected to a subexpression of the trueInst /// (so that all nullableVars are guaranteed non-null within this expression). /// /// Creates a new lifted instruction without modifying the input instruction. /// On success, returns (new lifted instruction, bitset). /// If lifting fails, returns (null, null). /// /// The returned bitset specifies which nullableVars were considered "relevant" for this instruction. /// bitSet[i] == true means nullableVars[i] was relevant. /// /// The new lifted instruction will have equivalent semantics to the input instruction /// if all relevant variables are non-null [except that the result will be wrapped in a Nullable{T} struct]. /// If any relevant variable is null, the new instruction is guaranteed to evaluate to <c>null</c> /// without having any other effect. /// </summary> (ILInstruction, BitSet) DoLift(ILInstruction inst) { if (MatchGetValueOrDefault(inst, out ILVariable inputVar)) { // n.GetValueOrDefault() lifted => n. BitSet foundIndices = new BitSet(nullableVars.Count); for (int i = 0; i < nullableVars.Count; i++) { if (nullableVars[i] == inputVar) { foundIndices[i] = true; } } if (foundIndices.Any()) { return(new LdLoc(inputVar) { ILRange = inst.ILRange }, foundIndices); } else { return(null, null); } } else if (inst is Conv conv) { var(arg, bits) = DoLift(conv.Argument); if (arg != null) { if (conv.HasFlag(InstructionFlags.MayThrow) && !bits.All(0, nullableVars.Count)) { // Cannot execute potentially-throwing instruction unless all // the nullableVars are arguments to the instruction // (thus causing it not to throw when any of them is null). return(null, null); } var newInst = new Conv(arg, conv.InputType, conv.InputSign, conv.TargetType, conv.CheckForOverflow, isLifted: true) { ILRange = conv.ILRange }; return(newInst, bits); } } else if (inst is BitNot bitnot) { var(arg, bits) = DoLift(bitnot.Argument); if (arg != null) { var newInst = new BitNot(arg, isLifted: true, stackType: bitnot.ResultType) { ILRange = bitnot.ILRange }; return(newInst, bits); } } else if (inst is BinaryNumericInstruction binary) { var(left, right, bits) = DoLiftBinary(binary.Left, binary.Right); if (left != null && right != null) { if (binary.HasFlag(InstructionFlags.MayThrow) && !bits.All(0, nullableVars.Count)) { // Cannot execute potentially-throwing instruction unless all // the nullableVars are arguments to the instruction // (thus causing it not to throw when any of them is null). return(null, null); } var newInst = new BinaryNumericInstruction( binary.Operator, left, right, binary.LeftInputType, binary.RightInputType, binary.CheckForOverflow, binary.Sign, isLifted: true ) { ILRange = binary.ILRange }; return(newInst, bits); } } else if (inst is Comp comp && !comp.IsLifted && comp.Kind == ComparisonKind.Equality && MatchGetValueOrDefault(comp.Left, out ILVariable v) && NullableType.GetUnderlyingType(v.Type).IsKnownType(KnownTypeCode.Boolean) && comp.Right.MatchLdcI4(0) ) { // C# doesn't support ComparisonLiftingKind.ThreeValuedLogic, // except for operator! on bool?. var(arg, bits) = DoLift(comp.Left); Debug.Assert(arg != null); var newInst = new Comp(comp.Kind, ComparisonLiftingKind.ThreeValuedLogic, comp.InputType, comp.Sign, arg, comp.Right.Clone()) { ILRange = comp.ILRange }; return(newInst, bits); }
public void SkeetEvilOverloadResolution() { // http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx // static void Foo<T>(T? ignored = default(T?)) where T : struct var m1 = MakeUnresolvedMethod(); m1.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, 0, "T") { HasValueTypeConstraint = true }); m1.Parameters.Add(MakeOptionalParameter( NullableType.Create(new TypeParameterReference(SymbolKind.Method, 0)), "ignored" )); // class ClassConstraint<T> where T : class {} var classConstraint = new DefaultUnresolvedTypeDefinition(string.Empty, "ClassConstraint"); classConstraint.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.TypeDefinition, 0, "T") { HasReferenceTypeConstraint = true }); // static void Foo<T>(ClassConstraint<T> ignored = default(ClassConstraint<T>)) // where T : class var m2 = MakeUnresolvedMethod(); m2.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, 0, "T") { HasReferenceTypeConstraint = true }); m2.Parameters.Add(MakeOptionalParameter( new ParameterizedTypeReference(classConstraint, new[] { new TypeParameterReference(SymbolKind.Method, 0) }), "ignored" )); // static void Foo<T>() var m3 = MakeUnresolvedMethod(); m3.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, 0, "T")); ICompilation compilation = TypeSystemHelper.CreateCompilation(classConstraint); var context = new SimpleTypeResolveContext(compilation.MainAssembly); IMethod resolvedM1 = (IMethod)m1.CreateResolved(context); IMethod resolvedM2 = (IMethod)m2.CreateResolved(context); IMethod resolvedM3 = (IMethod)m3.CreateResolved(context); // Call: Foo<int>(); OverloadResolution o; o = new OverloadResolution(compilation, new ResolveResult[0], typeArguments: new[] { compilation.FindType(typeof(int)) }); Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(resolvedM1)); Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM2)); Assert.AreSame(resolvedM1, o.BestCandidate); // Call: Foo<string>(); o = new OverloadResolution(compilation, new ResolveResult[0], typeArguments: new[] { compilation.FindType(typeof(string)) }); Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM1)); Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(resolvedM2)); Assert.AreSame(resolvedM2, o.BestCandidate); // Call: Foo<int?>(); o = new OverloadResolution(compilation, new ResolveResult[0], typeArguments: new[] { compilation.FindType(typeof(int?)) }); Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM1)); Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(resolvedM2)); Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(resolvedM3)); Assert.AreSame(resolvedM3, o.BestCandidate); }
bool IsNullableTypeOrNonValueType(IType type) { return(NullableType.IsNullable(type) || type.IsReferenceType != false); }
/// <summary> /// Determines whether a variable should be inlined in non-aggressive mode, even though it is not a generated variable. /// </summary> /// <param name="next">The next top-level expression</param> /// <param name="v">The variable being eliminated by inlining.</param> /// <param name="inlinedExpression">The expression being inlined</param> static bool NonAggressiveInlineInto(ILInstruction next, FindResult findResult, ILInstruction inlinedExpression, ILVariable v) { if (findResult.Type == FindResultType.NamedArgument) { var originalStore = (StLoc)inlinedExpression.Parent; return(!originalStore.ILStackWasEmpty); } Debug.Assert(findResult.Type == FindResultType.Found); var loadInst = findResult.LoadInst; Debug.Assert(loadInst.IsDescendantOf(next)); // decide based on the source expression being inlined switch (inlinedExpression.OpCode) { case OpCode.DefaultValue: case OpCode.StObj: case OpCode.NumericCompoundAssign: case OpCode.UserDefinedCompoundAssign: case OpCode.Await: case OpCode.SwitchInstruction: return(true); case OpCode.LdLoc: if (v.StateMachineField == null && ((LdLoc)inlinedExpression).Variable.StateMachineField != null) { // Roslyn likes to put the result of fetching a state machine field into a temporary variable, // so inline more aggressively in such cases. return(true); } break; } if (inlinedExpression.ResultType == StackType.Ref) { // VB likes to use ref locals for compound assignment // (the C# compiler uses ref stack slots instead). // We want to avoid unnecessary ref locals, so we'll always inline them if possible. return(true); } var parent = loadInst.Parent; if (NullableLiftingTransform.MatchNullableCtor(parent, out _, out _)) { // inline into nullable ctor call in lifted operator parent = parent.Parent; } if (parent is ILiftableInstruction liftable && liftable.IsLifted) { return(true); // inline into lifted operators } // decide based on the new parent into which we are inlining: switch (parent.OpCode) { case OpCode.NullCoalescingInstruction: if (NullableType.IsNullable(v.Type)) { return(true); // inline nullables into ?? operator } break; case OpCode.NullableUnwrap: return(true); // inline into ?. operator case OpCode.UserDefinedLogicOperator: case OpCode.DynamicLogicOperatorInstruction: return(true); // inline into (left slot of) user-defined && or || operator case OpCode.DynamicGetMemberInstruction: case OpCode.DynamicGetIndexInstruction: if (parent.Parent.OpCode == OpCode.DynamicCompoundAssign) { return(true); // inline into dynamic compound assignments } break; case OpCode.DynamicCompoundAssign: return(true); case OpCode.GetPinnableReference: case OpCode.LocAllocSpan: return(true); // inline size-expressions into localloc.span case OpCode.Call: case OpCode.CallVirt: // Aggressive inline into property/indexer getter calls for compound assignment calls // (The compiler generates locals for these because it doesn't want to evalute the args twice for getter+setter) if (parent.SlotInfo == CompoundAssignmentInstruction.TargetSlot) { return(true); } if (((CallInstruction)parent).Method is SyntheticRangeIndexAccessor) { return(true); } break; case OpCode.LdElema: if (((LdElema)parent).WithSystemIndex) { return(true); } break; case OpCode.Leave: case OpCode.YieldReturn: return(true); case OpCode.SwitchInstruction: //case OpCode.BinaryNumericInstruction when parent.SlotInfo == SwitchInstruction.ValueSlot: case OpCode.StringToInt when parent.SlotInfo == SwitchInstruction.ValueSlot: return(true); case OpCode.MatchInstruction when((MatchInstruction)parent).IsDeconstructTuple: return(true); } // decide based on the top-level target instruction into which we are inlining: switch (next.OpCode) { case OpCode.IfInstruction: while (parent.MatchLogicNot(out _)) { parent = parent.Parent; } return(parent == next); default: return(false); } }
private static object NewNullableInstanceSlow(Type type) { Type concrete = NullableType.MakeGenericType(type); return(Activator.CreateInstance(concrete)); }
private static void CheckLong(ConversionBlock block, Expression expression, IType expectedType, IType fromType, bool isChecked) { if (!NeedsNarrowingNumericConversion(fromType, expectedType)) { return; } if (isChecked) { expectedType = NullableType.IsNullable(expectedType) ? NullableType.GetUnderlyingType(expectedType) : expectedType; block.Write(JS.Types.System.Int64.CHECK); block.WriteOpenParentheses(); block.AfterOutput += ", "; block.AfterOutput += BridgeTypes.ToJsName(expectedType, block.Emitter); block.AfterOutput += ")"; } else { string action = null; expectedType = NullableType.IsNullable(expectedType) ? NullableType.GetUnderlyingType(expectedType) : expectedType; if (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression)) { action = "toNumber"; } else if (expectedType.IsKnownType(KnownTypeCode.Char)) { action = "clipu16"; } else if (expectedType.IsKnownType(KnownTypeCode.SByte)) { action = "clip8"; } else if (expectedType.IsKnownType(KnownTypeCode.Byte)) { action = "clipu8"; } else if (expectedType.IsKnownType(KnownTypeCode.Int16)) { action = "clip16"; } else if (expectedType.IsKnownType(KnownTypeCode.UInt16)) { action = "clipu16"; } else if (expectedType.IsKnownType(KnownTypeCode.Int32)) { action = "clip32"; } else if (expectedType.IsKnownType(KnownTypeCode.UInt32)) { action = "clipu32"; } else if (expectedType.IsKnownType(KnownTypeCode.Int64)) { action = "clip64"; } else if (expectedType.IsKnownType(KnownTypeCode.UInt64)) { action = "clipu64"; } else { throw new ArgumentException("Can not narrow to " + expectedType, "expectedType"); } block.Write(JS.Types.System.Int64.NAME + "."); block.Write(action); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } }
public static string ToJsName(IType type, IEmitter emitter, bool asDefinition = false, bool excludens = false) { if (type.Kind == TypeKind.Array) { return("Array"); } if (type.Kind == TypeKind.Dynamic) { return("Object"); } if (NullableType.IsNullable(type)) { return(BridgeTypes.ToJsName(NullableType.GetUnderlyingType(type), emitter)); } BridgeType bridgeType = emitter.BridgeTypes.Get(type, true); var name = excludens ? "" : type.Namespace; var hasTypeDef = bridgeType != null && bridgeType.TypeDefinition != null; if (hasTypeDef) { var typeDef = bridgeType.TypeDefinition; if (typeDef.IsNested && !excludens) { name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(typeDef); } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(typeDef.Name); } else { if (type.DeclaringType != null && !excludens) { name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(type); if (type.DeclaringType.TypeArguments.Count > 0) { name += "$" + type.TypeArguments.Count; } } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(type.Name); } bool isCustomName = false; if (bridgeType != null) { name = BridgeTypes.AddModule(name, bridgeType, out isCustomName); } if (!hasTypeDef && !isCustomName && type.TypeArguments.Count > 0) { name += "$" + type.TypeArguments.Count; } if (!asDefinition && type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(type, emitter)) { StringBuilder sb = new StringBuilder(name); bool needComma = false; sb.Append("("); foreach (var typeArg in type.TypeArguments) { if (needComma) { sb.Append(","); } needComma = true; sb.Append(BridgeTypes.ToJsName(typeArg, emitter)); } sb.Append(")"); name = sb.ToString(); } return(name); }
private static void NarrowingNumericOrEnumerationConversion(ConversionBlock block, Expression expression, IType targetType, bool fromFloatingPoint, bool isChecked, bool isNullable, bool isExplicit = true) { if (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression)) { return; } if (isChecked) { block.Write(JS.Types.BRIDGE_INT + ".check("); if (fromFloatingPoint) { block.Write(JS.Types.BRIDGE_INT + ".trunc"); block.WriteOpenParentheses(); } //expression.AcceptVisitor(block.Emitter); if (fromFloatingPoint) { block.AfterOutput += ")"; } block.AfterOutput += ", "; block.AfterOutput += BridgeTypes.ToJsName(targetType, block.Emitter); block.AfterOutput += ")"; } else { if (isNullable || fromFloatingPoint) { targetType = NullableType.IsNullable(targetType) ? NullableType.GetUnderlyingType(targetType) : targetType; string action = null; if (targetType.IsKnownType(KnownTypeCode.Char)) { action = "clipu16"; } else if (targetType.IsKnownType(KnownTypeCode.SByte)) { action = "clip8"; } else if (targetType.IsKnownType(KnownTypeCode.Byte)) { action = "clipu8"; } else if (targetType.IsKnownType(KnownTypeCode.Int16)) { action = "clip16"; } else if (targetType.IsKnownType(KnownTypeCode.UInt16)) { action = "clipu16"; } else if (targetType.IsKnownType(KnownTypeCode.Int32)) { action = "clip32"; } else if (targetType.IsKnownType(KnownTypeCode.UInt32)) { action = "clipu32"; } else if (targetType.IsKnownType(KnownTypeCode.Int64)) { action = "clip64"; } else if (targetType.IsKnownType(KnownTypeCode.UInt64)) { action = "clipu64"; } else { throw new ArgumentException("Can not narrow to " + targetType, "targetType"); } block.Write(JS.Types.BRIDGE_INT + "."); block.Write(action); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } else { var skipOuterWrap = (expression.Parent is VariableInitializer) || (expression.Parent is AssignmentExpression) || targetType.IsKnownType(KnownTypeCode.Int64) || targetType.IsKnownType(KnownTypeCode.UInt64) || targetType.IsKnownType(KnownTypeCode.Int16) || targetType.IsKnownType(KnownTypeCode.SByte); bool skipInnerWrap = false; var rr = block.Emitter.Resolver.ResolveNode(expression is CastExpression ? ((CastExpression)expression).Expression : expression, block.Emitter); var memberTargetrr = rr as MemberResolveResult; bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (rr is ThisResolveResult || rr is LocalResolveResult || rr is ConstantResolveResult || isField) { skipInnerWrap = true; } if (!skipOuterWrap) { block.WriteOpenParentheses(); } if (targetType.IsKnownType(KnownTypeCode.Char)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 65535"; } else if (targetType.IsKnownType(KnownTypeCode.SByte)) { block.Write(JS.Types.BRIDGE_INT + ".sxb("); if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 255)"; } else if (targetType.IsKnownType(KnownTypeCode.Byte)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 255"; } else if (targetType.IsKnownType(KnownTypeCode.Int16)) { block.Write(JS.Types.BRIDGE_INT + ".sxs("); if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 65535)"; } else if (targetType.IsKnownType(KnownTypeCode.UInt16)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 65535"; } else if (targetType.IsKnownType(KnownTypeCode.Int32)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " | 0"; } else if (targetType.IsKnownType(KnownTypeCode.UInt32)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " >>> 0"; } else if (targetType.IsKnownType(KnownTypeCode.Int64)) { block.Write(JS.Types.BRIDGE_INT + ".clip64("); block.AfterOutput += ")"; } else if (targetType.IsKnownType(KnownTypeCode.UInt64)) { block.Write(JS.Types.BRIDGE_INT + ".clipu64("); block.AfterOutput += ")"; } else { throw new ArgumentException("Can not narrow to " + targetType, "targetType"); } if (!skipOuterWrap) { block.AfterOutput += ")"; } } } }
private void UpdateContext(Solution solution, Project project, Compilation compilation, ReflectionCache reflectionCache) { Solution = solution; Project = project; Compilation = compilation; ReflectionCache = reflectionCache; // var diagnostics = compilation.GetDiagnostics(); // var mscorlib = compilation.GetReferencedAssemblySymbol(project.MetadataReferences.First()); // var typeNames = mscorlib.TypeNames.OrderBy(x => x).ToArray(); ObjectToString = compilation.ObjectType.GetMembers("ToString").OfType <IMethodSymbol>().Single(); String = compilation.FindType("System.String"); SpecialFunctions = compilation.FindType("System.Runtime.WootzJs.SpecialFunctions"); DefaultOf = SpecialFunctions.GetMethod("DefaultOf"); Char = compilation.FindType("System.Char"); Byte = compilation.FindType("System.Byte"); Int16 = compilation.FindType("System.Int16"); Int32 = compilation.FindType("System.Int32"); Int64 = compilation.FindType("System.Int64"); SByte = compilation.FindType("System.SByte"); UInt16 = compilation.FindType("System.UInt16"); UInt32 = compilation.FindType("System.UInt32"); UInt64 = compilation.FindType("System.UInt64"); Single = compilation.FindType("System.Single"); Double = compilation.FindType("System.Double"); Decimal = compilation.FindType("System.Decimal"); Exception = compilation.FindType("System.Exception"); InternalInit = Exception.GetMethodByName("InternalInit"); Assembly = compilation.FindType("System.Reflection.Assembly"); AssemblyConstructor = Assembly.InstanceConstructors.Single(); JsAttributeType = compilation.FindType("System.Runtime.WootzJs.JsAttribute"); JsCompilerOptionsAttribute = compilation.FindType("System.Runtime.WootzJs.JsCompilerOptionsAttribute"); PrecedesAttribute = compilation.FindType("System.Runtime.WootzJs.DependsOnAttribute"); ObjectType = compilation.FindType("System.Object"); GetType = ObjectType.GetMethod("GetType"); ObjectReferenceEquals = (IMethodSymbol)ObjectType.GetMembers("ReferenceEquals").Single(); ObjectCast = (IMethodSymbol)SpecialFunctions.GetMembers("ObjectCast").Single(); ObjectCreateDelegate = (IMethodSymbol)SpecialFunctions.GetMembers("CreateDelegate").Single(); TypeType = compilation.FindType("System.Type"); TypeArray = compilation.CreateArrayTypeSymbol(TypeType); TypeConstructor = TypeType.InstanceConstructors.Single(); TypeInit = (IMethodSymbol)TypeType.GetMembers("Init").Single(); CreateTypeParameter = (IMethodSymbol)TypeType.GetMembers("CreateTypeParameter").Single(); TypeIsInstanceOfType = (IMethodSymbol)TypeType.GetMembers("IsInstanceOfType").Single(); Type_GetTypeFromTypeFunc = (IMethodSymbol)TypeType.GetMembers("_GetTypeFromTypeFunc").Single(); GetField = TypeType.GetMethod("GetField", String); GetProperty = TypeType.GetMethod("GetProperty", String); GetMethod = TypeType.GetMethod("GetMethod", String, TypeArray); GetConstructor = TypeType.GetMethod("GetConstructor", TypeArray); AsExtensionType = compilation.FindType("System.Runtime.WootzJs.AsExtension"); JsniType = compilation.FindType("System.Runtime.WootzJs.Jsni"); EnumType = compilation.FindType("System.Enum"); EnumGetValue = EnumType.GetMethod("GetValue"); EnumInternalToObject = EnumType.GetMethod("InternalToObject"); Enumerable = compilation.FindType("System.Collections.IEnumerable"); EnumerableGeneric = compilation.FindType("System.Collections.Generic.IEnumerable`1"); Enumerator = compilation.FindType("System.Collections.IEnumerator"); EnumerableGetEnumerator = (IMethodSymbol)Enumerable.GetMembers("GetEnumerator").Single(); EnumeratorCurrent = (IPropertySymbol)Enumerator.GetMembers("Current").Single(); EnumeratorMoveNext = (IMethodSymbol)Enumerator.GetMembers("MoveNext").Single(); DelegateType = compilation.FindType("System.Delegate"); DelegateTypeConstructor = DelegateType.InstanceConstructors.Single(); DelegateTarget = (IPropertySymbol)DelegateType.GetMembers("Target").Single(); DelegateCombine = DelegateType.GetMembers("Combine").OfType <IMethodSymbol>().Single(x => x.Parameters.Count() == 2 && x.Parameters.All(y => Equals(y.Type, DelegateType))); DelegateRemove = DelegateType.GetMembers("Remove").OfType <IMethodSymbol>().Single(x => x.Parameters.Count() == 2 && x.Parameters.All(y => Equals(y.Type, DelegateType))); MulticastDelegateType = compilation.FindType("System.MulticastDelegate"); MulticastDelegateConstructor = MulticastDelegateType.InstanceConstructors.Single(x => x.Parameters.Last().Type.TypeKind == TypeKind.Array); NullableType = compilation.FindType("System.Nullable`1"); CharNullable = NullableType.Construct(Char); NullableHasValue = (IPropertySymbol)NullableType.GetMembers("HasValue").Single(); NullableValue = (IPropertySymbol)NullableType.GetMembers("Value").Single(); NullableGetValueOrDefault = (IMethodSymbol)NullableType.GetMembers("GetValueOrDefault").Single(); FieldInfo = compilation.FindType("System.Reflection.FieldInfo"); MethodInfo = compilation.FindType("System.Reflection.MethodInfo"); MemberInfo = compilation.FindType("System.Reflection.MemberInfo"); PropertyInfo = compilation.FindType("System.Reflection.PropertyInfo"); EventInfo = compilation.FindType("System.Reflection.EventInfo"); ConstructorInfo = compilation.FindType("System.Reflection.ConstructorInfo"); Attribute = compilation.FindType("System.Attribute"); FieldInfoConstructor = FieldInfo.InstanceConstructors.Single(); MethodInfoConstructor = MethodInfo.InstanceConstructors.Single(); ParameterInfo = compilation.FindType("System.Reflection.ParameterInfo"); ParameterInfoConstructor = ParameterInfo.InstanceConstructors.Single(); PropertyInfoConstructor = PropertyInfo.InstanceConstructors.Single(); EventInfoConstructor = EventInfo.InstanceConstructors.Single(); ConstructorInfoConstructor = ConstructorInfo.InstanceConstructors.Single(); TypeAttributes = compilation.FindType("System.Reflection.TypeAttributes"); TypeAttributesPublic = (IFieldSymbol)TypeAttributes.GetMembers("Public").Single(); TypeAttributesNotPublic = (IFieldSymbol)TypeAttributes.GetMembers("NotPublic").Single(); TypeAttributesNestedPublic = (IFieldSymbol)TypeAttributes.GetMembers("NestedPublic").Single(); TypeAttributesNestedPrivate = (IFieldSymbol)TypeAttributes.GetMembers("NestedPrivate").Single(); TypeAttributesNestedFamily = (IFieldSymbol)TypeAttributes.GetMembers("NestedFamily").Single(); TypeAttributesNestedAssembly = (IFieldSymbol)TypeAttributes.GetMembers("NestedAssembly").Single(); TypeAttributesNestedFamANDAssem = (IFieldSymbol)TypeAttributes.GetMembers("NestedFamANDAssem").Single(); TypeAttributesNestedFamORAssem = (IFieldSymbol)TypeAttributes.GetMembers("NestedFamORAssem").Single(); TypeAttributesAbstract = (IFieldSymbol)TypeAttributes.GetMembers("Abstract").Single(); TypeAttributesSealed = (IFieldSymbol)TypeAttributes.GetMembers("Sealed").Single(); TypeAttributesClass = (IFieldSymbol)TypeAttributes.GetMembers("Class").Single(); TypeAttributesInterface = (IFieldSymbol)TypeAttributes.GetMembers("Interface").Single(); FieldAttributes = compilation.FindType("System.Reflection.FieldAttributes"); FieldAttributesPublic = (IFieldSymbol)FieldAttributes.GetMembers("Public").Single(); FieldAttributesPrivate = (IFieldSymbol)FieldAttributes.GetMembers("Private").Single(); FieldAttributesFamily = (IFieldSymbol)FieldAttributes.GetMembers("Family").Single(); FieldAttributesAssembly = (IFieldSymbol)FieldAttributes.GetMembers("Assembly").Single(); FieldAttributesFamORAssem = (IFieldSymbol)FieldAttributes.GetMembers("FamORAssem").Single(); FieldAttributesStatic = (IFieldSymbol)FieldAttributes.GetMembers("Static").Single(); FieldAttributesInitOnly = (IFieldSymbol)FieldAttributes.GetMembers("InitOnly").Single(); FieldAttributesLiteral = (IFieldSymbol)FieldAttributes.GetMembers("Literal").Single(); MethodAttributes = compilation.FindType("System.Reflection.MethodAttributes"); MethodAttributesPublic = (IFieldSymbol)MethodAttributes.GetMembers("Public").Single(); MethodAttributesPrivate = (IFieldSymbol)MethodAttributes.GetMembers("Private").Single(); MethodAttributesFamily = (IFieldSymbol)MethodAttributes.GetMembers("Family").Single(); MethodAttributesAssembly = (IFieldSymbol)MethodAttributes.GetMembers("Assembly").Single(); MethodAttributesFamORAssem = (IFieldSymbol)MethodAttributes.GetMembers("FamORAssem").Single(); MethodAttributesStatic = (IFieldSymbol)MethodAttributes.GetMembers("Static").Single(); ParameterAttributes = compilation.FindType("System.Reflection.ParameterAttributes"); ParameterAttributesOut = (IFieldSymbol)ParameterAttributes.GetMembers("Out").Single(); ParameterAttributesHasDefault = (IFieldSymbol)ParameterAttributes.GetMembers("HasDefault").Single(); ParameterAttributesNone = (IFieldSymbol)ParameterAttributes.GetMembers("None").Single(); JsFunction = compilation.FindType("System.Runtime.WootzJs.JsFunction"); IDisposable = compilation.FindType("System.IDisposable"); IDisposableDispose = (IMethodSymbol)IDisposable.GetMembers("Dispose").Single(); Expression = compilation.FindType("System.Linq.Expressions.Expression"); ExpressionGeneric = compilation.FindType("System.Linq.Expressions.Expression`1"); ExpressionArray = compilation.CreateArrayTypeSymbol(Expression); ExpressionType = compilation.FindType("System.Linq.Expressions.ExpressionType"); ExpressionLambda = compilation.FindType("System.Linq.Expressions.Expression`1"); ParameterExpression = compilation.FindType("System.Linq.Expressions.ParameterExpression"); ParameterExpressionArray = compilation.CreateArrayTypeSymbol(ParameterExpression); NewExpression = compilation.FindType("System.Linq.Expressions.NewExpression"); MemberBinding = compilation.FindType("System.Linq.Expressions.MemberBinding"); MemberBindingArray = compilation.CreateArrayTypeSymbol(MemberBinding); ElementInit = compilation.FindType("System.Linq.Expressions.ElementInit"); ElementInitArray = compilation.CreateArrayTypeSymbol(ElementInit); Constant = compilation.FindType("System.Linq.Expressions.ConstantExpression"); Action = compilation.FindType("System.Action"); ActionT = compilation.FindType("System.Action`1"); Func = compilation.FindType("System.Func`1"); JsObject = compilation.FindType("System.Runtime.WootzJs.JsObject"); JsString = compilation.FindType("System.Runtime.WootzJs.JsString"); SafeToString = SpecialFunctions.GetMembers("SafeToString").OfType <IMethodSymbol>().Single(); Array = compilation.FindType("System.Array"); INotifyPropertyChanged = compilation.FindType("System.ComponentModel.INotifyPropertyChanged"); Task = compilation.FindType("System.Threading.Tasks.Task"); TaskT = compilation.FindType("System.Threading.Tasks.Task`1"); TaskAwaiter = compilation.FindType("System.Runtime.CompilerServices.TaskAwaiter"); TaskAwaiterT = compilation.FindType("System.Runtime.CompilerServices.TaskAwaiter`1"); Nop = compilation.FindType("System.Runtime.CompilerServices.Op").GetMethod("Nothing"); AsyncVoidMethodBuilder = compilation.FindType("System.Runtime.CompilerServices.AsyncVoidMethodBuilder"); AsyncVoidMethodBuilderCreate = AsyncVoidMethodBuilder.GetMethod("Create"); AsyncVoidMethodBuilderStart = AsyncVoidMethodBuilder.GetMethod("Start"); AsyncTaskMethodBuilder = compilation.FindType("System.Runtime.CompilerServices.AsyncTaskMethodBuilder"); AsyncTaskMethodBuilderCreate = AsyncTaskMethodBuilder.GetMethod("Create"); AsyncTaskMethodBuilderStart = AsyncTaskMethodBuilder.GetMethod("Start"); AsyncTaskTMethodBuilder = compilation.FindType("System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1"); AsyncTaskTMethodBuilderCreate = AsyncTaskTMethodBuilder.GetMethod("Create"); AsyncTaskTMethodBuilderStart = AsyncTaskTMethodBuilder.GetMethod("Start"); CallerMemberNameAttribute = compilation.FindType("System.Runtime.CompilerServices.CallerMemberNameAttribute"); CultureInfo = compilation.FindType("System.Globalization.CultureInfo"); InvalidOperationException = compilation.FindType("System.InvalidOperationException"); InvalidOperationExceptionStringConstructor = InvalidOperationException.Constructors.Single(x => x.Parameters.Count() == 1 && x.Parameters.First().Type == String); IAsyncStateMachine = compilation.FindType("System.Runtime.CompilerServices.IAsyncStateMachine"); IAsyncStateMachineMoveNext = IAsyncStateMachine.GetMethodByName("MoveNext"); IAsyncStateMachineSetStateMachine = IAsyncStateMachine.GetMethodByName("SetStateMachine"); IEnumerator = compilation.FindType("System.Collections.IEnumerator"); IEnumerable = compilation.FindType("System.Collections.IEnumerable"); IEnumeratorT = compilation.FindType("System.Collections.Generic.IEnumerator`1"); IEnumerableT = compilation.FindType("System.Collections.Generic.IEnumerable`1"); IEnumeratorCurrent = (IPropertySymbol)IEnumerator.GetMembers("Current").Single(); IEnumeratorMoveNext = (IMethodSymbol)IEnumerator.GetMembers("MoveNext").Single(); IEnumeratorReset = (IMethodSymbol)IEnumerator.GetMembers("Reset").Single(); IEnumerableGetEnumerator = (IMethodSymbol)IEnumerable.GetMembers("GetEnumerator").Single(); IEnumeratorTCurrent = (IPropertySymbol)IEnumeratorT.GetMembers("Current").Single(); IEnumerableTGetEnumerator = (IMethodSymbol)IEnumerableT.GetMembers("GetEnumerator").Single(); YieldIterator = compilation.FindType("System.YieldIterator`1"); YieldIteratorClone = YieldIterator.GetMethodByName("Clone"); YieldIteratorDoMoveNext = YieldIterator.GetMethodByName("DoMoveNext"); NullPropagation = SpecialFunctions.GetMethod("NullPropagation"); // IAutoNotifyPropertyChanged = compilation.FindType("System.Runtime.WootzJs.IAutoNotifyPropertyChanged"); // NotifyPropertyChanged = IAutoNotifyPropertyChanged.GetMethod("NotifyPropertyChanged"); }
public static void ClipInteger(ConversionBlock block, Expression expression, IType type, bool isExplicit) { var specialType = NullableType.IsNullable(type) ? NullableType.GetUnderlyingType(type) : type; if (!isExplicit && (specialType.IsKnownType(KnownTypeCode.UInt64) || specialType.IsKnownType(KnownTypeCode.Int64))) { //expression.AcceptVisitor(block.Emitter); return; } NarrowingNumericOrEnumerationConversion(block, expression, specialType, false, false, NullableType.IsNullable(type), isExplicit); }
public static void CheckInteger(ConversionBlock block, Expression expression, IType type) { NarrowingNumericOrEnumerationConversion(block, expression, NullableType.IsNullable(type) ? NullableType.GetUnderlyingType(type) : type, false, true, NullableType.IsNullable(type)); }
/// <summary> /// Implements the constructor: NullableType() /// Direct superclasses: global::MetaDslx.Soal.SoalType /// All superclasses: global::MetaDslx.Soal.SoalType /// </summary> public virtual void NullableType(NullableType @this) { this.SoalType(@this); }