Beispiel #1
0
        public override BoundNode VisitAssignmentExpression(AssignmentExpressionSyntax node)
        {
            BoundAccessExpression assignmentTarget = VisitAccessExpression(node.Left);

            if (node.Kind() != SyntaxKind.SimpleAssignmentExpression)
            {
                MethodSymbol operatorSymbol = (MethodSymbol)GetSymbol(node);

                BoundExpression rhsExpression = VisitExpression(node.Right);

                // Apparently Roslyn returns string + string for string += char, but returns string + object for string + char /shrug
                // Do ToString here if the constant folding can't convert the char
                if (assignmentTarget.ValueType == Context.GetTypeSymbol(SpecialType.System_String) &&
                    rhsExpression.ValueType == Context.GetTypeSymbol(SpecialType.System_Char))
                {
                    if (rhsExpression.IsConstant)
                    {
                        rhsExpression = new BoundConstantExpression(rhsExpression.ConstantValue.Value.ToString(), Context.GetTypeSymbol(SpecialType.System_String));
                    }
                    else
                    {
                        rhsExpression = BoundInvocationExpression.CreateBoundInvocation(Context, node, Context.GetTypeSymbol(SpecialType.System_Char).GetMember <MethodSymbol>("ToString", Context), rhsExpression, Array.Empty <BoundExpression>());
                    }
                }
                if (operatorSymbol is ExternBuiltinOperatorSymbol builtinOperatorSymbol)
                {
                    operatorSymbol = new ExternSynthesizedOperatorSymbol(builtinOperatorSymbol.OperatorType,
                                                                         assignmentTarget.ValueType, Context);
                }

                return(BoundInvocationExpression.CreateBoundInvocation(Context, node, operatorSymbol, null,
                                                                       new[] { assignmentTarget, ConvertExpression(node, rhsExpression, operatorSymbol.Parameters[1].Type) }));
            }
            return(new BoundAssignmentExpression(node, assignmentTarget, VisitExpression(node.Right, assignmentTarget.ValueType)));
        }
            private static BoundExpression[] GetParameterExpressions(AbstractPhaseContext context, MethodSymbol symbol, BoundExpression[] parameters)
            {
                BoundExpression typeExpression = new BoundConstantExpression(
                    symbol.TypeArguments[0].UdonType.SystemType,
                    context.GetTypeSymbol(typeof(Type)));

                if (parameters == null || parameters.Length == 0)
                {
                    return new [] { typeExpression }
                }
                ;

                return(parameters.Concat(new [] { typeExpression }).ToArray());
            }
Beispiel #3
0
        private static bool TryImplicitConstantConversion(ref BoundExpression boundExpression, TypeSymbol targetType)
        {
            if (!boundExpression.IsConstant)
            {
                return(false);
            }
            if (boundExpression.ValueType == targetType)
            {
                return(false);
            }

            var targetSystemType = targetType.UdonType.SystemType;

            object constantValue = boundExpression.ConstantValue.Value;

            // if (targetSystemType == typeof(string))
            // {
            //     IConstantValue constant = new ConstantValue<string>(constantValue?.ToString() ?? "");
            //
            //     boundExpression = new BoundConstantExpression(constant, targetType, boundExpression.SyntaxNode);
            // }

            var sourceSystemType = boundExpression.ValueType.UdonType.SystemType;

            if (ConstantExpressionOptimizer.CanDoConstantConversion(sourceSystemType) &&
                ConstantExpressionOptimizer.CanDoConstantConversion(targetSystemType))
            {
                IConstantValue constant = (IConstantValue)Activator.CreateInstance(typeof(ConstantValue <>).MakeGenericType(targetSystemType), ConstantExpressionOptimizer.FoldConstantConversion(targetSystemType, constantValue));
                boundExpression = new BoundConstantExpression(constant, targetType, boundExpression.SyntaxNode);

                return(true);
            }

            if (boundExpression.ValueType.IsEnum &&
                boundExpression.ValueType.IsExtern &&
                UdonSharpUtils.IsIntegerType(targetSystemType))
            {
                boundExpression = new BoundConstantExpression(ConstantExpressionOptimizer.FoldConstantConversion(targetSystemType, constantValue), targetType);

                return(true);
            }

            return(false);
        }
        public BoundInterpolatedStringExpression(InterpolatedStringExpressionSyntax node, string builtStr, BoundExpression[] interpolatedExpressions, BindContext context)
            : base(node)
        {
            ValueType = context.GetTypeSymbol(SpecialType.System_String);

            BuiltStr = new BoundConstantExpression(new ConstantValue <string>(builtStr), ValueType, node);
            InterpolationExpressions = interpolatedExpressions;

            ObjectArr = context.GetTypeSymbol(SpecialType.System_Object).MakeArrayType(context);

            if (interpolatedExpressions.Length > 3)
            {
                StringFormatMethod = ValueType.GetMembers <ExternMethodSymbol>("Format", context).First(e =>
                                                                                                        e.Parameters[0].Type == ValueType && e.Parameters[1].Type == ObjectArr);
            }
            else
            {
                StringFormatMethod = ValueType.GetMembers <ExternMethodSymbol>("Format", context).First(e =>
                                                                                                        e.Parameters[0].Type == ValueType && e.Parameters.Length == interpolatedExpressions.Length + 1);
            }
        }
