示例#1
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();
                }
            }
        }
示例#2
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));
 }
示例#3
0
        protected virtual bool WriteObject(string objectName, List <TypeConfigItem> members, string format, string interfaceFormat)
        {
            bool hasProperties = this.HasProperties(objectName, members);

            if (hasProperties && objectName != null)
            {
                this.EnsureComma();
                this.Write(objectName);

                this.WriteColon();
                this.BeginBlock();
            }

            bool isProperty = JS.Fields.PROPERTIES == objectName;

            foreach (var member in members)
            {
                object constValue    = null;
                bool   isPrimitive   = false;
                var    primitiveExpr = member.Initializer as PrimitiveExpression;
                bool   write         = false;
                bool   writeScript   = false;

                if (primitiveExpr != null)
                {
                    isPrimitive = true;
                    constValue  = primitiveExpr.Value;
                    //writeScript = true;
                }

                if (constValue is RawValue)
                {
                    constValue  = constValue.ToString();
                    write       = true;
                    writeScript = false;
                }

                var isNull = member.Initializer.IsNull || member.Initializer is NullReferenceExpression;

                if (!isNull && !isPrimitive)
                {
                    var constrr = this.Emitter.Resolver.ResolveNode(member.Initializer, this.Emitter);
                    if (constrr != null && constrr.IsCompileTimeConstant)
                    {
                        isPrimitive = true;
                        constValue  = constrr.ConstantValue;
                        writeScript = true;
                    }
                }

                var isNullable = false;

                if (isPrimitive && constValue is AstType)
                {
                    var itype = this.Emitter.Resolver.ResolveNode((AstType)constValue, this.Emitter);

                    if (NullableType.IsNullable(itype.Type))
                    {
                        isNullable = true;
                    }
                }

                if (!isNull && (!isPrimitive || (constValue is AstType)))
                {
                    string value        = null;
                    bool   needContinue = false;
                    string defValue     = "";
                    if (!isPrimitive)
                    {
                        var oldWriter = this.SaveWriter();
                        this.NewWriter();
                        member.Initializer.AcceptVisitor(this.Emitter);
                        value = this.Emitter.Output.ToString();
                        this.RestoreWriter(oldWriter);

                        ResolveResult rr      = null;
                        AstType       astType = null;
                        if (member.VarInitializer != null)
                        {
                            rr = this.Emitter.Resolver.ResolveNode(member.VarInitializer, this.Emitter);
                        }
                        else
                        {
                            astType = member.Entity.ReturnType;
                            rr      = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter);
                        }

                        constValue   = Inspector.GetDefaultFieldValue(rr.Type, astType);
                        isNullable   = NullableType.IsNullable(rr.Type);
                        needContinue = constValue is IType;
                        writeScript  = true;

                        if (needContinue && !(member.Initializer is ObjectCreateExpression))
                        {
                            defValue = " || " + Inspector.GetStructDefaultValue((IType)constValue, this.Emitter);
                        }
                    }
                    else
                    {
                        value        = isNullable ? "null" : Inspector.GetStructDefaultValue((AstType)constValue, this.Emitter);
                        constValue   = value;
                        write        = true;
                        needContinue = !isProperty && !isNullable;
                    }

                    var name = member.GetName(this.Emitter);
                    if (isProperty && isPrimitive)
                    {
                        constValue = "null";
                        this.Injectors.Add(string.Format(name.StartsWith("\"") ? "this[{0}] = {1};" : "this.{0} = {1};", name, value));
                    }
                    else
                    {
                        this.Injectors.Add(string.Format(name.StartsWith("\"") ? interfaceFormat : format, name, value + defValue));
                    }

                    if (needContinue)
                    {
                        continue;
                    }
                }

                this.EnsureComma();
                XmlToJsDoc.EmitComment(this, member.Entity);
                this.Write(member.GetName(this.Emitter, true));
                this.WriteColon();

                if (constValue is AstType)
                {
                    if (isNullable)
                    {
                        this.Write("null");
                    }
                    else
                    {
                        this.Write(Inspector.GetStructDefaultValue((AstType)constValue, this.Emitter));
                    }
                }
                else if (constValue is IType)
                {
                    if (isNullable)
                    {
                        this.Write("null");
                    }
                    else
                    {
                        this.Write(Inspector.GetStructDefaultValue((IType)constValue, this.Emitter));
                    }
                }
                else if (write)
                {
                    this.Write(constValue);
                }
                else if (writeScript)
                {
                    this.WriteScript(constValue);
                }
                else
                {
                    member.Initializer.AcceptVisitor(this.Emitter);
                }

                this.Emitter.Comma = true;
            }

            if (hasProperties && objectName != null)
            {
                this.WriteNewLine();
                this.EndBlock();
            }

            return(hasProperties);
        }
示例#4
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="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
        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 += ")";
                    }
                }
            }
        }
示例#6
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);

            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;
            }

            var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter);
            var typerr       = this.Emitter.Resolver.ResolveNode(type, this.Emitter);

            if (expressionrr.Type.Kind == TypeKind.Enum)
            {
                var enumMode = this.Emitter.Validator.EnumEmitMode(expressionrr.Type);
                if (enumMode >= 3 && enumMode < 7 && Helpers.IsIntegerType(itype, this.Emitter.Resolver))
                {
                    throw new EmitterException(this.CastExpression, "Enum underlying type is string and cannot be casted to number");
                }
            }

            if (method == CS.Ops.CAST && expressionrr.Type.Kind != TypeKind.Enum)
            {
                var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter);

                if (cast_rr is ConstantResolveResult)
                {
                    var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression);
                    var value        = ((ConstantResolveResult)cast_rr).ConstantValue;

                    this.WriteCastValue(value, expectedType);
                    return;
                }
                else
                {
                    var conv_rr = cast_rr as ConversionResolveResult;
                    if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined)
                    {
                        var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression);
                        var value        = ((ConstantResolveResult)conv_rr.Input).ConstantValue;
                        this.WriteCastValue(value, expectedType);
                        return;
                    }
                }
            }

            if (method == CS.Ops.IS && castToEnum)
            {
                this.Write(JS.Types.Bridge.IS);
                this.WriteOpenParentheses();
                expression.AcceptVisitor(this.Emitter);
                this.Write(", ");
                this.Write(BridgeTypes.ToJsName(itype, this.Emitter));
                this.Write(")");
                return;
            }

            if (expressionrr.Type.Equals(itype))
            {
                if (method == CS.Ops.IS)
                {
                    this.Write(JS.Funcs.BRIDGE_HASVALUE);
                    this.WriteOpenParentheses();
                }
                expression.AcceptVisitor(this.Emitter);
                if (method == CS.Ops.IS)
                {
                    this.Write(")");
                }

                return;
            }

            bool isResultNullable = NullableType.IsNullable(typerr.Type);

            if (castCode != null)
            {
                this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method);
                return;
            }

            bool isCast = method == CS.Ops.CAST;

            if (isCast)
            {
                if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression))
                {
                    expression.AcceptVisitor(this.Emitter);

                    return;
                }
            }

            var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression);

            if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion))
            {
                expression.AcceptVisitor(this.Emitter);
                return;
            }

            var  simpleType = type as SimpleType;
            bool hasValue   = false;

            if (simpleType != null && simpleType.Identifier == "dynamic")
            {
                if (method == CS.Ops.CAST || method == CS.Ops.AS)
                {
                    expression.AcceptVisitor(this.Emitter);
                    return;
                }
                else if (method == CS.Ops.IS)
                {
                    hasValue = true;
                    method   = "hasValue";
                }
            }

            bool unbox = !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion;

            if (unbox)
            {
                this.Write("System.Nullable.getValue(");
            }

            this.Write(JS.NS.BRIDGE);
            this.WriteDot();
            this.Write(method);
            this.WriteOpenParentheses();

            expression.AcceptVisitor(this.Emitter);

            if (!hasValue)
            {
                this.WriteComma();
                this.EmitCastType(itype);
            }

            if (isResultNullable && method != CS.Ops.IS)
            {
                this.WriteComma();
                this.WriteScript(true);
            }

            this.WriteCloseParentheses();

            if (unbox)
            {
                this.Write(")");
            }
        }
示例#7
0
        protected virtual bool WriteObject(string objectName, List <TypeConfigItem> members, Func <TypeConfigItem, string, string> format, FieldTypeEnum type)
        {
            bool hasProperties = this.HasProperties(members);

            if (hasProperties && objectName != null)
            {
                this.EnsureComma();
                this.Write(objectName);

                this.WriteEqualsSign();
                this.BeginBlock();
            }

            foreach (var member in members)
            {
                object constValue    = null;
                bool   isPrimitive   = false;
                var    primitiveExpr = member.Initializer as PrimitiveExpression;
                if (primitiveExpr != null)
                {
                    isPrimitive = true;
                    constValue  = primitiveExpr.Value;
                }

                var isNull = member.Initializer.IsNull || member.Initializer is NullReferenceExpression;

                if (!isNull && !isPrimitive)
                {
                    var resolveResult = this.Emitter.Resolver.ResolveNode(member.Initializer, this.Emitter);
                    if (resolveResult != null && resolveResult.IsCompileTimeConstant)
                    {
                        isPrimitive = true;
                        constValue  = resolveResult.ConstantValue;
                    }
                }

                var isNullable = false;

                if (isPrimitive && constValue is AstType)
                {
                    var itype = this.Emitter.Resolver.ResolveNode((AstType)constValue, this.Emitter);

                    if (NullableType.IsNullable(itype.Type))
                    {
                        isNullable = true;
                    }
                }

                if (type == FieldTypeEnum.Property || type == FieldTypeEnum.Event)
                {
                    this.PushWriter("{0}");
                    member.Initializer.AcceptVisitor(this.Emitter);
                    string value = this.PopWriter(true);
                    this.Injectors.Add(format(member, value));
                    continue;
                }

                if (!isNull && (!isPrimitive || (constValue is AstType)))
                {
                    string value = null;

                    if (!isPrimitive)
                    {
                        this.PushWriter("{0}");
                        member.Initializer.AcceptVisitor(this.Emitter);
                        value = this.PopWriter(true);

                        //var oldWriter = this.SaveWriter();
                        //this.NewWriter();
                        //member.Initializer.AcceptVisitor(this.Emitter);
                        //value = this.Emitter.Output.ToString();
                        //this.RestoreWriter(oldWriter);
                    }
                    else
                    {
                        if (isNullable)
                        {
                            value = LuaHelper.Nil;
                        }
                        else
                        {
                            AstType astType = (AstType)constValue;
                            var     rr      = Emitter.Resolver.ResolveNode(astType, Emitter);
                            var     def     = Inspector.GetDefaultFieldValue(rr.Type);
                            if (def == rr.Type)
                            {
                                value = Inspector.GetStructDefaultValue(rr.Type, this.Emitter);
                            }
                            else
                            {
                                value = def.ToString();
                            }
                        }
                    }

                    this.Injectors.Add(format(member, value));
                    continue;
                }

                PushWriter("{0}");
                if (constValue is AstType)
                {
                    if (isNullable)
                    {
                        this.Write(LuaHelper.Nil);
                    }
                    else
                    {
                        AstType astType = (AstType)constValue;
                        var     rr      = Emitter.Resolver.ResolveNode(astType, Emitter);
                        var     def     = Inspector.GetDefaultFieldValue(rr.Type);
                        if (def == rr.Type)
                        {
                            this.Write(Inspector.GetStructDefaultValue(rr.Type, this.Emitter));
                        }
                        else
                        {
                            this.WriteScript(def);
                        }
                    }
                }
                else
                {
                    member.Initializer.AcceptVisitor(this.Emitter);
                }

                string fieldValue = PopWriter(true);
                if (fieldValue != LuaHelper.Nil)
                {
                    this.EnsureComma();
                    XmlToJsDoc.EmitComment(this, member.Entity);
                    this.Write(member.GetName(this.Emitter));
                    this.WriteEqualsSign();
                    this.Write(fieldValue);
                    this.Emitter.Comma = true;
                }
            }

            if (hasProperties && objectName != null)
            {
                this.WriteNewLine();
                this.EndBlock();
            }

            return(hasProperties);
        }
