Beispiel #1
0
        protected void VisitUnaryOperatorExpression()
        {
            var  unaryOperatorExpression = UnaryOperatorExpression;
            var  oldType              = Emitter.UnaryOperatorType;
            var  oldAccessor          = Emitter.IsUnaryAccessor;
            var  resolveOperator      = Emitter.Resolver.ResolveNode(unaryOperatorExpression);
            var  expectedType         = Emitter.Resolver.Resolver.GetExpectedType(unaryOperatorExpression);
            bool isDecimalExpected    = Helpers.IsDecimalType(expectedType, Emitter.Resolver);
            bool isDecimal            = Helpers.IsDecimalType(resolveOperator.Type, Emitter.Resolver);
            bool isLongExpected       = Helpers.Is64Type(expectedType, Emitter.Resolver);
            bool isLong               = Helpers.Is64Type(resolveOperator.Type, Emitter.Resolver);
            OperatorResolveResult orr = resolveOperator as OperatorResolveResult;
            int count = 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)
                {
                    Write("-");
                }

                WriteScript(constantValue);
                return;
            }

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

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

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

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

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

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

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

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

            bool isAccessor = false;


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

                    var ignoreAccessor     = prop.Getter != null && Emitter.Validator.IsExternalType(prop.Getter);
                    var isAccessorsIndexer = 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;
            }

            Emitter.UnaryOperatorType = op;

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

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

                Emitter.IsUnaryAccessor = oldAccessor;

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

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

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

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

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

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

                    break;

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

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

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

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

                        WriteAwaiter(unaryOperatorExpression.Expression);

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

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

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

            Emitter.UnaryOperatorType = oldType;
        }