Beispiel #5
0
        public override BoundNode VisitArrayCreationExpression(ArrayCreationExpressionSyntax node)
        {
            if (node.Type.RankSpecifiers[0].Sizes.Count != 1)
            {
                throw new NotSupportedException(
                          "Multidimensional arrays are not yet supported by UdonSharp, consider using jagged arrays instead.",
                          node.GetLocation());
            }

            // Almost certainly needs to be revisited for jagged arrays
            TypeSymbol arrayType = GetTypeSymbol(node.Type);

            BoundExpression[] elementCounts = new BoundExpression[1];
            var initializerExpressions      = node.Initializer?.Expressions ?? new SeparatedSyntaxList <ExpressionSyntax>();

            if (node.Type.RankSpecifiers[0].Sizes[0] is OmittedArraySizeExpressionSyntax)
            {
                elementCounts[0] = new BoundConstantExpression(new ConstantValue <int>(initializerExpressions.Count), Context.GetTypeSymbol(SpecialType.System_Int32), node);
            }
            else
            {
                elementCounts[0] = VisitExpression(node.Type.RankSpecifiers[0].Sizes[0], Context.GetTypeSymbol(SpecialType.System_Int32));
            }

            BoundExpression[] initializers = null;

            if (node.Initializer != null)
            {
                TypeSymbol elementType = arrayType.ElementType;
                initializers = new BoundExpression[initializerExpressions.Count];

                for (int i = 0; i < initializers.Length; ++i)
                {
                    initializers[i] = VisitExpression(initializerExpressions[i], elementType);
                }
            }

            return(new BoundArrayCreationExpression(node, Context, arrayType, elementCounts, initializers));
        }