示例#8
0
        protected virtual void EmitArrayAccess(IndexerExpression indexerExpression)
        {
            string targetVar      = null;
            bool   writeTargetVar = false;
            bool   isStatement    = false;
            string valueVar       = null;
            var    resolveResult  = this.Emitter.Resolver.ResolveNode(indexerExpression, this.Emitter);

            if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
            {
                writeTargetVar = true;
            }
            else if (this.Emitter.IsUnaryAccessor)
            {
                writeTargetVar = true;

                isStatement = indexerExpression.Parent is UnaryOperatorExpression && indexerExpression.Parent.Parent is ExpressionStatement;

                if (NullableType.IsNullable(resolveResult.Type))
                {
                    isStatement = false;
                }

                if (!isStatement)
                {
                    this.WriteOpenParentheses();
                }
            }

            if (writeTargetVar)
            {
                var  targetrr       = this.Emitter.Resolver.ResolveNode(indexerExpression.Target, this.Emitter);
                var  memberTargetrr = targetrr as MemberResolveResult;
                bool isField        = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult);

                if (!(targetrr is ThisResolveResult || targetrr is LocalResolveResult || isField))
                {
                    targetVar = this.GetTempVarName();

                    this.Write(targetVar);
                    this.Write(" = ");
                }
            }

            if (this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null)
            {
                valueVar = this.GetTempVarName();

                this.Write(valueVar);
                this.Write(" = ");
            }

            var oldIsAssignment = this.Emitter.IsAssignment;
            var oldUnary        = this.Emitter.IsUnaryAccessor;

            this.Emitter.IsAssignment    = false;
            this.Emitter.IsUnaryAccessor = false;
            indexerExpression.Target.AcceptVisitor(this.Emitter);
            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);
                }
            }

            this.WriteDot();

            var argsInfo        = new ArgumentsInfo(this.Emitter, indexerExpression);
            var argsExpressions = argsInfo.ArgumentsExpressions;
            var paramsArg       = argsInfo.ParamsExpression;

            if (!this.Emitter.IsAssignment)
            {
                if (this.Emitter.IsUnaryAccessor)
                {
                    bool isDecimal  = Helpers.IsDecimalType(resolveResult.Type, this.Emitter.Resolver);
                    bool isNullable = NullableType.IsNullable(resolveResult.Type);

                    if (isStatement)
                    {
                        this.Write("set");
                        this.WriteOpenParentheses();
                        this.WriteOpenBracket();
                        new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                        this.WriteCloseBracket();
                        this.WriteComma(false);

                        if (isDecimal)
                        {
                            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();

                                if (targetVar != null)
                                {
                                    this.Write(targetVar);
                                }
                                else
                                {
                                    indexerExpression.Target.AcceptVisitor(this.Emitter);
                                }

                                this.WriteDot();

                                this.Write("get");
                                this.WriteOpenParentheses();
                                this.WriteOpenBracket();
                                new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                                this.WriteCloseBracket();
                                this.WriteCloseParentheses();
                                this.WriteCloseParentheses();
                            }
                            else
                            {
                                if (targetVar != null)
                                {
                                    this.Write(targetVar);
                                }
                                else
                                {
                                    indexerExpression.Target.AcceptVisitor(this.Emitter);
                                }

                                this.WriteDot();

                                this.Write("get");
                                this.WriteOpenParentheses();
                                this.WriteOpenBracket();
                                new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                                this.WriteCloseBracket();
                                this.WriteCloseParentheses();
                                this.WriteDot();
                                if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                {
                                    this.Write("inc");
                                }
                                else
                                {
                                    this.Write("dec");
                                }

                                this.WriteOpenCloseParentheses();
                            }
                        }
                        else
                        {
                            if (targetVar != null)
                            {
                                this.Write(targetVar);
                            }
                            else
                            {
                                indexerExpression.Target.AcceptVisitor(this.Emitter);
                            }

                            this.WriteDot();

                            this.Write("get");
                            this.WriteOpenParentheses();
                            this.WriteOpenBracket();
                            new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                            this.WriteCloseBracket();
                            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("get");
                        this.WriteOpenParentheses();
                        this.WriteOpenBracket();
                        new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                        this.WriteCloseBracket();
                        this.WriteCloseParentheses();
                        this.WriteComma();

                        if (targetVar != null)
                        {
                            this.Write(targetVar);
                        }
                        else
                        {
                            indexerExpression.Target.AcceptVisitor(this.Emitter);
                        }
                        this.WriteDot();
                        this.Write("set");
                        this.WriteOpenParentheses();
                        this.WriteOpenBracket();
                        new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                        this.WriteCloseBracket();
                        this.WriteComma(false);

                        if (isDecimal)
                        {
                            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.WriteDot();

                                this.Write("get");
                                this.WriteOpenParentheses();
                                this.WriteOpenBracket();
                                new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                                this.WriteCloseBracket();
                                this.WriteCloseParentheses();
                                this.WriteCloseParentheses();
                            }
                            else
                            {
                                if (targetVar != null)
                                {
                                    this.Write(targetVar);
                                }
                                else
                                {
                                    indexerExpression.Target.AcceptVisitor(this.Emitter);
                                }

                                this.WriteDot();

                                this.Write("get");
                                this.WriteOpenParentheses();
                                this.WriteOpenBracket();
                                new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                                this.WriteCloseBracket();
                                this.WriteCloseParentheses();
                                this.WriteDot();
                                if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                    this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                {
                                    this.Write("inc");
                                }
                                else
                                {
                                    this.Write("dec");
                                }

                                this.WriteOpenCloseParentheses();
                            }
                        }
                        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();

                        var isPreOp = this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                      this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement;

                        if (isPreOp)
                        {
                            if (targetVar != null)
                            {
                                this.Write(targetVar);
                            }
                            else
                            {
                                indexerExpression.Target.AcceptVisitor(this.Emitter);
                            }

                            this.WriteDot();

                            this.Write("get");
                            this.WriteOpenParentheses();
                            this.WriteOpenBracket();
                            new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                            this.WriteCloseBracket();
                            this.WriteCloseParentheses();
                        }
                        else
                        {
                            this.Write(valueVar);
                        }

                        this.WriteCloseParentheses();

                        if (valueVar != null)
                        {
                            this.RemoveTempVar(valueVar);
                        }
                    }

                    if (targetVar != null)
                    {
                        this.RemoveTempVar(targetVar);
                    }
                }
                else
                {
                    this.Write("get");
                    this.WriteOpenParentheses();
                    this.WriteOpenBracket();
                    new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                    this.WriteCloseBracket();
                    this.WriteCloseParentheses();
                }
            }
            else
            {
                if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
                {
                    var oldWriter = this.SaveWriter();
                    this.NewWriter();
                    new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                    var paramsStr = this.Emitter.Output.ToString();
                    this.RestoreWriter(oldWriter);

                    if (targetVar != null)
                    {
                        this.PushWriter(string.Concat(
                                            "set([",
                                            paramsStr,
                                            "],",
                                            targetVar,
                                            ".get([",
                                            paramsStr,
                                            "]){0})"), () => { this.RemoveTempVar(targetVar); });
                    }
                    else
                    {
                        oldWriter = this.SaveWriter();
                        this.NewWriter();

                        this.Emitter.IsAssignment    = false;
                        this.Emitter.IsUnaryAccessor = false;
                        indexerExpression.Target.AcceptVisitor(this.Emitter);
                        this.Emitter.IsAssignment    = oldIsAssignment;
                        this.Emitter.IsUnaryAccessor = oldUnary;

                        var trg = this.Emitter.Output.ToString();

                        this.RestoreWriter(oldWriter);
                        this.PushWriter(string.Concat(
                                            "set([",
                                            paramsStr,
                                            "],",
                                            trg,
                                            ".get([",
                                            paramsStr,
                                            "]){0})"));
                    }
                }
                else
                {
                    this.Write("set");
                    this.WriteOpenParentheses();
                    this.WriteOpenBracket();
                    new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                    this.WriteCloseBracket();
                    this.PushWriter(", {0})");
                }
            }
        }
示例#9
0
        public static bool CheckConversion(ConversionBlock block, Expression expression)
        {
            Conversion conversion = null;

            try
            {
                var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter);
                conversion = block.Emitter.Resolver.Resolver.GetConversion(expression);
                var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression);

                var invocationExpression = expression.Parent as InvocationExpression;
                if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression))
                {
                    var index = invocationExpression.Arguments.ToList().IndexOf(expression);
                    var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult;

                    var m   = methodResolveResult.Member as IMethod;
                    var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)];

                    if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var namedArgExpression = expression.Parent as NamedArgumentExpression;
                if (namedArgExpression != null)
                {
                    var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult;

                    if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var namedExpression = expression.Parent as NamedExpression;
                if (namedExpression != null)
                {
                    var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter);

                    if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var binaryOpExpr = expression.Parent as BinaryOperatorExpression;
                if (binaryOpExpr != null)
                {
                    var idx        = binaryOpExpr.Left == expression ? 0 : 1;
                    var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult;

                    if (Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var assignmentExpr = expression.Parent as AssignmentExpression;
                if (assignmentExpr != null)
                {
                    var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult;

                    if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                var arrayInit = expression.Parent as ArrayInitializerExpression;
                if (arrayInit != null)
                {
                    while (arrayInit.Parent is ArrayInitializerExpression)
                    {
                        arrayInit = (ArrayInitializerExpression)arrayInit.Parent;
                    }

                    IType elementType = null;
                    var   arrayCreate = arrayInit.Parent as ArrayCreateExpression;
                    if (arrayCreate != null)
                    {
                        var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter);
                        if (rrArrayType.Type is TypeWithElementType)
                        {
                            elementType = ((TypeWithElementType)rrArrayType.Type).ElementType;
                        }
                        else
                        {
                            elementType = rrArrayType.Type;
                        }
                    }
                    else
                    {
                        var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter);
                        var pt         = rrElemenet.Type as ParameterizedType;
                        if (pt != null)
                        {
                            elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null;
                        }
                        else
                        {
                            var arrayType = rrElemenet.Type as TypeWithElementType;
                            if (arrayType != null)
                            {
                                elementType = arrayType.ElementType;
                            }
                            else
                            {
                                elementType = rrElemenet.Type;
                            }
                        }
                    }

                    if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver))
                {
                    var           castExpr   = expression.Parent as CastExpression;
                    ResolveResult castTypeRr = null;
                    if (castExpr != null)
                    {
                        castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter);
                    }

                    if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver))
                    {
                        if (expression.IsNull)
                        {
                            return(false);
                        }

                        block.Write("Bridge.Decimal");
                        if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression))
                        {
                            block.Write(".lift");
                        }
                        block.WriteOpenParentheses();
                        return(true);
                    }
                }

                if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver))
                {
                    return(false);
                }

                if (conversion == null)
                {
                    return(false);
                }

                if (conversion.IsIdentityConversion)
                {
                    return(false);
                }

                var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression);
                if (isNumLifted && !conversion.IsUserDefined)
                {
                    return(false);
                }
                bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock);
                if (isLifted)
                {
                    block.Write("Bridge.Nullable.lift(");
                }

                if (conversion.IsUserDefined)
                {
                    var method = conversion.Method;

                    string inline = block.Emitter.GetInline(method);

                    if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline))
                    {
                        // Still returns true if Nullable.lift( was written.
                        return(isLifted);
                    }

                    if (!string.IsNullOrWhiteSpace(inline))
                    {
                        if (expression is InvocationExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is ObjectCreateExpression)
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit();
                        }
                        else if (expression is UnaryOperatorExpression)
                        {
                            var unaryExpression       = (UnaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit();
                        }
                        else if (expression is BinaryOperatorExpression)
                        {
                            var binaryExpression      = (BinaryOperatorExpression)expression;
                            var resolveOperator       = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter);
                            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit();
                        }
                        else
                        {
                            new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit();
                        }

                        block.DisableEmitConversionExpression = true;

                        // Still returns true if Nullable.lift( was written.
                        return(isLifted);
                    }
                    else
                    {
                        if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition))
                        {
                            // Still returns true if Nullable.lift( was written.
                            return(isLifted);
                        }

                        block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter));
                        block.WriteDot();

                        block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName());
                    }

                    if (isLifted)
                    {
                        block.WriteComma();
                    }
                    else
                    {
                        block.WriteOpenParentheses();
                    }

                    return(true);
                }
                // Still returns true if Nullable.lift( was written.
                return(isLifted);
            }
            catch
            {
            }

            return(false);
        }
示例#10
0
        public static object GetDefaultFieldValue(IType type, AstType astType, bool wrapType = true)
        {
            if (type.Kind == TypeKind.TypeParameter && astType != null)
            {
                var parameter = type as ITypeParameter;
                if (parameter != null && (
                        parameter.Owner.Attributes.Any(a => a.AttributeType.FullName == "Bridge.IgnoreGenericAttribute") ||
                        parameter.Owner.DeclaringTypeDefinition != null && parameter.Owner.DeclaringTypeDefinition.Attributes.Any(a => a.AttributeType.FullName == "Bridge.IgnoreGenericAttribute")))
                {
                    return(null);
                }
                return(new RawValue(JS.Funcs.BRIDGE_GETDEFAULTVALUE + "(" + astType.ToString() + ")"));
            }

            if (type.IsKnownType(KnownTypeCode.Decimal))
            {
                return(0m);
            }

            if (type.IsKnownType(KnownTypeCode.Int64))
            {
                return(0L);
            }

            if (type.IsKnownType(KnownTypeCode.UInt64))
            {
                return(0UL);
            }

            if (type.IsKnownType(KnownTypeCode.Char) ||
                type.IsKnownType(KnownTypeCode.Int16) ||
                type.IsKnownType(KnownTypeCode.Int32) ||
                type.IsKnownType(KnownTypeCode.UInt16) ||
                type.IsKnownType(KnownTypeCode.UInt32) ||
                type.IsKnownType(KnownTypeCode.Byte) ||
                type.IsKnownType(KnownTypeCode.Double) ||
                type.IsKnownType(KnownTypeCode.SByte) ||
                type.IsKnownType(KnownTypeCode.Single) ||
                type.IsKnownType(KnownTypeCode.Enum))
            {
                return(0);
            }

            if (NullableType.IsNullable(type))
            {
                return(null);
            }

            if (type.IsKnownType(KnownTypeCode.Boolean))
            {
                return(false);
            }

            if (type.IsKnownType(KnownTypeCode.Enum) || type.Kind == TypeKind.Enum)
            {
                return(0);
            }

            if (type.Kind == TypeKind.Struct && wrapType)
            {
                return(type);
            }

            return(null);
        }
