示例#1
0
        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());
        }
示例#2
0
        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(")");
            }
        }
示例#3
0
        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);
        }
示例#4
0
文件: ILInlining.cs 项目: yrest/ILSpy
        /// <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);
            }
        }
示例#5
0
        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));
            }
        }
示例#6
0
        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));
                }
            }
示例#7
0
        /// <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);
        }
示例#8
0
        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);
        }
示例#9
0
        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);
        }
示例#10
0
        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);
        }
示例#11
0
 /// <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;
 }
示例#12
0
        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));
                }
            }
示例#13
0
        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);
            }
        }
示例#14
0
        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();
                }
            }
        }
示例#15
0
        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(")");
            }
        }
示例#16
0
        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);
        }
示例#17
0
 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));
 }
示例#18
0
 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]));
 }
示例#19
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);
        }
示例#20
0
        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);
        }
示例#21
0
 /// <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);
     }
示例#22
0
        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);
        }
示例#23
0
 bool IsNullableTypeOrNonValueType(IType type)
 {
     return(NullableType.IsNullable(type) || type.IsReferenceType != false);
 }
示例#24
0
        /// <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);
            }
        }
示例#25
0
        private static object NewNullableInstanceSlow(Type type)
        {
            Type concrete = NullableType.MakeGenericType(type);

            return(Activator.CreateInstance(concrete));
        }
示例#26
0
        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 += ")";
                }
            }
        }
示例#27
0
        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);
        }
示例#28
0
        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 += ")";
                    }
                }
            }
        }
示例#29
0
        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");
        }
示例#30
0
        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);
        }
示例#31
0
 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));
 }
示例#32
0
文件: Soal.cs 项目: Bubesz/soal-cs
 /// <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);
 }