Exemple #1
0
        public static bool TypeCompatible(VariableType dest, VariableType src, bool coerce = false)
        {
            if (dest is DynamicArrayType destArr && src is DynamicArrayType srcArr)
            {
                return(TypeCompatible(destArr.ElementType, srcArr.ElementType));
            }

            if (dest is ClassType destClassType && src is ClassType srcClassType)
            {
                return(destClassType.ClassLimiter == srcClassType.ClassLimiter || ((Class)srcClassType.ClassLimiter).SameAsOrSubClassOf(destClassType.ClassLimiter.Name));
            }

            if (dest.PropertyType == EPropertyType.Byte && src.PropertyType == EPropertyType.Byte)
            {
                return(true);
            }

            if (dest is DelegateType destDel && src is DelegateType srcDel)
            {
                return(true);
                // this seems like how it ought to be done, but there is bioware code that would have only compiled if all delegates are considered the same type
                // maybe log a warning here instead of an error?
                //return destDel.DefaultFunction.SignatureEquals(srcDel.DefaultFunction);
            }

            if (dest is Class destClass)
            {
                if (src is Class srcClass)
                {
                    bool sameAsOrSubClassOf = srcClass.SameAsOrSubClassOf(destClass.Name);
                    if (srcClass.IsInterface)
                    {
                        return(sameAsOrSubClassOf || destClass.Implements(srcClass));
                    }
                    return(sameAsOrSubClassOf
                           //this seems super wrong obviously. A sane type system would require an explicit downcast.
                           //But to make this work with existing bioware code, it's this, or write a control-flow analyzer that implicitly downcasts based on typecheck conditional gates
                           //I have chosen the lazy path
                           || destClass.SameAsOrSubClassOf(srcClass.Name));
                }

                if (destClass.Name.CaseInsensitiveEquals("Object") && src is ClassType)
                {
                    return(true);
                }
            }

            if (dest.Name.CaseInsensitiveEquals(src?.Name))
            {
                return(true);
            }
            ECast cast = CastHelper.GetConversion(dest, src);

            if (coerce)
            {
                return(cast != ECast.Max);
            }
            return(cast.Has(ECast.AutoConvert));
        }
Exemple #2
0
        public static int ConversionCost(FunctionParameter dest, VariableType src)
        {
            if (dest.VarType == src)
            {
                return(0); //exact match
            }

            if (src?.PropertyType == EPropertyType.Vector && dest.VarType?.PropertyType == EPropertyType.Vector ||
                src?.PropertyType == EPropertyType.Rotator && dest.VarType?.PropertyType == EPropertyType.Rotator)
            {
                return(0);
            }
            if (dest.VarType is Class c && (src is null || src is ClassType && !c.IsInterface))
            {
                return(0);
            }
            if (dest.VarType is DelegateType && src is null)
            {
                return(0);
            }
            if (dest.IsOut)
            {
                return(int.MaxValue);
            }
            if (INTERFACE.CaseInsensitiveEquals(dest.VarType?.Name) && src is Class cls && cls.SameAsOrSubClassOf(INTERFACE))
            {
                return(1); //Interface subclass
            }
            if (!INTERFACE.CaseInsensitiveEquals(dest.VarType?.Name) && dest.VarType is Class && src is Class)
            {
                return(2);
            }
            ECast conversion = GetConversion(dest.VarType, src);

            //if it has 'coerce', any valid conversion is acceptable, otherwise only autoconversions are acceptable
            if (dest.Flags.Has(UnrealFlags.EPropertyFlags.CoerceParm) ? conversion != ECast.Max : conversion.Has(ECast.AutoConvert))
            {
                if (conversion.Has(ECast.Truncate))
                {
                    return(104); //lossy conversion
                }

                if (dest.VarType == SymbolTable.FloatType && (src == SymbolTable.IntType || src?.PropertyType == EPropertyType.Byte))
                {
                    return(103); //int to float conversion
                }

                return(101); //lossless conversion
            }

            return(int.MaxValue);
        }