示例#11
0
        protected void VisitIndexerExpression()
        {
            IndexerExpression indexerExpression = this.IndexerExpression;

            IAttribute inlineAttr          = null;
            string     inlineCode          = null;
            var        resolveResult       = this.Emitter.Resolver.ResolveNode(indexerExpression, this.Emitter);
            var        memberResolveResult = resolveResult as MemberResolveResult;

            var arrayAccess = resolveResult as ArrayAccessResolveResult;

            if (arrayAccess != null && arrayAccess.Indexes.Count > 1)
            {
                this.EmitArrayAccess(indexerExpression);
                return;
            }

            var       isIgnore           = true;
            var       isAccessorsIndexer = false;
            var       ignoreAccessor     = false;
            IProperty member             = null;
            IMethod   method             = null;
            var       oldIsAssignment    = this.Emitter.IsAssignment;
            var       oldUnary           = this.Emitter.IsUnaryAccessor;

            if (memberResolveResult != null)
            {
                var resolvedMember = memberResolveResult.Member;
                isIgnore           = this.Emitter.Validator.IsIgnoreType(resolvedMember.DeclaringTypeDefinition);
                isAccessorsIndexer =
                    resolvedMember.DeclaringTypeDefinition.DirectBaseTypes.Any(
                        t => t.FullName == "Bridge.IAccessorsIndexer");

                if (resolvedMember is IProperty)
                {
                    member         = (IProperty)resolvedMember;
                    method         = this.Emitter.IsAssignment ? member.Setter : member.Getter;
                    inlineAttr     = this.Emitter.GetAttribute(method.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute");
                    ignoreAccessor = this.Emitter.Validator.HasAttribute(method.Attributes, "Bridge.IgnoreAttribute");
                }
            }

            if (inlineAttr != null)
            {
                var inlineArg = inlineAttr.PositionalArguments[0];

                if (inlineArg.ConstantValue != null)
                {
                    inlineCode = inlineArg.ConstantValue.ToString();
                }
            }

            if (inlineCode != null && inlineCode.Contains("{this}"))
            {
                this.Write("");
                var oldBuilder = this.Emitter.Output;
                this.Emitter.Output          = new StringBuilder();
                this.Emitter.IsAssignment    = false;
                this.Emitter.IsUnaryAccessor = false;
                indexerExpression.Target.AcceptVisitor(this.Emitter);
                this.Emitter.IsAssignment    = oldIsAssignment;
                this.Emitter.IsUnaryAccessor = oldUnary;
                inlineCode          = inlineCode.Replace("{this}", this.Emitter.Output.ToString());
                this.Emitter.Output = oldBuilder;

                this.PushWriter(inlineCode);
                new ExpressionListBlock(this.Emitter, indexerExpression.Arguments, null).Emit();

                if (!this.Emitter.IsAssignment)
                {
                    this.PopWriter();
                }
                else
                {
                    this.WriteComma();
                }

                return;
            }

            if (inlineAttr != null || (isIgnore && !isAccessorsIndexer))
            {
                this.Emitter.IsAssignment    = false;
                this.Emitter.IsUnaryAccessor = false;
                indexerExpression.Target.AcceptVisitor(this.Emitter);
                this.Emitter.IsAssignment    = oldIsAssignment;
                this.Emitter.IsUnaryAccessor = oldUnary;
            }

            if (inlineAttr != null)
            {
                if (inlineCode != null)
                {
                    this.WriteDot();
                    this.PushWriter(inlineCode);
                    this.Emitter.IsAssignment    = false;
                    this.Emitter.IsUnaryAccessor = false;
                    new ExpressionListBlock(this.Emitter, indexerExpression.Arguments, null).Emit();
                    this.Emitter.IsAssignment    = oldIsAssignment;
                    this.Emitter.IsUnaryAccessor = oldUnary;

                    if (!this.Emitter.IsAssignment)
                    {
                        this.PopWriter();
                    }
                    else
                    {
                        this.WriteComma();
                    }
                }
            }
            else if (!(isIgnore || ignoreAccessor) || isAccessorsIndexer)
            {
                string targetVar      = null;
                string valueVar       = null;
                bool   writeTargetVar = false;
                bool   isStatement    = false;

                if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
                {
                    writeTargetVar = true;
                }
                else if (this.Emitter.IsUnaryAccessor)
                {
                    writeTargetVar = true;

                    isStatement = indexerExpression.Parent is UnaryOperatorExpression && indexerExpression.Parent.Parent is ExpressionStatement;

                    if (memberResolveResult != null && NullableType.IsNullable(memberResolveResult.Type))
                    {
                        isStatement = false;
                    }

                    if (!isStatement)
                    {
                        this.WriteOpenParentheses();
                    }
                }

                if (writeTargetVar)
                {
                    var  targetrr       = this.Emitter.Resolver.ResolveNode(indexerExpression.Target, this.Emitter);
                    var  memberTargetrr = targetrr as MemberResolveResult;
                    bool isField        = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult);

                    if (!(targetrr is ThisResolveResult || targetrr is LocalResolveResult || isField))
                    {
                        targetVar = this.GetTempVarName();
                        this.Write(targetVar);
                        this.Write(" = ");
                    }
                }

                if (this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null)
                {
                    valueVar = this.GetTempVarName();

                    this.Write(valueVar);
                    this.Write(" = ");
                }

                this.Emitter.IsAssignment    = false;
                this.Emitter.IsUnaryAccessor = false;
                indexerExpression.Target.AcceptVisitor(this.Emitter);
                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);
                    }
                }

                this.WriteDot();
                var argsInfo        = new ArgumentsInfo(this.Emitter, indexerExpression);
                var argsExpressions = argsInfo.ArgumentsExpressions;
                var paramsArg       = argsInfo.ParamsExpression;
                var name            = Helpers.GetPropertyRef(member, this.Emitter, this.Emitter.IsAssignment);

                if (!this.Emitter.IsAssignment)
                {
                    if (this.Emitter.IsUnaryAccessor)
                    {
                        var oldWriter = this.SaveWriter();
                        this.NewWriter();
                        new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                        var paramsStr = this.Emitter.Output.ToString();
                        this.RestoreWriter(oldWriter);

                        bool isDecimal  = Helpers.IsDecimalType(member.ReturnType, this.Emitter.Resolver);
                        bool isNullable = NullableType.IsNullable(member.ReturnType);
                        if (isStatement)
                        {
                            this.Write(Helpers.GetPropertyRef(member, this.Emitter, true));
                            this.WriteOpenParentheses();
                            this.Write(paramsStr);
                            this.WriteComma(false);

                            if (isDecimal)
                            {
                                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();

                                    if (targetVar != null)
                                    {
                                        this.Write(targetVar);
                                    }
                                    else
                                    {
                                        indexerExpression.Target.AcceptVisitor(this.Emitter);
                                    }

                                    this.WriteDot();

                                    this.Write(Helpers.GetPropertyRef(member, this.Emitter, false));
                                    this.WriteOpenParentheses();
                                    this.Write(paramsStr);
                                    this.WriteCloseParentheses();

                                    this.WriteCloseParentheses();
                                }
                                else
                                {
                                    if (targetVar != null)
                                    {
                                        this.Write(targetVar);
                                    }
                                    else
                                    {
                                        indexerExpression.Target.AcceptVisitor(this.Emitter);
                                    }

                                    this.WriteDot();

                                    this.Write(Helpers.GetPropertyRef(member, this.Emitter, false));
                                    this.WriteOpenParentheses();
                                    this.Write(paramsStr);
                                    this.WriteCloseParentheses();
                                    this.WriteDot();
                                    if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement)
                                    {
                                        this.Write("inc");
                                    }
                                    else
                                    {
                                        this.Write("dec");
                                    }
                                    this.WriteOpenCloseParentheses();
                                }
                            }
                            else
                            {
                                if (targetVar != null)
                                {
                                    this.Write(targetVar);
                                }
                                else
                                {
                                    indexerExpression.Target.AcceptVisitor(this.Emitter);
                                }

                                this.WriteDot();

                                this.Write(Helpers.GetPropertyRef(member, this.Emitter, false));
                                this.WriteOpenParentheses();
                                this.Write(paramsStr);
                                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(member, this.Emitter, false));
                            this.WriteOpenParentheses();
                            this.Write(paramsStr);
                            this.WriteCloseParentheses();
                            this.WriteComma();

                            if (targetVar != null)
                            {
                                this.Write(targetVar);
                            }
                            else
                            {
                                indexerExpression.Target.AcceptVisitor(this.Emitter);
                            }
                            this.WriteDot();
                            this.Write(Helpers.GetPropertyRef(member, this.Emitter, true));
                            this.WriteOpenParentheses();
                            this.Write(paramsStr);
                            this.WriteComma(false);

                            if (isDecimal)
                            {
                                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.WriteOpenCloseParentheses();
                                }
                            }
                            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();

                            bool isPreOp = this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                           this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement;

                            if (isPreOp)
                            {
                                if (targetVar != null)
                                {
                                    this.Write(targetVar);
                                }
                                else
                                {
                                    indexerExpression.Target.AcceptVisitor(this.Emitter);
                                }
                                this.WriteDot();
                                this.Write(Helpers.GetPropertyRef(member, this.Emitter, false));
                                this.WriteOpenParentheses();
                                this.Write(paramsStr);
                                this.WriteCloseParentheses();
                            }
                            else
                            {
                                this.Write(valueVar);
                            }

                            this.WriteCloseParentheses();

                            if (valueVar != null)
                            {
                                this.RemoveTempVar(valueVar);
                            }
                        }

                        if (targetVar != null)
                        {
                            this.RemoveTempVar(targetVar);
                        }
                    }
                    else
                    {
                        this.Write(name);
                        this.WriteOpenParentheses();
                        new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                        this.WriteCloseParentheses();
                    }
                }
                else
                {
                    if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
                    {
                        var oldWriter = this.SaveWriter();
                        this.NewWriter();
                        new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                        var paramsStr = this.Emitter.Output.ToString();
                        this.RestoreWriter(oldWriter);

                        if (targetVar != null)
                        {
                            this.PushWriter(string.Concat(
                                                name,
                                                "(",
                                                paramsStr,
                                                ", ",
                                                targetVar,
                                                ".",
                                                Helpers.GetPropertyRef(member, this.Emitter, false),
                                                "(",
                                                paramsStr,
                                                "){0})"));

                            this.RemoveTempVar(targetVar);
                        }
                        else
                        {
                            oldWriter = this.SaveWriter();
                            this.NewWriter();

                            this.Emitter.IsAssignment    = false;
                            this.Emitter.IsUnaryAccessor = false;
                            indexerExpression.Target.AcceptVisitor(this.Emitter);
                            this.Emitter.IsAssignment    = oldIsAssignment;
                            this.Emitter.IsUnaryAccessor = oldUnary;

                            var trg = this.Emitter.Output.ToString();

                            this.RestoreWriter(oldWriter);
                            this.PushWriter(string.Concat(
                                                name,
                                                "(",
                                                paramsStr,
                                                ", ",
                                                trg,
                                                ".",
                                                Helpers.GetPropertyRef(member, this.Emitter, false),
                                                "(",
                                                paramsStr,
                                                "){0})"));
                        }
                    }
                    else
                    {
                        this.Write(name);
                        this.WriteOpenParentheses();
                        this.Emitter.IsAssignment    = false;
                        this.Emitter.IsUnaryAccessor = false;
                        new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit();
                        this.Emitter.IsAssignment    = oldIsAssignment;
                        this.Emitter.IsUnaryAccessor = oldUnary;
                        this.PushWriter(", {0})");
                    }
                }
            }
            else
            {
                if (indexerExpression.Arguments.Count != 1)
                {
                    throw new EmitterException(indexerExpression, "Only one index is supported");
                }

                var index = indexerExpression.Arguments.First();

                var primitive = index as PrimitiveExpression;

                if (primitive != null && primitive.Value != null && Regex.Match(primitive.Value.ToString(), "^[_$a-z][_$a-z0-9]*$", RegexOptions.IgnoreCase).Success)
                {
                    this.WriteDot();
                    this.Write(primitive.Value);
                }
                else
                {
                    this.Emitter.IsAssignment    = false;
                    this.Emitter.IsUnaryAccessor = false;
                    this.WriteOpenBracket();
                    index.AcceptVisitor(this.Emitter);
                    this.WriteCloseBracket();
                    this.Emitter.IsAssignment    = oldIsAssignment;
                    this.Emitter.IsUnaryAccessor = oldUnary;
                }
            }
        }
