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