示例#1
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 crr)
            {
                object constantValue = crr.ConstantValue;

                if (unaryOperatorExpression.Operator == UnaryOperatorType.Minus && SyntaxHelper.IsNumeric(constantValue.GetType()) && Convert.ToDouble(constantValue) == 0)
                {
                    this.Write("-");
                }

                this.WriteScript(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)
            {
                var prop = memberArgResolverResult.Member as IProperty;

                if (prop != null)
                {
                    var isIgnore   = memberArgResolverResult.Member.DeclaringTypeDefinition != null && this.Emitter.Validator.IsExternalType(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.IsExternalType(prop.Getter);
                    var isAccessorsIndexer = this.Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member);

                    isAccessor = prop.IsIndexer;

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