示例#12
0
        protected virtual bool WriteObject(string objectName, List <TypeConfigItem> members, string format, string interfaceFormat)
        {
            bool        hasProperties = this.HasProperties(objectName, members);
            int         pos           = 0;
            IWriterInfo writer        = null;
            bool        beginBlock    = false;

            if (hasProperties && objectName != null && !this.IsObjectLiteral)
            {
                beginBlock = true;
                pos        = this.Emitter.Output.Length;
                writer     = this.SaveWriter();
                this.EnsureComma();
                this.Write(objectName);

                this.WriteColon();
                this.BeginBlock();
            }

            bool isProperty = JS.Fields.PROPERTIES == objectName;
            bool isField    = JS.Fields.FIELDS == objectName;
            int  count      = 0;

            foreach (var member in members)
            {
                object constValue    = null;
                bool   isPrimitive   = false;
                var    primitiveExpr = member.Initializer as PrimitiveExpression;
                bool   write         = false;
                bool   writeScript   = false;

                if (primitiveExpr != null)
                {
                    //isPrimitive = true;
                    constValue = primitiveExpr.Value;

                    ResolveResult rr = null;
                    if (member.VarInitializer != null)
                    {
                        rr = this.Emitter.Resolver.ResolveNode(member.VarInitializer, this.Emitter);
                    }
                    else
                    {
                        rr = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter);
                    }

                    if (rr != null && rr.Type.Kind == TypeKind.Enum)
                    {
                        constValue  = Helpers.GetEnumValue(this.Emitter, rr.Type, constValue);
                        writeScript = true;
                    }
                }

                if (constValue is RawValue)
                {
                    constValue  = constValue.ToString();
                    write       = true;
                    writeScript = false;
                }

                var isNull = member.Initializer.IsNull || member.Initializer is NullReferenceExpression || member.Initializer.Parent == null;

                if (!isNull && !isPrimitive)
                {
                    var constrr = this.Emitter.Resolver.ResolveNode(member.Initializer, this.Emitter);
                    if (constrr != null && constrr.IsCompileTimeConstant)
                    {
                        //isPrimitive = true;
                        constValue = constrr.ConstantValue;

                        var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(member.Initializer);
                        if (!expectedType.Equals(constrr.Type) && expectedType.Kind != TypeKind.Dynamic)
                        {
                            try
                            {
                                constValue = Convert.ChangeType(constValue, ReflectionHelper.GetTypeCode(expectedType));
                            }
                            catch (Exception)
                            {
                                this.Emitter.Log.Warn($"FieldBlock: Convert.ChangeType is failed. Value type: {constrr.Type.FullName}, Target type: {expectedType.FullName}");
                            }
                        }

                        if (constrr.Type.Kind == TypeKind.Enum)
                        {
                            constValue = Helpers.GetEnumValue(this.Emitter, constrr.Type, constrr.ConstantValue);
                        }

                        writeScript = true;
                    }
                }

                var isNullable = false;

                if (isPrimitive && constValue is AstType)
                {
                    var itype = this.Emitter.Resolver.ResolveNode((AstType)constValue, this.Emitter);

                    if (NullableType.IsNullable(itype.Type))
                    {
                        isNullable = true;
                    }
                }

                string              tpl            = null;
                IMember             templateMember = null;
                MemberResolveResult init_rr        = null;
                if (isField && member.VarInitializer != null)
                {
                    init_rr = this.Emitter.Resolver.ResolveNode(member.VarInitializer, this.Emitter) as MemberResolveResult;
                    tpl     = init_rr != null?this.Emitter.GetInline(init_rr.Member) : null;

                    if (tpl != null)
                    {
                        templateMember = init_rr.Member;
                    }
                }

                bool isAutoProperty = false;

                if (isProperty)
                {
                    var member_rr = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter) as MemberResolveResult;
                    var property  = (IProperty)member_rr.Member;
                    isAutoProperty = Helpers.IsAutoProperty(property);
                }

                bool written = false;
                if (!isNull && (!isPrimitive || constValue is AstType || tpl != null) && !(isProperty && !IsObjectLiteral && !isAutoProperty))
                {
                    string value        = null;
                    bool   needContinue = false;
                    string defValue     = "";
                    if (!isPrimitive)
                    {
                        var oldWriter = this.SaveWriter();
                        this.NewWriter();
                        member.Initializer.AcceptVisitor(this.Emitter);
                        value = this.Emitter.Output.ToString();
                        this.RestoreWriter(oldWriter);

                        ResolveResult rr      = null;
                        AstType       astType = null;
                        if (member.VarInitializer != null)
                        {
                            rr = this.Emitter.Resolver.ResolveNode(member.VarInitializer, this.Emitter);
                        }
                        else
                        {
                            astType = member.Entity.ReturnType;
                            rr      = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter);
                        }

                        constValue = Inspector.GetDefaultFieldValue(rr.Type, astType);
                        if (rr.Type.Kind == TypeKind.Enum)
                        {
                            constValue = Helpers.GetEnumValue(this.Emitter, rr.Type, constValue);
                        }
                        isNullable   = NullableType.IsNullable(rr.Type);
                        needContinue = constValue is IType;
                        writeScript  = true;

                        /*if (needContinue && !(member.Initializer is ObjectCreateExpression))
                         * {
                         *  defValue = " || " + Inspector.GetStructDefaultValue((IType)constValue, this.Emitter);
                         * }*/
                    }
                    else if (constValue is AstType)
                    {
                        value = isNullable
                            ? "null"
                            : Inspector.GetStructDefaultValue((AstType)constValue, this.Emitter);
                        constValue   = value;
                        write        = true;
                        needContinue = !isProperty && !isNullable;
                    }

                    var name = member.GetName(this.Emitter);

                    bool isValidIdentifier = Helpers.IsValidIdentifier(name);

                    if (isProperty && isPrimitive)
                    {
                        constValue = "null";

                        if (this.IsObjectLiteral)
                        {
                            written = true;
                            if (isValidIdentifier)
                            {
                                this.Write(string.Format("this.{0} = {1};", name, value));
                            }
                            else
                            {
                                this.Write(string.Format("this[{0}] = {1};", AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value));
                            }

                            this.WriteNewLine();
                        }
                        else
                        {
                            this.Injectors.Add(string.Format(name.StartsWith("\"") || !isValidIdentifier ? "this[{0}] = {1};" : "this.{0} = {1};", isValidIdentifier ? name : AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value));
                        }
                    }
                    else
                    {
                        if (this.IsObjectLiteral)
                        {
                            written = true;
                            if (isValidIdentifier)
                            {
                                this.Write(string.Format("this.{0} = {1};", name, value + defValue));
                            }
                            else
                            {
                                this.Write(string.Format("this[{0}] = {1};", AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value + defValue));
                            }
                            this.WriteNewLine();
                        }
                        else if (tpl != null)
                        {
                            if (!tpl.Contains("{0}"))
                            {
                                tpl = tpl + " = {0};";
                            }

                            string v = null;
                            if (!isNull && (!isPrimitive || constValue is AstType))
                            {
                                v = value + defValue;
                            }
                            else
                            {
                                if (write)
                                {
                                    v = constValue != null?constValue.ToString() : "";
                                }
                                else if (writeScript)
                                {
                                    v = AbstractEmitterBlock.ToJavaScript(constValue, this.Emitter);
                                }
                                else
                                {
                                    var oldWriter = this.SaveWriter();
                                    this.NewWriter();
                                    member.Initializer.AcceptVisitor(this.Emitter);
                                    v = this.Emitter.Output.ToString();
                                    this.RestoreWriter(oldWriter);
                                }
                            }

                            tpl = Helpers.ConvertTokens(this.Emitter, tpl, templateMember);
                            tpl = tpl.Replace("{this}", "this").Replace("{0}", v);

                            if (!tpl.EndsWith(";"))
                            {
                                tpl += ";";
                            }
                            this.Injectors.Add(tpl);
                        }
                        else
                        {
                            var  rr = this.Emitter.Resolver.ResolveNode(member.Initializer, this.Emitter) as CSharpInvocationResolveResult;
                            bool isDefaultInstance = rr != null &&
                                                     rr.Member.SymbolKind == SymbolKind.Constructor &&
                                                     rr.Arguments.Count == 0 &&
                                                     rr.InitializerStatements.Count == 0 &&
                                                     rr.Type.Kind == TypeKind.Struct;

                            if (!isDefaultInstance)
                            {
                                if (isField && !isValidIdentifier)
                                {
                                    this.Injectors.Add(string.Format("this[{0}] = {1};", name.StartsWith("\"") ? name : AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value + defValue));
                                }
                                else
                                {
                                    this.Injectors.Add(string.Format(name.StartsWith("\"") ? interfaceFormat : format, name, value + defValue));
                                }
                            }
                        }
                    }
                }

                count++;

                if (written)
                {
                    continue;
                }
                bool withoutTypeParams   = true;
                MemberResolveResult m_rr = null;
                if (member.Entity != null)
                {
                    m_rr = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter) as MemberResolveResult;
                    if (m_rr != null)
                    {
                        withoutTypeParams = OverloadsCollection.ExcludeTypeParameterForDefinition(m_rr);
                    }
                }

                var mname = member.GetName(this.Emitter, withoutTypeParams);

                if (this.TypeInfo.IsEnum && m_rr != null)
                {
                    mname = this.Emitter.GetEntityName(m_rr.Member);
                }

                bool isValid = Helpers.IsValidIdentifier(mname);
                if (!isValid)
                {
                    if (this.IsObjectLiteral)
                    {
                        mname = "[" + AbstractEmitterBlock.ToJavaScript(mname, this.Emitter) + "]";
                    }
                    else
                    {
                        mname = AbstractEmitterBlock.ToJavaScript(mname, this.Emitter);
                    }
                }

                if (this.IsObjectLiteral)
                {
                    this.WriteThis();
                    if (isValid)
                    {
                        this.WriteDot();
                    }
                    this.Write(mname);
                    this.Write(" = ");
                }
                else
                {
                    this.EnsureComma();
                    XmlToJsDoc.EmitComment(this, member.Entity, null, member.Entity is FieldDeclaration ? member.VarInitializer : null);
                    this.Write(mname);
                    this.WriteColon();
                }

                bool close = false;
                if (isProperty && !IsObjectLiteral && !isAutoProperty)
                {
                    var oldTempVars = this.Emitter.TempVariables;
                    this.BeginBlock();
                    new VisitorPropertyBlock(this.Emitter, (PropertyDeclaration)member.Entity).Emit();
                    this.WriteNewLine();
                    this.EndBlock();
                    this.Emitter.Comma         = true;
                    this.Emitter.TempVariables = oldTempVars;
                    continue;
                }

                if (constValue is AstType || constValue is IType)
                {
                    this.Write("null");

                    if (!isNullable)
                    {
                        var  name = member.GetName(this.Emitter);
                        bool isValidIdentifier = Helpers.IsValidIdentifier(name);
                        var  value             = constValue is AstType?Inspector.GetStructDefaultValue((AstType)constValue, this.Emitter) : Inspector.GetStructDefaultValue((IType)constValue, this.Emitter);

                        if (!isValidIdentifier)
                        {
                            this.Injectors.Insert(BeginCounter++, string.Format("this[{0}] = {1};", name.StartsWith("\"") ? name : AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value));
                        }
                        else
                        {
                            this.Injectors.Insert(BeginCounter++, string.Format(name.StartsWith("\"") ? interfaceFormat : format, name, value));
                        }
                    }
                }
                else if (write)
                {
                    this.Write(constValue);
                }
                else if (writeScript)
                {
                    this.WriteScript(constValue);
                }
                else
                {
                    member.Initializer.AcceptVisitor(this.Emitter);
                }

                if (close)
                {
                    this.Write(" }");
                }

                if (this.IsObjectLiteral)
                {
                    this.WriteSemiColon(true);
                }

                this.Emitter.Comma = true;
            }

            if (count > 0 && objectName != null && !IsObjectLiteral)
            {
                this.WriteNewLine();
                this.EndBlock();
            }
            else if (beginBlock)
            {
                this.Emitter.IsNewLine = writer.IsNewLine;
                this.Emitter.ResetLevel(writer.Level);
                this.Emitter.Comma = writer.Comma;

                this.Emitter.Output.Length = pos;
            }

            return(count > 0);
        }