Beispiel #6
0
        public override BoundNode VisitInvocationExpression(InvocationExpressionSyntax node)
        {
            MethodSymbol methodSymbol = (MethodSymbol)GetSymbol(node);

            // Check if the symbol is null because you can technically have methods named nameof since it is not reserved
            if (methodSymbol == null &&
                node.Expression is IdentifierNameSyntax nameSyntax &&
                nameSyntax.Identifier.Text == "nameof")
            {
                return(HandleNameOfExpression(node));
            }

            BoundExpression instanceExpression = null;

            if (node.Expression is MemberAccessExpressionSyntax accessExpressionSyntax)
            {
                instanceExpression = VisitExpression(accessExpressionSyntax.Expression);
            }

            // Implicit this on member functions for this behaviour
            if (instanceExpression == null &&
                !methodSymbol.IsStatic &&
                methodSymbol.IsExtern)
            {
                instanceExpression = BoundAccessExpression.BindThisAccess(OwningSymbol.ContainingType);
            }

            BoundExpression[] boundArguments = new BoundExpression[methodSymbol.Parameters.Length];
            var argumentsList = node.ArgumentList.Arguments;

            int startIdx = 0;

            if (instanceExpression != null && methodSymbol.RoslynSymbol.IsExtensionMethod)
            {
                boundArguments[0]  = instanceExpression;
                instanceExpression = null;
                startIdx           = 1;
            }

            bool           hasParams        = false;
            int            handledArgsCount = startIdx;
            ArgumentSyntax paramsNamedArg   = null;

            for (int i = startIdx; i < boundArguments.Length; ++i)
            {
                if (methodSymbol.Parameters[i].IsParams)
                {
                    hasParams      = true;
                    paramsNamedArg = argumentsList.FirstOrDefault(x => x.NameColon?.Name.Identifier.ValueText == methodSymbol.Parameters[i].Name);

                    break;
                }

                ArgumentSyntax argument;

                if (i - startIdx >= argumentsList.Count)
                {
                    argument = null;
                }
                else if (argumentsList[i - startIdx].NameColon != null)
                {
                    argument = argumentsList.FirstOrDefault(x => x.NameColon?.Name.Identifier.ValueText == methodSymbol.Parameters[i].Name);
                }
                else
                {
                    argument = argumentsList[i - startIdx];
                }

                if (argument == null) // Default argument handling
                {
                    boundArguments[i] = new BoundConstantExpression(methodSymbol.Parameters[i].DefaultValue, methodSymbol.Parameters[i].Type, node);
                    continue;
                }

                boundArguments[i] = VisitExpression(argument.Expression, methodSymbol.Parameters[i].Type);
                handledArgsCount++;
            }

            if (hasParams)
            {
                int paramCount;

                BoundExpression[] paramExpressions;

                if (paramsNamedArg != null)
                {
                    paramCount       = 1;
                    paramExpressions = new BoundExpression[paramCount];

                    paramExpressions[0] = VisitExpression(paramsNamedArg.Expression);
                }
                else
                {
                    paramCount       = argumentsList.Count - handledArgsCount;
                    paramExpressions = new BoundExpression[paramCount];

                    int idx = 0;
                    for (int i = handledArgsCount; i < argumentsList.Count; ++i)
                    {
                        paramExpressions[idx++] = VisitExpression(argumentsList[i].Expression);
                    }
                }

                void SetParamsArray()
                {
                    TypeSymbol paramType = methodSymbol.Parameters.Last().Type;

                    boundArguments[boundArguments.Length - 1] = new BoundConstArrayCreationExpression(node, paramType,
                                                                                                      paramExpressions.Select(e => ConvertExpression(node, e, paramType.ElementType)).ToArray());
                }

                void SetDirectParam()
                {
                    boundArguments[boundArguments.Length - 1] = paramExpressions[0];
                }

                if (paramCount != 1)
                {
                    SetParamsArray();
                }
                else if (paramExpressions[0].ValueType == methodSymbol.Parameters.Last().Type)
                {
                    SetDirectParam();
                }
                else
                {
                    Conversion conversion = Context.CompileContext.RoslynCompilation.ClassifyConversion(paramExpressions[0].ValueType.RoslynSymbol, methodSymbol.Parameters.Last().Type.RoslynSymbol);

                    if (conversion.IsImplicit) // Covariant array param conversion
                    {
                        SetDirectParam();
                    }
                    else
                    {
                        SetParamsArray();
                    }
                }
            }

            var invocation = BoundInvocationExpression.CreateBoundInvocation(Context, node, methodSymbol, instanceExpression, boundArguments);

            if ((instanceExpression == null || instanceExpression.IsThis) && node.Expression is MemberAccessExpressionSyntax accessExpressionSyntax2 &&
                accessExpressionSyntax2.Expression.Kind() == SyntaxKind.BaseExpression)
            {
                invocation.MarkForcedBaseCall();
            }

            return(invocation);
        }