Exemple #1
0
        private BoundNode GeneratePropertyAutoGetter(BindContext context, SyntaxNode node)
        {
            FieldSymbol autoField = GetAutoField(context);

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

            return(new BoundReturnStatement(node, BoundAccessExpression.BindAccess(context, node, autoField, null)));
        }
Exemple #2
0
        public Value EmitSet(BoundAccessExpression targetExpression, BoundExpression sourceExpression)
        {
            UpdateNode(targetExpression);

            EnterCowScope();
            Value resultVal = targetExpression.EmitSet(this, sourceExpression);

            ExitCowScope();
            targetExpression.ReleaseCowReferences(this);

            return(resultVal);
        }
Exemple #3
0
        private BoundNode GeneratePropertyAutoSetter(BindContext context, SyntaxNode node)
        {
            FieldSymbol autoField = GetAutoField(context);

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

            return(new BoundAssignmentExpression(node, BoundAccessExpression.BindAccess(context, node, autoField, null),
                                                 BoundAccessExpression.BindAccess(context, node, Parameters[0], null)));
        }
Exemple #4
0
        private void CastValue(Value sourceValue, Value targetValue, bool explicitCast)
        {
            if (targetValue.UserType is TypeParameterSymbol)
            {
                throw new InvalidOperationException("Target cast type cannot be a generic type parameter");
            }

            if (sourceValue == targetValue)
            {
                return;
            }

            // Early out for exact type matches
            if (sourceValue.UserType == targetValue.UserType)
            {
                Module.AddCopy(sourceValue, targetValue);
                return;
            }

            TypeSymbol sourceType = sourceValue.UserType;
            TypeSymbol targetType = targetValue.UserType;

            void ExecuteBoundInvocation(MethodSymbol conversionMethod)
            {
                using (OpenAssignmentScope(targetValue))
                {
                    sourceValue = EmitValue(BoundInvocationExpression.CreateBoundInvocation(this, null, conversionMethod, null,
                                                                                            new BoundExpression[] { BoundAccessExpression.BindAccess(sourceValue) }));
                }

                if (sourceValue != targetValue)
                {
                    Module.AddCopy(sourceValue, targetValue);
                }
            }

            Conversion conversion = CompileContext.RoslynCompilation.ClassifyConversion(sourceType.RoslynSymbol, targetType.RoslynSymbol);

            if (conversion.IsEnumeration)
            {
                // Extern enum -> integer
                if (sourceValue.UdonType.IsEnum &&
                    UdonSharpUtils.IsIntegerType(targetType.UdonType.SystemType))
                {
                    MethodSymbol conversionMethod =
                        GetNumericConversionMethod(GetTypeSymbol(SpecialType.System_Object), targetType);
                    ExecuteBoundInvocation(conversionMethod);
                    return;
                }

                // Integer -> user enum
                // User enum -> user enum
                if (UdonSharpUtils.IsIntegerType(sourceType.UdonType.SystemType) && !targetType.IsExtern && targetType.IsEnum)
                {
                    if (sourceType.UdonType == targetType.UdonType)
                    {
                        Module.AddCopy(sourceValue, targetValue);
                        return;
                    }

                    ExecuteBoundInvocation(GetNumericConversionMethod(sourceType.UdonType, targetType.UdonType));
                    return;
                }

                // integer -> extern enum
                if (UdonSharpUtils.IsIntegerType(sourceType.UdonType.SystemType) &&
                    targetType.UdonType.IsEnum)
                {
                    Value enumArray = GetEnumArrayForType(targetType.UdonType.SystemType);

                    Value indexValue         = CastValue(sourceValue, GetTypeSymbol(SpecialType.System_Int32), true);
                    var   boundElementAccess = BoundAccessExpression.BindElementAccess(this, null, BoundAccessExpression.BindAccess(enumArray),
                                                                                       new BoundExpression[]
                    {
                        BoundAccessExpression.BindAccess(indexValue),
                    });

                    Value enumVal = EmitValue(boundElementAccess);

                    // todo: get rid of the copy again
                    Module.AddCopy(enumVal, targetValue);
                    return;
                }
            }

            if (conversion.IsNumeric ||
                (UdonSharpUtils.IsNumericType(targetType.UdonType.SystemType) && sourceType == GetTypeSymbol(SpecialType.System_Object)))
            {
                MethodSymbol conversionMethod = GetNumericConversionMethod(sourceType, targetType);

                if (conversionMethod != null)
                {
                    using (InterruptAssignmentScope())
                    {
                        // Float to int truncation handling since System.Convert rounds
                        if (UdonSharpUtils.IsFloatType(sourceType.UdonType.SystemType) &&
                            UdonSharpUtils.IsIntegerType(targetType.UdonType.SystemType))
                        {
                            TypeSymbol floatType = GetTypeSymbol(SpecialType.System_Single);
                            sourceValue = CastValue(sourceValue, floatType, true);

                            if (_mathfFloorMethodSymbol == null)
                            {
                                _mathfFloorMethodSymbol =
                                    GetTypeSymbol(typeof(Mathf)).GetMember <MethodSymbol>("Floor", this);
                            }

                            sourceValue = EmitValue(BoundInvocationExpression.CreateBoundInvocation(this, null, _mathfFloorMethodSymbol,
                                                                                                    null,
                                                                                                    new BoundExpression[] { BoundAccessExpression.BindAccess(sourceValue) }));

                            conversionMethod = GetNumericConversionMethod(floatType, targetType);
                        }
                    }

                    ExecuteBoundInvocation(conversionMethod);
                    return;
                }
            }

            if (conversion.IsUserDefined && conversion.MethodSymbol != null)
            {
                MethodSymbol conversionMethod = (MethodSymbol)GetSymbol(conversion.MethodSymbol);
                ExecuteBoundInvocation(conversionMethod);
                return;
            }

            Module.AddCopy(sourceValue, targetValue);
        }