示例#13
0
        protected void VisitUnaryOperatorExpression()
        {
            var  unaryOperatorExpression = this.UnaryOperatorExpression;
            var  oldType              = this.Emitter.UnaryOperatorType;
            var  oldAccessor          = this.Emitter.IsUnaryAccessor;
            var  resolveOperator      = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression, this.Emitter);
            var  expectedType         = this.Emitter.Resolver.Resolver.GetExpectedType(unaryOperatorExpression);
            bool isDecimalExpected    = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver);
            bool isDecimal            = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver);
            bool isLongExpected       = Helpers.Is64Type(expectedType, this.Emitter.Resolver);
            bool isLong               = Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver);
            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
            int count = this.Emitter.Writers.Count;

            if (resolveOperator is ConstantResolveResult)
            {
                this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue);
                return;
            }

            if (Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver))
            {
                isDecimal         = true;
                isDecimalExpected = true;
            }

            if (isDecimal && isDecimalExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await)
            {
                this.HandleDecimal(resolveOperator);
                return;
            }

            if (this.ResolveOperator(unaryOperatorExpression, orr))
            {
                return;
            }

            if (Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver))
            {
                isLong         = true;
                isLongExpected = true;
            }

            if (isLong && isLongExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await)
            {
                this.HandleDecimal(resolveOperator, true);
                return;
            }

            if (this.ResolveOperator(unaryOperatorExpression, orr))
            {
                return;
            }

            var  op = unaryOperatorExpression.Operator;
            var  argResolverResult = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression.Expression, this.Emitter);
            bool nullable          = NullableType.IsNullable(argResolverResult.Type);

            if (nullable)
            {
                if (op != UnaryOperatorType.Increment &&
                    op != UnaryOperatorType.Decrement &&
                    op != UnaryOperatorType.PostIncrement &&
                    op != UnaryOperatorType.PostDecrement)
                {
                    this.Write(JS.Types.SYSTEM_NULLABLE + ".");
                }
            }

            bool isAccessor = false;
            var  memberArgResolverResult = argResolverResult as MemberResolveResult;

            if (memberArgResolverResult != null && memberArgResolverResult.Member is IProperty)
            {
                var prop       = (IProperty)memberArgResolverResult.Member;
                var isIgnore   = this.Emitter.Validator.IsIgnoreType(memberArgResolverResult.Member.DeclaringTypeDefinition);
                var inlineAttr = prop.Getter != null?this.Emitter.GetAttribute(prop.Getter.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute") : null;

                var ignoreAccessor     = prop.Getter != null && this.Emitter.Validator.IsIgnoreType(prop.Getter);
                var isAccessorsIndexer = this.Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member);

                isAccessor = true;

                if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer)
                {
                    isAccessor = false;
                }
            }
            else if (argResolverResult is ArrayAccessResolveResult)
            {
                isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1;
            }

            this.Emitter.UnaryOperatorType = op;

            if ((isAccessor) &&
                (op == UnaryOperatorType.Increment ||
                 op == UnaryOperatorType.Decrement ||
                 op == UnaryOperatorType.PostIncrement ||
                 op == UnaryOperatorType.PostDecrement))
            {
                this.Emitter.IsUnaryAccessor = true;

                if (nullable)
                {
                    this.Write(JS.Funcs.BRIDGE_HASVALUE);
                    this.WriteOpenParentheses();
                    this.Emitter.IsUnaryAccessor = false;
                    unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(") ? ");
                    this.Emitter.IsUnaryAccessor = true;
                    unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(" : null)");
                }
                else
                {
                    unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                }

                this.Emitter.IsUnaryAccessor = oldAccessor;

                if (this.Emitter.Writers.Count > count)
                {
                    this.PopWriter();
                }
            }
            else
            {
                switch (op)
                {
                case UnaryOperatorType.BitNot:
                    if (nullable)
                    {
                        this.Write("bnot(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        this.Write("~");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Decrement:
                    if (nullable)
                    {
                        this.Write(JS.Funcs.BRIDGE_HASVALUE);
                        this.WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        this.Write("--");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(" : null)");
                    }
                    else
                    {
                        this.Write("--");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Increment:
                    if (nullable)
                    {
                        this.Write(JS.Funcs.BRIDGE_HASVALUE);
                        this.WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        this.Write("++");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(" : null)");
                    }
                    else
                    {
                        this.Write("++");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Minus:
                    if (nullable)
                    {
                        this.Write("neg(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        this.Write("-");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Not:
                    if (nullable)
                    {
                        this.Write("not(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        this.Write("!");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Plus:
                    if (nullable)
                    {
                        this.Write("pos(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }

                    break;

                case UnaryOperatorType.PostDecrement:
                    if (nullable)
                    {
                        this.Write(JS.Funcs.BRIDGE_HASVALUE);
                        this.WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("--");
                        this.Write(" : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("--");
                    }
                    break;

                case UnaryOperatorType.PostIncrement:
                    if (nullable)
                    {
                        this.Write(JS.Funcs.BRIDGE_HASVALUE);
                        this.WriteOpenParentheses();
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("++");
                        this.Write(" : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("++");
                    }
                    break;

                case UnaryOperatorType.Await:
                    if (this.Emitter.ReplaceAwaiterByVar)
                    {
                        var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, unaryOperatorExpression.Expression) + 1;
                        this.Write(JS.Vars.ASYNC_TASK_RESULT + index);
                    }
                    else
                    {
                        var oldValue = this.Emitter.ReplaceAwaiterByVar;
                        var oldAsyncExpressionHandling = this.Emitter.AsyncExpressionHandling;

                        if (this.Emitter.IsAsync && !this.Emitter.AsyncExpressionHandling)
                        {
                            this.WriteAwaiters(unaryOperatorExpression.Expression);
                            this.Emitter.ReplaceAwaiterByVar     = true;
                            this.Emitter.AsyncExpressionHandling = true;
                        }

                        this.WriteAwaiter(unaryOperatorExpression.Expression);

                        this.Emitter.ReplaceAwaiterByVar     = oldValue;
                        this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;
                    }
                    break;

                default:
                    throw new EmitterException(unaryOperatorExpression, "Unsupported unary operator: " + unaryOperatorExpression.Operator.ToString());
                }

                if (this.Emitter.Writers.Count > count)
                {
                    this.PopWriter();
                }
            }

            this.Emitter.UnaryOperatorType = oldType;
        }
示例#14
0
        private void HandleDecimal(ResolveResult resolveOperator, bool isLong = false)
        {
            var orr         = resolveOperator as OperatorResolveResult;
            var op          = this.UnaryOperatorExpression.Operator;
            var oldType     = this.Emitter.UnaryOperatorType;
            var oldAccessor = this.Emitter.IsUnaryAccessor;
            var typeCode    = isLong ? KnownTypeCode.Int64 : KnownTypeCode.Decimal;

            this.Emitter.UnaryOperatorType = op;

            var  argResolverResult       = this.Emitter.Resolver.ResolveNode(this.UnaryOperatorExpression.Expression, this.Emitter);
            bool nullable                = NullableType.IsNullable(argResolverResult.Type);
            bool isAccessor              = false;
            var  memberArgResolverResult = argResolverResult as MemberResolveResult;

            if (memberArgResolverResult != null && memberArgResolverResult.Member is IProperty)
            {
                var isIgnore           = this.Emitter.Validator.IsIgnoreType(memberArgResolverResult.Member.DeclaringTypeDefinition);
                var inlineAttr         = this.Emitter.GetAttribute(memberArgResolverResult.Member.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute");
                var ignoreAccessor     = this.Emitter.Validator.IsIgnoreType(((IProperty)memberArgResolverResult.Member).Getter);
                var isAccessorsIndexer = this.Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member);

                isAccessor = true;

                if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer)
                {
                    isAccessor = false;
                }
            }
            else if (argResolverResult is ArrayAccessResolveResult)
            {
                isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1;
            }

            var isOneOp = op == UnaryOperatorType.Increment ||
                          op == UnaryOperatorType.Decrement ||
                          op == UnaryOperatorType.PostIncrement ||
                          op == UnaryOperatorType.PostDecrement;

            if (isAccessor && isOneOp)
            {
                this.Emitter.IsUnaryAccessor = true;

                if (nullable)
                {
                    this.Write(JS.Funcs.BRIDGE_HASVALUE);
                    this.WriteOpenParentheses();
                    this.Emitter.IsUnaryAccessor = false;
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(") ? ");
                    this.Emitter.IsUnaryAccessor = true;
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(" : null)");
                }
                else
                {
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                }

                this.Emitter.UnaryOperatorType = oldType;
                this.Emitter.IsUnaryAccessor   = oldAccessor;

                return;
            }

            var method = orr != null ? orr.UserDefinedOperatorMethod : null;

            if (orr != null && method == null)
            {
                var name = Helpers.GetUnaryOperatorMethodName(this.UnaryOperatorExpression.Operator);
                var type = NullableType.IsNullable(orr.Type) ? NullableType.GetUnderlyingType(orr.Type) : orr.Type;
                method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
            }

            if (orr.IsLiftedOperator)
            {
                if (!isOneOp)
                {
                    this.Write(JS.Types.SYSTEM_NULLABLE + ".");
                }

                string action  = JS.Funcs.Math.LIFT1;
                string op_name = null;

                switch (this.UnaryOperatorExpression.Operator)
                {
                case UnaryOperatorType.Minus:
                    op_name = JS.Funcs.Math.NEG;
                    break;

                case UnaryOperatorType.Plus:
                    op_name = "clone";
                    break;

                case UnaryOperatorType.BitNot:
                    op_name = "not";
                    break;

                case UnaryOperatorType.Increment:
                case UnaryOperatorType.Decrement:
                    this.Write(JS.Funcs.BRIDGE_HASVALUE);
                    this.WriteOpenParentheses();
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(") ? ");
                    this.WriteOpenParentheses();
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(" = " + JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "('" + (op == UnaryOperatorType.Decrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "', ");
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, true);
                    this.Write(")");
                    this.WriteCloseParentheses();

                    this.Write(" : null");
                    break;

                case UnaryOperatorType.PostIncrement:
                case UnaryOperatorType.PostDecrement:
                    this.Write(JS.Funcs.BRIDGE_HASVALUE);
                    this.WriteOpenParentheses();
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(") ? ");
                    this.WriteOpenParentheses();
                    var valueVar = this.GetTempVarName();

                    this.Write(valueVar);
                    this.Write(" = ");

                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.WriteComma();
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(" = " + JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "('" + (op == UnaryOperatorType.PostDecrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "', ");
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, true);
                    this.Write(")");
                    this.WriteComma();
                    this.Write(valueVar);
                    this.WriteCloseParentheses();
                    this.RemoveTempVar(valueVar);

                    this.Write(" : null");
                    break;
                }

                if (!isOneOp)
                {
                    this.Write(action);
                    this.WriteOpenParentheses();
                    this.WriteScript(op_name);
                    this.WriteComma();
                    new ExpressionListBlock(this.Emitter,
                                            new Expression[] { this.UnaryOperatorExpression.Expression }, null, null, 0).Emit();
                    this.AddOveflowFlag(typeCode, op_name, true);
                    this.WriteCloseParentheses();
                }
            }
            else if (method == null)
            {
                string op_name     = null;
                var    isStatement = this.UnaryOperatorExpression.Parent is ExpressionStatement;

                if (isStatement)
                {
                    if (op == UnaryOperatorType.PostIncrement)
                    {
                        op = UnaryOperatorType.Increment;
                    }
                    else if (op == UnaryOperatorType.PostDecrement)
                    {
                        op = UnaryOperatorType.Decrement;
                    }
                }

                switch (op)
                {
                case UnaryOperatorType.Minus:
                    op_name = JS.Funcs.Math.NEG;
                    break;

                case UnaryOperatorType.Plus:
                    op_name = "clone";
                    break;

                case UnaryOperatorType.BitNot:
                    op_name = "not";
                    break;

                case UnaryOperatorType.Increment:
                case UnaryOperatorType.Decrement:
                    if (!isStatement)
                    {
                        this.WriteOpenParentheses();
                    }

                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(" = ");
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write("." + (op == UnaryOperatorType.Decrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "(");
                    this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, false);
                    this.Write(")");

                    if (!isStatement)
                    {
                        this.WriteCloseParentheses();
                    }
                    break;

                case UnaryOperatorType.PostIncrement:
                case UnaryOperatorType.PostDecrement:
                    this.WriteOpenParentheses();
                    var valueVar = this.GetTempVarName();

                    this.Write(valueVar);
                    this.Write(" = ");

                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.WriteComma();
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(" = ");
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write("." + (op == UnaryOperatorType.PostDecrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "(");
                    this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, false);
                    this.Write("), ");
                    this.Write(valueVar);
                    this.WriteCloseParentheses();
                    this.RemoveTempVar(valueVar);
                    break;
                }

                if (!isOneOp)
                {
                    this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.WriteDot();
                    this.Write(op_name);
                    this.WriteOpenParentheses();
                    this.AddOveflowFlag(typeCode, op_name, false);
                    this.WriteCloseParentheses();
                }
            }
            else
            {
                var inline = this.Emitter.GetInline(method);

                if (!string.IsNullOrWhiteSpace(inline))
                {
                    if (isOneOp)
                    {
                        var isStatement = this.UnaryOperatorExpression.Parent is ExpressionStatement;

                        if (isStatement || this.UnaryOperatorExpression.Operator == UnaryOperatorType.Increment ||
                            this.UnaryOperatorExpression.Operator == UnaryOperatorType.Decrement)
                        {
                            if (!isStatement)
                            {
                                this.WriteOpenParentheses();
                            }

                            this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                            this.Write(" = ");
                            new InlineArgumentsBlock(this.Emitter,
                                                     new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit
                                ();
                            if (!isStatement)
                            {
                                this.WriteCloseParentheses();
                            }
                        }
                        else
                        {
                            this.WriteOpenParentheses();
                            var valueVar = this.GetTempVarName();

                            this.Write(valueVar);
                            this.Write(" = ");

                            this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                            this.WriteComma();
                            this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                            this.Write(" = ");
                            new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit();
                            this.WriteComma();
                            this.Write(valueVar);
                            this.WriteCloseParentheses();
                            this.RemoveTempVar(valueVar);
                        }
                    }
                    else
                    {
                        new InlineArgumentsBlock(this.Emitter,
                                                 new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit();
                    }
                }
                else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition))
                {
                    this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter));
                    this.WriteDot();

                    this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName());

                    this.WriteOpenParentheses();

                    new ExpressionListBlock(this.Emitter,
                                            new Expression[] { this.UnaryOperatorExpression.Expression }, null, null, 0).Emit();
                    this.WriteCloseParentheses();
                }
            }

            this.Emitter.UnaryOperatorType = oldType;
        }
        protected void VisitMemberReferenceExpression()
        {
            MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression;
            int pos = this.Emitter.Output.Length;

            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)
            {
                if (memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField)
                {
                    isConstTarget = true;
                }
                else if (memberTargetrr.IsCompileTimeConstantToString())
                {
                    isConstTarget = true;
                }
            }

            if (memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression))
            {
                resolveResult           = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter);
                expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter);

                if (expressionResolveResult is InvocationResolveResult)
                {
                    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;
            }

            if (resolveResult is DynamicInvocationResolveResult)
            {
                resolveResult = ((DynamicInvocationResolveResult)resolveResult).Target;
            }

            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;
            Tuple <bool, bool, string> inlineInfo = member != null?this.Emitter.GetInlineCode(memberReferenceExpression) : null;

            //string inline = member != null ? this.Emitter.GetInline(member.Member) : null;
            string inline    = inlineInfo != null ? inlineInfo.Item3 : null;
            bool   hasInline = !string.IsNullOrEmpty(inline);
            bool   hasThis   = hasInline && inline.Contains("{this}");

            if (hasThis)
            {
                this.Write("");
                var oldBuilder = this.Emitter.Output;
                this.Emitter.Output          = new StringBuilder();
                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;
                inline = inline.Replace("{this}", this.Emitter.Output.ToString());
                this.Emitter.Output = oldBuilder;

                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inline);
                }
                else
                {
                    if (member != null && member.Member is IMethod)
                    {
                        throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference");
                    }
                    else
                    {
                        this.Write(inline);
                    }
                }

                return;
            }

            if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && !hasInline)
            {
                this.WriteScript(member.ConstantValue);
            }
            else if (hasInline && member.Member.IsStatic)
            {
                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inline);
                }
                else
                {
                    if (member != null && member.Member is IMethod)
                    {
                        var r     = new Regex(@"([$\w\.]+)\(\s*\S.*\)");
                        var match = r.Match(inline);

                        if (match.Success)
                        {
                            this.Write(match.Groups[1].Value);
                        }
                        else
                        {
                            throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference");
                        }
                    }
                    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 DefaultResolvedTypeDefinition;

                    if (typeDef != null)
                    {
                        var enumMode = this.Emitter.Validator.EnumEmitMode(typeDef);

                        if ((this.Emitter.Validator.IsIgnoreType(typeDef) && enumMode == -1) || enumMode == 2)
                        {
                            this.WriteScript(member.ConstantValue);

                            return;
                        }

                        if (enumMode >= 3)
                        {
                            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:
                                    break;

                                case 5:
                                    enumStringName = enumStringName.ToLowerInvariant();
                                    break;

                                case 6:
                                    enumStringName = enumStringName.ToUpperInvariant();
                                    break;
                                }
                            }

                            this.WriteScript(enumStringName);

                            return;
                        }
                    }
                }

                bool isInvokeInCurClass = false;
                if (resolveResult is TypeResolveResult)
                {
                    TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult;
                    this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter));

                    /*
                     * var isNative = this.Emitter.Validator.IsIgnoreType(typeResolveResult.Type.GetDefinition());
                     * if(isNative) {
                     *  this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter));
                     * }
                     * else {
                     *  this.Write("Bridge.get(" + 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 == "("
                             )
                         )
                {
                    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(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "(");
                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                        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("(");
                        }
                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                        if (isConstTarget)
                        {
                            this.Write(")");
                        }
                        this.Emitter.IsAssignment    = oldIsAssignment;
                        this.Emitter.IsUnaryAccessor = oldUnary;
                    }

                    this.WriteDot();

                    this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName());

                    if (!isStatic)
                    {
                        this.Write(")");
                    }

                    return;
                }
                else
                {
                    bool isProperty = false;

                    if (member != null && member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !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.WriteVar();
                                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("(");
                    }
                    isInvokeInCurClass = resolveResult is InvocationResolveResult && member.Member.IsInternalMember();
                    if (!isInvokeInCurClass)
                    {
                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                    }
                    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);
                        }
                    }
                }

                if (member != null && member.Member != null)
                {
                    if (!isInvokeInCurClass)
                    {
                        if (!member.Member.IsStatic && ((member.Member.SymbolKind == SymbolKind.Method && !this.Emitter.Validator.IsDelegateOrLambda(expressionResolveResult)) || (member.Member.SymbolKind == SymbolKind.Property && !Helpers.IsFieldProperty(member.Member, this.Emitter))))
                        {
                            this.WriteObjectColon();
                        }
                        else
                        {
                            this.WriteDot();
                        }
                    }
                }
                else
                {
                    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.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment))
                    {
                        this.PushWriter(inline);
                    }
                    else
                    {
                        this.Write(inline);
                    }
                }
                else if (member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition))
                {
                    var proto = false;
                    if (this.MemberReferenceExpression.Target is BaseReferenceExpression && member != null)
                    {
                        var prop = member.Member as IProperty;

                        if (prop != null && (prop.IsVirtual || prop.IsOverride))
                        {
                            proto = true;
                        }
                    }

                    if (Helpers.IsFieldProperty(member.Member, this.Emitter))
                    {
                        this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter));
                    }
                    else if (!this.Emitter.IsAssignment)
                    {
                        if (this.Emitter.IsUnaryAccessor)
                        {
                            bool isNullable = NullableType.IsNullable(member.Member.ReturnType);
                            bool isDecimal  = Helpers.IsDecimalType(member.Member.ReturnType, this.Emitter.Resolver);

                            if (isStatement)
                            {
                                this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true));
                                if (proto)
                                {
                                    this.Write(".call");
                                    this.WriteOpenParentheses();
                                    this.WriteThis();
                                    this.WriteComma();
                                }
                                else
                                {
                                    this.WriteOpenParentheses();
                                }

                                if (isDecimal)
                                {
                                    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();

                                        if (targetVar != null)
                                        {
                                            this.Write(targetVar);
                                        }
                                        else
                                        {
                                            memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                        }

                                        this.WriteDot();

                                        this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));

                                        if (proto)
                                        {
                                            this.Write(".call");
                                            this.WriteOpenParentheses();
                                            this.WriteThis();
                                            this.WriteCloseParentheses();
                                        }
                                        else
                                        {
                                            this.WriteOpenParentheses();
                                            this.WriteCloseParentheses();
                                        }

                                        this.WriteCloseParentheses();
                                    }
                                    else
                                    {
                                        if (targetVar != null)
                                        {
                                            this.Write(targetVar);
                                        }
                                        else
                                        {
                                            memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                        }

                                        this.WriteDot();

                                        this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));

                                        if (proto)
                                        {
                                            this.Write(".call");
                                            this.WriteOpenParentheses();
                                            this.WriteThis();
                                            this.WriteCloseParentheses();
                                        }
                                        else
                                        {
                                            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();

                                        this.WriteCloseParentheses();
                                    }
                                }
                                else
                                {
                                    if (targetVar != null)
                                    {
                                        this.Write(targetVar);
                                    }
                                    else
                                    {
                                        if (isConstTarget)
                                        {
                                            this.Write("(");
                                        }
                                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                        if (isConstTarget)
                                        {
                                            this.Write(")");
                                        }
                                    }

                                    this.WriteObjectColon();
                                    this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));

                                    if (proto)
                                    {
                                        this.Write(".call");
                                        this.WriteOpenParentheses();
                                        this.WriteThis();
                                        this.WriteCloseParentheses();
                                    }
                                    else
                                    {
                                        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(member.Member, this.Emitter, false));
                                if (proto)
                                {
                                    this.Write(".call");
                                    this.WriteOpenParentheses();
                                    this.WriteThis();
                                    this.WriteCloseParentheses();
                                }
                                else
                                {
                                    this.WriteOpenParentheses();
                                    this.WriteCloseParentheses();
                                }
                                this.WriteComma();

                                if (targetVar != null)
                                {
                                    this.Write(targetVar);
                                }
                                else
                                {
                                    if (isConstTarget)
                                    {
                                        this.Write("(");
                                    }
                                    memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                    if (isConstTarget)
                                    {
                                        this.Write(")");
                                    }
                                }

                                this.WriteDot();
                                this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true));

                                if (proto)
                                {
                                    this.Write(".call");
                                    this.WriteOpenParentheses();
                                    this.WriteThis();
                                    this.WriteComma();
                                }
                                else
                                {
                                    this.WriteOpenParentheses();
                                }

                                if (isDecimal)
                                {
                                    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();

                                bool isPreOp = this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                               this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement;

                                if (isPreOp)
                                {
                                    if (targetVar != null)
                                    {
                                        this.Write(targetVar);
                                    }
                                    else
                                    {
                                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                    }
                                    this.WriteDot();
                                    this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));
                                    this.WriteOpenParentheses();
                                    this.WriteCloseParentheses();
                                }
                                else
                                {
                                    this.Write(valueVar);
                                }
                                this.WriteCloseParentheses();

                                if (valueVar != null)
                                {
                                    this.RemoveTempVar(valueVar);
                                }
                            }

                            if (targetVar != null)
                            {
                                this.RemoveTempVar(targetVar);
                            }
                        }
                        else
                        {
                            this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter));
                            if (proto)
                            {
                                this.Write(".call");
                                this.WriteOpenParentheses();
                                this.WriteThis();
                                this.WriteCloseParentheses();
                            }
                            else
                            {
                                this.WriteOpenParentheses();
                                this.WriteCloseParentheses();
                            }
                        }
                    }
                    else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
                    {
                        if (targetVar != null)
                        {
                            this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true),
                                                          proto ? ".call(this, " : "(",
                                                          targetVar,
                                                          ".",
                                                          Helpers.GetPropertyRef(member.Member, this.Emitter, false),
                                                          proto ? ".call(this)" : "()",
                                                          "{0})"), () => {
                                this.RemoveTempVar(targetVar);
                            });
                        }
                        else
                        {
                            var oldWriter = this.SaveWriter();
                            this.NewWriter();

                            this.Emitter.IsAssignment    = false;
                            this.Emitter.IsUnaryAccessor = false;
                            memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                            this.Emitter.IsAssignment    = oldIsAssignment;
                            this.Emitter.IsUnaryAccessor = oldUnary;
                            var trg = this.Emitter.Output.ToString();

                            this.RestoreWriter(oldWriter);
                            this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + "({0})");

                            /*
                             * this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true),
                             * proto ? ".call(this, " : "(",
                             * trg,
                             * ".",
                             * Helpers.GetPropertyRef(member.Member, this.Emitter, false),
                             * proto ? ".call(this)" : "()",
                             * "{0})"));*/
                        }
                    }
                    else
                    {
                        if (proto)
                        {
                            this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + ".call(this, {0})");
                        }
                        else
                        {
                            this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + "({0})");
                        }
                    }
                }
                else if (member.Member.SymbolKind == SymbolKind.Field)
                {
                    bool isConst = this.Emitter.IsMemberConst(member.Member);
                    if (isConst)
                    {
                        this.WriteScript(member.ConstantValue);
                    }
                    else
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName());
                    }
                }
                else if (resolveResult is InvocationResolveResult)
                {
                    InvocationResolveResult       invocationResult  = (InvocationResolveResult)resolveResult;
                    CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult;
                    var expresssionMember = expressionResolveResult as MemberResolveResult;

                    if (expresssionMember != null &&
                        cInvocationResult != null &&
                        cInvocationResult.IsDelegateInvocation &&
                        invocationResult.Member != expresssionMember.Member)
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName());
                    }
                    else
                    {
                        string name = OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName();
                        if (isInvokeInCurClass && Emitter.LocalsNamesMap.ContainsKey(name))
                        {
                            string newName = this.GetUniqueName(name);
                            this.IntroduceTempVar(newName + " = " + name);
                            name = newName;
                        }
                        this.Write(name);
                    }
                }
                else if (member.Member is DefaultResolvedEvent)
                {
                    if (this.Emitter.IsAssignment &&
                        (this.Emitter.AssignmentType == AssignmentOperatorType.Add ||
                         this.Emitter.AssignmentType == AssignmentOperatorType.Subtract))
                    {
                        this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove");
                        this.Write(
                            OverloadsCollection.Create(this.Emitter, member.Member,
                                                       this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName());
                        this.WriteOpenParentheses();
                    }
                    else
                    {
                        this.Write(this.Emitter.GetEntityName(member.Member, true));
                    }
                }
                else
                {
                    this.Write(this.Emitter.GetEntityName(member.Member));
                }

                Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos);
            }
        }
