public void GenerateInto(Scope scope)
        {
            Debug.Assert(operands.Count >= 2, "Not enough operands for binary expression");

            var ops = new Queue <ExpressionSyntax>();

            foreach (var op in operands)
            {
                ops.Enqueue(op);
            }

            var            left    = ops.Dequeue();
            ScriptDataType?topType = this.OwnDataType;

            while (ops.Any())
            {
                var right = ops.Dequeue();

                var binExp = SyntaxFactory.BinaryExpression(operatorSyntaxKind,
                                                            left, right);

                if (numericPromotionOperators.Contains(this.operatorSyntaxKind) &&
                    SyntaxUtil.TryGetTypeOfExpression(left, out var leftType) &&
                    SyntaxUtil.TryGetTypeOfExpression(right, out var rightType))
                {
                    var promoted = SyntaxUtil.BinaryNumericPromotion(leftType, rightType);
                    binExp  = binExp.WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(promoted));
                    topType = promoted;
                }

                left = binExp;
            }

            if (topType.HasValue && topType.Value != scope.Type)
            {
                left = SyntaxUtil.CreateCast(topType.Value, scope.Type, SyntaxFactory.ParenthesizedExpression(left));
            }

            scope.Context.AddExpression(left);
        }
Exemple #2
0
        public void GenerateInto(Scope scope)
        {
            var invocationExpression = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                            SyntaxFactory.IdentifierName("Engine"),
                                                                            SyntaxFactory.IdentifierName(this.MethodName));

            ExpressionSyntax invocation = SyntaxFactory.InvocationExpression(invocationExpression)
                                          .WithArgumentList(SyntaxFactory.ArgumentList(
                                                                SyntaxFactory.SeparatedList(this.arguments)))
                                          .WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(this.ReturnType));

            var tempArgs = new List <Type>();

            foreach (var t in argumentTypes)
            {
                if (t.HasValue && SyntaxUtil.TryGetTypeFromScriptType(t.Value, out var T))
                {
                    tempArgs.Add(T);
                }
                else
                {
                    break;
                }
            }

            if (tempArgs.Count == argumentTypes.Count)
            {
                // Do full overload match
                var method = typeof(IScriptEngine).GetMethod(this.MethodName,
                                                             BindingFlags.Public | BindingFlags.Instance,
                                                             null,
                                                             tempArgs.ToArray(),
                                                             null);

                if (method != null)
                {
                    SyntaxUtil.AwaitIfNeeded(method, ref invocation, out var materializedReturnType);

                    if (SyntaxUtil.TryGetScriptTypeFromType(materializedReturnType, out var fromType))
                    {
                        // Insert cast to destination
                        invocation = SyntaxUtil.CreateCast(fromType, this.ReturnType, invocation)
                                     .WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(this.ReturnType));
                    }
                }
            }
            else
            {
                // Fallback to name only lookup
                var scriptEngineMethods = typeof(IScriptEngine).GetMethods().Where(m => m.Name == this.MethodName);

                if (scriptEngineMethods.Any())
                {
                    //var hasOverload = scriptEngineMethods.Any(m => m.ReturnType == destinationType);

                    //if (hasOverload == false)
                    {
                        var method = scriptEngineMethods.First();

                        SyntaxUtil.AwaitIfNeeded(method, ref invocation, out var materializedReturnType);

                        if (SyntaxUtil.TryGetScriptTypeFromType(materializedReturnType, out var fromType) && fromType != this.ReturnType)
                        {
                            // Insert cast to destination
                            invocation = SyntaxUtil.CreateCast(fromType, this.ReturnType, invocation)
                                         .WithAdditionalAnnotations(ScriptGenAnnotations.TypeAnnotation(this.ReturnType));
                        }
                    }
                }
            }

            scope.Context.AddExpression(invocation);
        }