Example #1
0
        private void InferenceTypeOfMethodArguments(TES5ObjectCall objectCall, TES5MultipleScriptsScope multipleScriptsScope)
        {
            /*
             * Inference the arguments
             */
            int       argumentIndex = 0;
            ITES5Type calledOnType  = objectCall.AccessedObject.TES5Type.NativeType;

            foreach (ITES5Value argument in objectCall.Arguments)
            {
                /*
                 * Get the argument type according to TES5Inheritance graph.
                 */
                ITES5Type argumentTargetType = TES5InheritanceGraphAnalyzer.FindTypeByMethodParameter(calledOnType, objectCall.FunctionName, argumentIndex);
                if (argument.TES5Type != argumentTargetType)
                {
                    /*
                     * todo - maybe we should move getReferencesTo() to TES5Value and make all of the rest TES5Values just have null references as they do not reference anything? :)
                     */
                    ITES5Referencer referencerArgument = argument as ITES5Referencer;
                    if (referencerArgument != null && TES5InheritanceGraphAnalyzer.IsExtending(argumentTargetType, argument.TES5Type.NativeType))
                    { //HACKY!
                        this.InferenceType(referencerArgument.ReferencesTo, argumentTargetType, multipleScriptsScope);
                    }
                    else
                    {
                        //So there"s one , one special case where we actually have to cast a var from one to another even though they are not ,,inheriting" from themselves, because they are primitives.
                        //Scenario: there"s an T_INT argument, and we feed it with a T_FLOAT variable reference. It won"t work :(
                        //We need to cast it on call level ( NOT inference it ) to make it work and not break other possible scenarios ( more specifically, when a float would be inferenced to int and there"s a
                        //float assigment somewhere in the code )
                        if (argumentTargetType == TES5BasicType.T_INT && argument.TES5Type == TES5BasicType.T_FLOAT)
                        {
                            TES5Castable argumentCastable = argument as TES5Castable;
                            if (argumentCastable != null)
                            { //HACKY! When we"ll clean up this interface, it will dissapear :)
                                argumentCastable.ManualCastTo = argumentTargetType;
                            }
                        }
                        else if (
                            !TES5InheritanceGraphAnalyzer.IsExtending(argument.TES5Type, argumentTargetType) &&
                            !TES5InheritanceGraphAnalyzer.IsNumberTypeOrBoolAndInt(argument.TES5Type, argumentTargetType) &&
                            !(argument is TES5None && TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(argumentTargetType, (new TES5None()).TES5Type)))
                        {
                            bool expected = objectCall.AccessedObject.TES5Type.OriginalName == "TES4TimerHelper" && objectCall.FunctionName == "LegacySay";
                            throw new ConversionException("Argument type mismatch at " + objectCall.FunctionName + " index " + argumentIndex + ".  Expected " + argumentTargetType.OriginalName + ".  Found " + argument.TES5Type.OriginalName + ".", expected: expected);
                        }
                    }
                }
                argumentIndex++;
            }
        }
Example #2
0
        public ITES5ValueCodeChunk ConvertFunction(ITES5Referencer calledOn, TES4Function function, TES5CodeScope codeScope, TES5GlobalScope globalScope, TES5MultipleScriptsScope multipleScriptsScope)
        {
            TES4FunctionArguments   functionArguments = function.Arguments;
            TES5LocalScope          localScope        = codeScope.LocalScope;
            TES5ObjectCallArguments arguments         = new TES5ObjectCallArguments()
            {
                calledOn
            };
            ITES5Value argument1 = this.valueFactory.CreateValue(functionArguments[0], codeScope, globalScope, multipleScriptsScope);

            if (argument1.TES5Type != TES5BasicType.T_TOPIC)
            {
                TES5Castable argument1Castable = argument1 as TES5Reference;
                if (argument1Castable != null && TES5InheritanceGraphAnalyzer.IsExtending(TES5BasicType.T_TOPIC, argument1.TES5Type))
                {
                    argument1Castable.ManualCastTo = TES5BasicType.T_TOPIC;
                }
            }
            arguments.Add(argument1);
            ITES4StringValue optionalFlag = functionArguments.GetOrNull(2);

            if (optionalFlag != null)
            {
                string optionalFlagDataString = optionalFlag.StringValue;
                if (this.analyzer.GetFormTypeByEDID(optionalFlagDataString).Value != TES4RecordType.REFR.Name)
                {
                    this.metadataLogService.WriteLine("ADD_SPEAK_AS_ACTOR", new string[] { optionalFlagDataString });
                    optionalFlag = new TES4ApiToken(optionalFlag.Data + "Ref");
                }

                arguments.Add(this.valueFactory.CreateValue(optionalFlag, codeScope, globalScope, multipleScriptsScope));
            }
            else
            {
                arguments.Add(new TES5None());
            }

            arguments.Add(new TES5Bool(true));
            ITES5Referencer timerReference = this.referenceFactory.CreateTimerReadReference(globalScope, multipleScriptsScope, localScope);

            return(this.objectCallFactory.CreateObjectCall(timerReference, "LegacySay", multipleScriptsScope, arguments));
        }