示例#16
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);
            }
            // 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);
            }
        }
示例#17
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 if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode))
                    {
                        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 if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode))
                    {
                        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 == "("
                    )
                )
            {
                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_CACHE_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 (memberResult.Member is IProperty)
                {
                    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));
                }
            }
            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);
        }
示例#18
0
        protected void VisitMemberReferenceExpression()
        {
            MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression;

            ResolveResult resolveResult           = null;
            ResolveResult expressionResolveResult = null;
            string        targetVar   = null;
            string        valueVar    = null;
            bool          isStatement = false;

            var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter);

            if (memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression))
            {
                resolveResult           = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter);
                expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter);

                if (expressionResolveResult is InvocationResolveResult)
                {
                    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;
                memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                this.Emitter.IsAssignment    = oldIsAssignment;
                this.Emitter.IsUnaryAccessor = oldUnary;
                this.WriteDot();
                string name = memberReferenceExpression.MemberName;
                this.Write(name.ToLowerCamelCase());

                return;
            }

            if (resolveResult is DynamicInvocationResolveResult)
            {
                resolveResult = ((DynamicInvocationResolveResult)resolveResult).Target;
            }

            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 (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;
            }

            string inline = member != null?this.Emitter.GetInline(member.Member) : null;

            bool hasInline = !string.IsNullOrEmpty(inline);
            bool hasThis   = hasInline && inline.Contains("{this}");

            if (hasThis)
            {
                this.Write("");
                var oldBuilder = this.Emitter.Output;
                this.Emitter.Output          = new StringBuilder();
                this.Emitter.IsAssignment    = false;
                this.Emitter.IsUnaryAccessor = false;
                memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                this.Emitter.IsAssignment    = oldIsAssignment;
                this.Emitter.IsUnaryAccessor = oldUnary;
                inline = inline.Replace("{this}", this.Emitter.Output.ToString());
                this.Emitter.Output = oldBuilder;

                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inline);
                }
                else
                {
                    this.Write(inline);
                }

                return;
            }

            if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && this.Emitter.IsInlineConst(member.Member))
            {
                this.WriteScript(member.ConstantValue);
            }
            else if (hasInline && member.Member.IsStatic)
            {
                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inline);
                }
                else
                {
                    //this.Write(inline);
                    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 DefaultResolvedTypeDefinition;

                    if (typeDef != null)
                    {
                        var enumMode = this.Emitter.Validator.EnumEmitMode(typeDef);

                        if ((this.Emitter.Validator.IsIgnoreType(typeDef) && enumMode == -1) || enumMode == 2)
                        {
                            this.WriteScript(member.ConstantValue);

                            return;
                        }

                        if (enumMode >= 3)
                        {
                            string enumStringName = member.Member.Name;
                            var    attr           = this.Emitter.GetAttribute(member.Member.Attributes, 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:
                                    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 == "("
                             )
                         )
                {
                    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(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "(");
                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                        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;
                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                        this.Emitter.IsAssignment    = oldIsAssignment;
                        this.Emitter.IsUnaryAccessor = oldUnary;
                    }

                    this.WriteDot();

                    this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName());

                    if (!isStatic)
                    {
                        this.Write(")");
                    }

                    return;
                }
                else
                {
                    bool isProperty = false;

                    if (member != null && member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !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)
                        {
                            var  memberTargetrr = targetrr as MemberResolveResult;
                            bool isField        = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult);

                            if (!(targetrr is ThisResolveResult || 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;
                    memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                    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)
                {
                    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.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment))
                    {
                        this.PushWriter(inline);
                    }
                    else
                    {
                        this.Write(inline);
                    }
                }
                else if (member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition))
                {
                    var proto = false;
                    if (this.MemberReferenceExpression.Target is BaseReferenceExpression && member != null)
                    {
                        var prop = member.Member as IProperty;

                        if (prop != null && prop.IsVirtual)
                        {
                            proto = true;
                        }
                    }

                    if (Helpers.IsFieldProperty(member.Member, this.Emitter))
                    {
                        this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter));
                    }
                    else if (!this.Emitter.IsAssignment)
                    {
                        if (this.Emitter.IsUnaryAccessor)
                        {
                            bool isNullable = NullableType.IsNullable(member.Member.ReturnType);
                            bool isDecimal  = Helpers.IsDecimalType(member.Member.ReturnType, this.Emitter.Resolver);

                            if (isStatement)
                            {
                                this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true));
                                if (proto)
                                {
                                    this.Write(".call");
                                    this.WriteOpenParentheses();
                                    this.WriteThis();
                                    this.WriteComma();
                                }
                                else
                                {
                                    this.WriteOpenParentheses();
                                }

                                if (isDecimal)
                                {
                                    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();

                                        if (targetVar != null)
                                        {
                                            this.Write(targetVar);
                                        }
                                        else
                                        {
                                            memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                        }

                                        this.WriteDot();

                                        this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));

                                        if (proto)
                                        {
                                            this.Write(".call");
                                            this.WriteOpenParentheses();
                                            this.WriteThis();
                                            this.WriteCloseParentheses();
                                        }
                                        else
                                        {
                                            this.WriteOpenParentheses();
                                            this.WriteCloseParentheses();
                                        }

                                        this.WriteCloseParentheses();
                                    }
                                    else
                                    {
                                        if (targetVar != null)
                                        {
                                            this.Write(targetVar);
                                        }
                                        else
                                        {
                                            memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                        }

                                        this.WriteDot();

                                        this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));

                                        if (proto)
                                        {
                                            this.Write(".call");
                                            this.WriteOpenParentheses();
                                            this.WriteThis();
                                            this.WriteCloseParentheses();
                                        }
                                        else
                                        {
                                            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();

                                        this.WriteCloseParentheses();
                                    }
                                }
                                else
                                {
                                    if (targetVar != null)
                                    {
                                        this.Write(targetVar);
                                    }
                                    else
                                    {
                                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                    }

                                    this.WriteDot();

                                    this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));

                                    if (proto)
                                    {
                                        this.Write(".call");
                                        this.WriteOpenParentheses();
                                        this.WriteThis();
                                        this.WriteCloseParentheses();
                                    }
                                    else
                                    {
                                        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(member.Member, this.Emitter, false));
                                if (proto)
                                {
                                    this.Write(".call");
                                    this.WriteOpenParentheses();
                                    this.WriteThis();
                                    this.WriteCloseParentheses();
                                }
                                else
                                {
                                    this.WriteOpenParentheses();
                                    this.WriteCloseParentheses();
                                }
                                this.WriteComma();

                                if (targetVar != null)
                                {
                                    this.Write(targetVar);
                                }
                                else
                                {
                                    memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                }

                                this.WriteDot();
                                this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true));

                                if (proto)
                                {
                                    this.Write(".call");
                                    this.WriteOpenParentheses();
                                    this.WriteThis();
                                    this.WriteComma();
                                }
                                else
                                {
                                    this.WriteOpenParentheses();
                                }

                                if (isDecimal)
                                {
                                    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();

                                bool isPreOp = this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment ||
                                               this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement;

                                if (isPreOp)
                                {
                                    if (targetVar != null)
                                    {
                                        this.Write(targetVar);
                                    }
                                    else
                                    {
                                        memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                                    }
                                    this.WriteDot();
                                    this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false));
                                    this.WriteOpenParentheses();
                                    this.WriteCloseParentheses();
                                }
                                else
                                {
                                    this.Write(valueVar);
                                }
                                this.WriteCloseParentheses();

                                if (valueVar != null)
                                {
                                    this.RemoveTempVar(valueVar);
                                }
                            }

                            if (targetVar != null)
                            {
                                this.RemoveTempVar(targetVar);
                            }
                        }
                        else
                        {
                            this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter));
                            if (proto)
                            {
                                this.Write(".call");
                                this.WriteOpenParentheses();
                                this.WriteThis();
                                this.WriteCloseParentheses();
                            }
                            else
                            {
                                this.WriteOpenParentheses();
                                this.WriteCloseParentheses();
                            }
                        }
                    }
                    else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
                    {
                        if (targetVar != null)
                        {
                            this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true),
                                                          proto ? ".call(this, " : "(",
                                                          targetVar,
                                                          ".",
                                                          Helpers.GetPropertyRef(member.Member, this.Emitter, false),
                                                          proto ? ".call(this)" : "()",
                                                          "{0})"), () => { this.RemoveTempVar(targetVar); });
                        }
                        else
                        {
                            var oldWriter = this.SaveWriter();
                            this.NewWriter();

                            this.Emitter.IsAssignment    = false;
                            this.Emitter.IsUnaryAccessor = false;
                            memberReferenceExpression.Target.AcceptVisitor(this.Emitter);
                            this.Emitter.IsAssignment    = oldIsAssignment;
                            this.Emitter.IsUnaryAccessor = oldUnary;
                            var trg = this.Emitter.Output.ToString();

                            this.RestoreWriter(oldWriter);
                            this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true),
                                                          proto ? ".call(this, " : "(",
                                                          trg,
                                                          ".",
                                                          Helpers.GetPropertyRef(member.Member, this.Emitter, false),
                                                          proto ? ".call(this)" : "()",
                                                          "{0})"));
                        }
                    }
                    else
                    {
                        if (proto)
                        {
                            this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + ".call(this, {0})");
                        }
                        else
                        {
                            this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + "({0})");
                        }
                    }
                }
                else if (member.Member.SymbolKind == SymbolKind.Field)
                {
                    bool isConst = this.Emitter.IsMemberConst(member.Member);

                    if (isConst && this.Emitter.IsInlineConst(member.Member))
                    {
                        this.WriteScript(member.ConstantValue);
                    }
                    else
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName());
                    }
                }
                else if (resolveResult is InvocationResolveResult)
                {
                    InvocationResolveResult       invocationResult  = (InvocationResolveResult)resolveResult;
                    CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult;
                    var expresssionMember = expressionResolveResult as MemberResolveResult;

                    if (expresssionMember != null &&
                        cInvocationResult != null &&
                        cInvocationResult.IsDelegateInvocation &&
                        invocationResult.Member != expresssionMember.Member)
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName());
                    }
                    else
                    {
                        this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName());
                    }
                }
                else if (member.Member is DefaultResolvedEvent && this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract))
                {
                    this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove");
                    this.Write(OverloadsCollection.Create(this.Emitter, member.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName());
                    this.WriteOpenParentheses();
                }
                else
                {
                    this.Write(this.Emitter.GetEntityName(member.Member));
                }

                Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this);
            }
        }
示例#19
0
        protected virtual string GetCastCode(Expression expression, AstType astType, out bool isCastAttr)
        {
            var resolveResult = this.Emitter.Resolver.ResolveNode(astType, this.Emitter) as TypeResolveResult;

            isCastAttr = false;

            if (resolveResult == null)
            {
                return(null);
            }

            var    exprResolveResult = this.Emitter.Resolver.ResolveNode(expression, this.Emitter);
            string inline            = null;

            var method = this.GetCastMethod(exprResolveResult.Type, resolveResult.Type, out inline);

            if (method == null && (NullableType.IsNullable(exprResolveResult.Type) || NullableType.IsNullable(resolveResult.Type)))
            {
                method = this.GetCastMethod(NullableType.IsNullable(exprResolveResult.Type) ? NullableType.GetUnderlyingType(exprResolveResult.Type) : exprResolveResult.Type,
                                            NullableType.IsNullable(resolveResult.Type) ? NullableType.GetUnderlyingType(resolveResult.Type) : resolveResult.Type, out inline);
            }

            if (inline != null)
            {
                this.InlineMethod = method;
                return(inline);
            }

            IEnumerable <IAttribute> attributes = null;
            var type = resolveResult.Type.GetDefinition();

            if (type != null)
            {
                attributes = type.Attributes;
            }
            else
            {
                ParameterizedType paramType = resolveResult.Type as ParameterizedType;

                if (paramType != null)
                {
                    attributes = paramType.GetDefinition().Attributes;
                }
            }

            if (attributes != null)
            {
                var attribute = this.Emitter.GetAttribute(attributes, Translator.Bridge_ASSEMBLY + ".CastAttribute");

                if (attribute != null)
                {
                    isCastAttr = true;
                    return(attribute.PositionalArguments[0].ConstantValue.ToString());
                }
            }

            return(null);
        }
示例#20
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="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.NumericCompoundAssign:
            case OpCode.UserDefinedCompoundAssign:
            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 (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:
            case OpCode.LdObj:
                if (parent.Parent.OpCode == OpCode.DynamicCompoundAssign)
                {
                    return(true);                            // inline into dynamic compound assignments
                }
                break;

            case OpCode.ArrayToPointer:
            case OpCode.LocAllocSpan:
                return(true);                        // inline size-expressions into localloc.span
            }
            // decide based on the top-level target instruction into which we are inlining:
            switch (next.OpCode)
            {
            case OpCode.Leave:
            case OpCode.YieldReturn:
                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:
                if (parent == next)
                {
                    return(true);
                }
                if (parent.MatchBinaryNumericInstruction(BinaryNumericOperator.Sub) && parent.Parent == next)
                {
                    return(true);
                }
                if (parent is StringToInt stringToInt && stringToInt.Parent == next)
                {
                    return(true);
                }
                return(false);

            default:
                return(false);
            }
        }
示例#21
0
        public Expression ResolveUnaryOperator(ResolveContext rc, UnaryOperatorType op, Expression expression)
        {
            // V# 4.0 spec: §7.3.3 Unary operator overload resolution
            string overloadableOperatorName = GetOverloadableOperatorName(op);

            if (overloadableOperatorName == null)
            {
                switch (op)
                {
                case UnaryOperatorType.Dereference:
                    PointerTypeSpec p = expression.Type as PointerTypeSpec;
                    if (p != null)
                    {
                        return(SetOperationInformations(rc, p.ElementType, op, expression));
                    }
                    else
                    {
                        return(ErrorResult);
                    }

                case UnaryOperatorType.AddressOf:
                    return(SetOperationInformations(rc, new PointerTypeSpec(expression.Type), op, expression));


                default:
                    return(ErrorExpression.UnknownError);
                }
            }
            // If the type is nullable, get the underlying type:
            IType type       = NullableType.GetUnderlyingType(expression.Type);
            bool  isNullable = NullableType.IsNullable(expression.Type);

            // the operator is overloadable:
            OverloadResolution userDefinedOperatorOR = rc.CreateOverloadResolution(new[] { expression });

            foreach (var candidate in rc.GetUserDefinedOperatorCandidates(type, overloadableOperatorName))
            {
                userDefinedOperatorOR.AddCandidate(candidate);
            }
            if (userDefinedOperatorOR.FoundApplicableCandidate)
            {
                return(SetUserDefinedOperationInformations(rc, userDefinedOperatorOR));
            }

            expression = UnaryNumericPromotion(rc, op, ref type, isNullable, expression);
            VSharpOperators.OperatorMethod[] methodGroup;
            VSharpOperators operators = VSharpOperators.Get(rc.compilation);

            switch (op)
            {
            case UnaryOperatorType.PreIncrement:
            case UnaryOperatorType.Decrement:
            case UnaryOperatorType.PostIncrement:
            case UnaryOperatorType.PostDecrement:
                // V# 4.0 spec: §7.6.9 Postfix increment and decrement operators
                // V# 4.0 spec: §7.7.5 Prefix increment and decrement operators
                TypeCode code = ReflectionHelper.GetTypeCode(type);
                if ((code >= TypeCode.Char && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer)
                {
                    return(SetOperationInformations(rc, expression.Type, op, expression, isNullable));
                }
                else
                {
                    return(new ErrorExpression(expression.Type));
                }

            case UnaryOperatorType.UnaryPlus:
                methodGroup = operators.UnaryPlusOperators;
                break;

            case UnaryOperatorType.UnaryNegation:
                methodGroup = rc.checkForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators;
                break;

            case UnaryOperatorType.LogicalNot:
                methodGroup = operators.LogicalNegationOperators;
                break;

            case UnaryOperatorType.OnesComplement:
                if (type.Kind == TypeKind.Enum)
                {
                    if (expression.IsCompileTimeConstant && !isNullable && expression.ConstantValue != null)
                    {
                        // evaluate as (E)(~(U)x);
                        var            U            = rc.compilation.FindType(expression.ConstantValue.GetType());
                        var            unpackedEnum = Constant.CreateConstantFromValue(rc, U, expression.ConstantValue, loc);
                        var            rr           = ResolveUnaryOperator(rc, op, unpackedEnum);
                        ResolveContext ovfrc        = rc.WithCheckForOverflow(false);
                        rr = new CastExpression(type, rr).DoResolve(ovfrc);
                        if (rr.IsCompileTimeConstant)
                        {
                            return(rr);
                        }
                    }
                    return(SetOperationInformations(rc, expression.Type, op, expression, isNullable));
                }
                else
                {
                    methodGroup = operators.BitwiseComplementOperators;
                    break;
                }

            default:
                throw new InvalidOperationException();
            }
            OverloadResolution builtinOperatorOR = rc.CreateOverloadResolution(new[] { expression });

            foreach (var candidate in methodGroup)
            {
                builtinOperatorOR.AddCandidate(candidate);
            }
            VSharpOperators.UnaryOperatorMethod m = (VSharpOperators.UnaryOperatorMethod)builtinOperatorOR.BestCandidate;
            IType resultType = m.ReturnType;

            if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None)
            {
                if (userDefinedOperatorOR.BestCandidate != null)
                {
                    // If there are any user-defined operators, prefer those over the built-in operators.
                    // It'll be a more informative error.
                    return(SetUserDefinedOperationInformations(rc, userDefinedOperatorOR));
                }
                else if (builtinOperatorOR.BestCandidateAmbiguousWith != null)
                {
                    // If the best candidate is ambiguous, just use the input type instead
                    // of picking one of the ambiguous overloads.
                    return(new ErrorExpression(expression.Type));
                }
                else
                {
                    return(new ErrorExpression(resultType));
                }
            }
            else if (expression.IsCompileTimeConstant && m.CanEvaluateAtCompileTime)
            {
                object val;
                try
                {
                    val = m.Invoke(rc, expression.ConstantValue);
                }
                catch (ArithmeticException)
                {
                    return(new ErrorExpression(resultType));
                }
                return(Constant.CreateConstantFromValue(rc, resultType, val, loc));
            }
            else
            {
                expression = rc.Convert(expression, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]);
                return(SetOperationInformations(rc, resultType, op, expression,
                                                builtinOperatorOR.BestCandidate is OverloadResolution.ILiftedOperator));
            }
        }
示例#22
0
        public static string ToJavascriptName(IType type, IEmitter emitter)
        {
            if (type.Kind == TypeKind.Delegate)
            {
                var delegateName = H5Types.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.Double) ||
                type.IsKnownType(KnownTypeCode.Int16) ||
                type.IsKnownType(KnownTypeCode.Int32) ||
                type.IsKnownType(KnownTypeCode.SByte) ||
                type.IsKnownType(KnownTypeCode.Single) ||
                type.IsKnownType(KnownTypeCode.UInt16) ||
                type.IsKnownType(KnownTypeCode.UInt32))
            {
                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));
            }

            H5Type h5Type = emitter.H5Types.Get(type, true);
            //string name = H5Types.ConvertName(type.FullName);

            var name = type.Namespace;

            var  hasTypeDef = h5Type != null && h5Type.TypeDefinition != null;
            bool isNested   = false;

            if (hasTypeDef)
            {
                var typeDef = h5Type.TypeDefinition;
                if (typeDef.IsNested)
                {
                    name     = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + H5Types.GetParentNames(emitter, typeDef);
                    isNested = true;
                }

                name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + H5Types.ConvertName(typeDef.Name);
            }
            else
            {
                if (type.DeclaringType != null)
                {
                    name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + H5Types.GetParentNames(emitter, type);

                    if (type.DeclaringType.TypeArguments.Count > 0)
                    {
                        name += Helpers.PrefixDollar(type.TypeArguments.Count);
                    }
                    isNested = true;
                }

                name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + H5Types.ConvertName(type.Name);
            }

            bool isCustomName = false;

            if (h5Type != null)
            {
                name = H5Types.AddModule(name, h5Type, false, isNested, out isCustomName);
            }

            if (!hasTypeDef && !isCustomName && type.TypeArguments.Count > 0)
            {
                name += Helpers.PrefixDollar(type.TypeArguments.Count);
            }

            return(name);
        }
示例#23
0
        private static void CheckLong(ConversionBlock block, Expression expression, IType expectedType, IType fromType, bool isChecked)
        {
            if (!NeedsNarrowingNumericConversion(fromType, expectedType))
            {
                return;
            }

            if (isChecked)
            {
                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 += ")";
                }
            }
        }
示例#24
0
        protected void VisitIdentifierExpression()
        {
            IdentifierExpression identifierExpression = this.IdentifierExpression;
            int           pos           = this.Emitter.Output.Length;
            ResolveResult resolveResult = null;

            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))
            {
                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()))
                 * {
                 *  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 (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))
                     * {
                     *  this.Write("(Bridge.get(" + BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))");
                     * }
                     * else
                     * {
                     *  this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter));
                     * }*/
                }
                else
                {
                    this.WriteThis();
                }

                inlineCode          = inlineCode.Replace("{this}", this.Emitter.Output.ToString());
                this.Emitter.Output = oldBuilder;

                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inlineCode);
                }
                else
                {
                    this.Write(inlineCode);
                }

                return;
            }

            if (hasInline && memberResult.Member.IsStatic)
            {
                if (resolveResult is InvocationResolveResult)
                {
                    this.PushWriter(inlineCode);
                }
                else
                {
                    this.Write(inlineCode);
                }
            }

            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.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);
                }
                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 isNullable = NullableType.IsNullable(memberResult.Member.ReturnType);
                        if (isStatement)
                        {
                            this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true));
                            this.WriteOpenParentheses();

                            if (isDecimal)
                            {
                                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)
                            {
                                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();
                        if (!memberResult.Member.IsStatic && memberResult.Member.IsInternalMember())
                        {
                            this.WriteThis();
                        }
                        this.WriteCloseParentheses();
                    }
                }
                else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign)
                {
                    this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + "({0})");

                    /*
                     * 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
                {
                    string argsFormatStr;
                    if (!memberResult.Member.IsStatic && memberResult.Member.DeclaringType == TransformCtx.CurClass)
                    {
                        argsFormatStr = "(this, {0})";
                    }
                    else
                    {
                        argsFormatStr = "({0})";
                    }

                    this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + argsFormatStr);
                }
            }
            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;
                        this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter));

                        /*
                         * var isNative = this.Emitter.Validator.IsIgnoreType(typeResolveResult.Type.GetDefinition());
                         * 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)
                    {
                        if (resolveResult.IsCompileTimeConstant)
                        {
                            this.Write(resolveResult.ConstantValue);
                        }
                        else
                        {
                            var localResolveResult = (LocalResolveResult)resolveResult;
                            this.Write(localResolveResult.Variable.Name);
                        }
                    }
                    else if (memberResult != null)
                    {
                        if (this.Emitter.IsMemberConst(memberResult.Member))
                        {
                            this.Write(memberResult.ConstantValue);
                        }
                        else
                        {
                            this.WriteTarget(memberResult);
                            this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName());
                        }
                    }
                    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);
        }
示例#25
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);
        }
示例#26
0
        public static string ToTypeScriptName(IType type, IEmitter emitter, bool asDefinition = false, bool excludens = false, bool ignoreDependency = false, List <string> guard = null)
        {
            if (type.Kind == TypeKind.Delegate)
            {
                if (guard == null)
                {
                    guard = new List <string>();
                }

                if (guard.Contains(type.FullName))
                {
                    return("Function");
                }

                guard.Add(type.FullName);
                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, guard: guard);

                    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, guard: guard));
                sb.Append("}");
                guard.Remove(type.FullName);
                return(sb.ToString());
            }

            var oname = ObjectLiteralSignature(type, emitter);

            if (oname != null)
            {
                return(oname);
            }

            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.Array))
            {
                return("any[]");
            }

            if (type.IsKnownType(KnownTypeCode.Byte) ||
                type.IsKnownType(KnownTypeCode.Char) ||
                type.IsKnownType(KnownTypeCode.Double) ||
                type.IsKnownType(KnownTypeCode.Int16) ||
                type.IsKnownType(KnownTypeCode.Int32) ||
                type.IsKnownType(KnownTypeCode.SByte) ||
                type.IsKnownType(KnownTypeCode.Single) ||
                type.IsKnownType(KnownTypeCode.UInt16) ||
                type.IsKnownType(KnownTypeCode.UInt32))
            {
                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, guard: guard) + "[]");
            }

            if (type.Kind == TypeKind.Dynamic || type.IsKnownType(KnownTypeCode.Object))
            {
                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, guard: guard));
            }

            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;
            bool isNested   = false;

            if (hasTypeDef)
            {
                var typeDef = bridgeType.TypeDefinition;
                if (typeDef.IsNested && !excludens)
                {
                    //name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(emitter, typeDef);
                    name     = BridgeTypes.ToJsName(typeDef.DeclaringType, emitter, true, ignoreVirtual: true);
                    isNested = true;
                }

                name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(emitter.GetTypeName(bridgeType.Type.GetDefinition(), typeDef));
            }
            else
            {
                if (type.DeclaringType != null && !excludens)
                {
                    //name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(emitter, type);
                    name = BridgeTypes.ToJsName(type.DeclaringType, emitter, true, ignoreVirtual: true);

                    if (type.DeclaringType.TypeArguments.Count > 0)
                    {
                        name += Helpers.PrefixDollar(type.TypeArguments.Count);
                    }
                    isNested = true;
                }

                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.GetCustomName(name, bridgeType, excludens, isNested, ref isCustomName, null);
            }

            if (!hasTypeDef && !isCustomName && type.TypeArguments.Count > 0)
            {
                name += Helpers.PrefixDollar(type.TypeArguments.Count);
            }

            if (!asDefinition && type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(type, emitter, true))
            {
                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, guard: guard));
                }
                sb.Append(">");
                name = sb.ToString();
            }

            return(name);
        }
示例#27
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));
 }
        private void HandleDecimal(ResolveResult resolveOperator)
        {
            if (this.AssignmentExpression.Operator == AssignmentOperatorType.Assign)
            {
                new ExpressionListBlock(this.Emitter,
                                        new Expression[] { this.AssignmentExpression.Right }, null).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(Bridge.Translator.Emitter.ROOT + ".Nullable.");
                    string action  = "lift2";
                    string op_name = null;

                    switch (assigmentType)
                    {
                    case BinaryOperatorType.GreaterThan:
                        op_name = "gt";
                        break;

                    case BinaryOperatorType.GreaterThanOrEqual:
                        op_name = "gte";
                        break;

                    case BinaryOperatorType.Equality:
                        op_name = "equals";
                        break;

                    case BinaryOperatorType.InEquality:
                        op_name = "ne";
                        break;

                    case BinaryOperatorType.LessThan:
                        op_name = "lt";
                        break;

                    case BinaryOperatorType.LessThanOrEqual:
                        op_name = "lte";
                        break;

                    case BinaryOperatorType.Add:
                        op_name = "add";
                        break;

                    case BinaryOperatorType.Subtract:
                        op_name = "sub";
                        break;

                    case BinaryOperatorType.Multiply:
                        op_name = "mul";
                        break;

                    case BinaryOperatorType.Divide:
                        op_name = "div";
                        break;

                    case BinaryOperatorType.Modulus:
                        op_name = "mod";
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    this.Write(action);
                    this.WriteOpenParentheses();
                    this.WriteScript(op_name);
                    this.WriteComma();
                    new ExpressionListBlock(this.Emitter,
                                            new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null).Emit();
                    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.IsIgnoreType(method.DeclaringTypeDefinition))
                {
                    this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter));
                    this.WriteDot();

                    this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName());

                    this.WriteOpenParentheses();

                    new ExpressionListBlock(this.Emitter,
                                            new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null).Emit();
                    this.WriteCloseParentheses();
                }
            }
        }
示例#29
0
        protected void VisitUnaryOperatorExpression()
        {
            var unaryOperatorExpression = this.UnaryOperatorExpression;
            var oldType     = this.Emitter.UnaryOperatorType;
            var oldAccessor = this.Emitter.IsUnaryAccessor;

            var resolveOperator       = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression, this.Emitter);
            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;

            if (resolveOperator is ConstantResolveResult)
            {
                this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue);
                return;
            }

            if (this.ResolveOperator(unaryOperatorExpression, orr))
            {
                return;
            }

            var  op = unaryOperatorExpression.Operator;
            var  argResolverResult = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression.Expression, this.Emitter);
            bool nullable          = NullableType.IsNullable(argResolverResult.Type);

            if (nullable)
            {
                if (op != UnaryOperatorType.Increment &&
                    op != UnaryOperatorType.Decrement &&
                    op != UnaryOperatorType.PostIncrement &&
                    op != UnaryOperatorType.PostDecrement)
                {
                    this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable.");
                }
            }

            bool isAccessor = false;
            var  memberArgResolverResult = argResolverResult as MemberResolveResult;

            if (memberArgResolverResult != null && memberArgResolverResult.Member is IProperty)
            {
                isAccessor = true;
            }
            else if (argResolverResult is ArrayAccessResolveResult)
            {
                isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1;
            }

            this.Emitter.UnaryOperatorType = op;

            if (isAccessor &&
                (op == UnaryOperatorType.Increment ||
                 op == UnaryOperatorType.Decrement ||
                 op == UnaryOperatorType.PostIncrement ||
                 op == UnaryOperatorType.PostDecrement))
            {
                this.Emitter.IsUnaryAccessor = true;

                if (nullable)
                {
                    this.Write("(Bridge.hasValue(");
                    this.Emitter.IsUnaryAccessor = false;
                    unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(") ? ");
                    this.Emitter.IsUnaryAccessor = true;
                    unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    this.Write(" : null)");
                }
                else
                {
                    unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                }

                this.Emitter.IsUnaryAccessor = oldAccessor;
            }
            else
            {
                switch (op)
                {
                case UnaryOperatorType.BitNot:
                    if (nullable)
                    {
                        this.Write("bnot(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        this.Write("~");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Decrement:
                    if (nullable)
                    {
                        this.Write("(Bridge.hasValue(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? --");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(" : null)");
                    }
                    else
                    {
                        this.Write("--");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Increment:
                    if (nullable)
                    {
                        this.Write("(Bridge.hasValue(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ++");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(" : null)");
                    }
                    else
                    {
                        this.Write("++");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Minus:
                    if (nullable)
                    {
                        this.Write("neg(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        this.Write("-");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Not:
                    if (nullable)
                    {
                        this.Write("not(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        this.Write("!");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }
                    break;

                case UnaryOperatorType.Plus:
                    if (nullable)
                    {
                        this.Write("pos(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(")");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                    }

                    break;

                case UnaryOperatorType.PostDecrement:
                    if (nullable)
                    {
                        this.Write("(Bridge.hasValue(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("-- : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("--");
                    }
                    break;

                case UnaryOperatorType.PostIncrement:
                    if (nullable)
                    {
                        this.Write("(Bridge.hasValue(");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write(") ? ");
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("++ : null)");
                    }
                    else
                    {
                        unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter);
                        this.Write("++");
                    }
                    break;

                case UnaryOperatorType.Await:
                    if (this.Emitter.ReplaceAwaiterByVar)
                    {
                        var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, unaryOperatorExpression.Expression) + 1;
                        this.Write("$taskResult" + index);
                    }
                    else
                    {
                        var oldValue = this.Emitter.ReplaceAwaiterByVar;
                        var oldAsyncExpressionHandling = this.Emitter.AsyncExpressionHandling;

                        if (this.Emitter.IsAsync && !this.Emitter.AsyncExpressionHandling)
                        {
                            this.WriteAwaiters(unaryOperatorExpression.Expression);
                            this.Emitter.ReplaceAwaiterByVar     = true;
                            this.Emitter.AsyncExpressionHandling = true;
                        }

                        this.WriteAwaiter(unaryOperatorExpression.Expression);

                        this.Emitter.ReplaceAwaiterByVar     = oldValue;
                        this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling;
                    }
                    break;

                default:
                    throw new EmitterException(unaryOperatorExpression, "Unsupported unary operator: " + unaryOperatorExpression.Operator.ToString());
                }
            }

            this.Emitter.UnaryOperatorType = oldType;
        }
示例#30
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(")");
            }
        }