protected static void GetFactories(MetadataLogService metadataLogService, ESMAnalyzer esmAnalyzer, out TES5FragmentFactory fragmentFactory)
        {
            TES5ChainedCodeChunkFactory chainedCodeChunkFactory;

            GetFactories(metadataLogService, esmAnalyzer, out _, out chainedCodeChunkFactory, out _);
            fragmentFactory = new TES5FragmentFactory(chainedCodeChunkFactory);
        }
 public TES4ToTES5ASTQFFragmentConverter(ESMAnalyzer esmAnalyzer, TES5FragmentFactory fragmentFactory, TES5ValueFactory valueFactory, TES5ReferenceFactory referenceFactory)
 {
     this.esmAnalyzer      = esmAnalyzer;
     this.fragmentFactory  = fragmentFactory;
     this.valueFactory     = valueFactory;
     this.referenceFactory = referenceFactory;
 }
 protected static void GetFactories(MetadataLogService metadataLogService, out ESMAnalyzer analyzer, out TES5ReferenceFactory referenceFactory, out TES5ValueFactory valueFactory, out TES5FragmentFactory fragmentFactory)
 {
     TES5ObjectCallFactory objectCallFactory;
     TES5ChainedCodeChunkFactory chainedCodeChunkFactory;
     TES5AdditionalBlockChangesPass additionalBlockChangesPass;
     GetFactories(metadataLogService, out analyzer, out objectCallFactory, out referenceFactory, out valueFactory, out chainedCodeChunkFactory, out additionalBlockChangesPass);
     fragmentFactory = new TES5FragmentFactory(chainedCodeChunkFactory, additionalBlockChangesPass);
 }
        public static void GenerateINFOAddTopicScripts(ESMAnalyzer esmAnalyzer, BuildTracker buildTracker, IBuildTarget tifBuildTarget)
        {
            TES5TypeInferencer    typeInferencer    = new TES5TypeInferencer(esmAnalyzer);
            TES5ObjectCallFactory objectCallFactory = new TES5ObjectCallFactory(typeInferencer);
            TES4TopicsToTES5GlobalVariableFinder globalVariableFinder = new TES4TopicsToTES5GlobalVariableFinder();
            TES5GlobalVariables globalVariables = esmAnalyzer.GlobalVariables;
            var builtTIFs = buildTracker.GetBuiltScripts(BuildTargetFactory.TIFName);

            foreach (TES4Record infoRecord in esmAnalyzer.GetRecords().Where(r => r.RecordType == TES4RecordType.INFO))
            {
                TES4SubrecordData[] names = infoRecord.GetSubrecords("NAME").ToArray();
                if (names.Any())
                {
                    string                fragment0Name     = TES5FragmentFactory.GetFragmentName(0);
                    string                nameTES5FormIDHex = (infoRecord.FormID + 0x01000000).ToString("x8");
                    string                scriptName        = TES5ReferenceFactory.tif_Prefix + "_" + nameTES5FormIDHex;
                    TES5Script?           infoTIF           = builtTIFs.Where(s => s.Key == scriptName).Select(s => s.Value.Script).FirstOrDefault();
                    TES5FunctionCodeBlock fragment0;
                    if (infoTIF != null)
                    {
                        fragment0 = infoTIF.BlockList.Blocks.OfType <TES5FunctionCodeBlock>().Where(b => b.BlockName == fragment0Name).First();
                    }
                    else
                    {
                        TES5ScriptHeader  scriptHeader  = TES5ScriptHeaderFactory.GetFromCacheOrConstructByBasicType(scriptName, TES5BasicType.T_TOPICINFO, TES5TypeFactory.TES4_Prefix, true);
                        TES5GlobalScope   globalScope   = new TES5GlobalScope(scriptHeader);
                        TES5FunctionScope functionScope = new TES5FunctionScope(fragment0Name);
                        functionScope.AddParameter(new TES5SignatureParameter("akSpeakerRef", TES5BasicType.T_OBJECTREFERENCE, true));
                        TES5LocalScope localScope = new TES5LocalScope(functionScope);
                        TES5CodeScope  codeScope  = TES5CodeScopeFactory.CreateCodeScope(localScope);
                        fragment0 = new TES5FunctionCodeBlock(functionScope, codeScope, TES5VoidType.Instance, false, true);
                        TES5BlockList blockList = new TES5BlockList()
                        {
                            fragment0
                        };
                        infoTIF = new TES5Script(globalScope, blockList, true);
                        string     outputPath = tifBuildTarget.GetTranspileToPath(scriptName);
                        TES5Target target     = new TES5Target(infoTIF, outputPath);
                        buildTracker.RegisterBuiltScript(tifBuildTarget, target);
                    }
                    foreach (TES4SubrecordData name in names)
                    {
                        int                 formID                   = infoRecord.ExpandBytesIntoFormID(name);
                        TES4Record          addedTopic               = esmAnalyzer.GetRecordByFormID(formID);
                        Tuple <int, string>?globalVariable           = globalVariableFinder.GetGlobalVariableNullable(addedTopic.FormID);
                        string              globalVariableEditorID   = globalVariable != null ? globalVariable.Item2 : globalVariableFinder.GetGlobalVariableEditorID(addedTopic.GetEditorID());
                        Nullable <int>      globalVariableTES5FormID = globalVariable != null ? globalVariable.Item1 : (Nullable <int>)null;
                        TES5Property        topicAddedProperty       = TES5PropertyFactory.ConstructWithTES5FormID(globalVariableEditorID, TES5BasicType.T_GLOBALVARIABLE, globalVariableEditorID, globalVariableTES5FormID);
                        infoTIF.GlobalScope.AddPropertyIfNotExists(topicAddedProperty);
                        TES5Reference topicAddedReference = TES5ReferenceFactory.CreateReferenceToVariableOrProperty(topicAddedProperty);
                        fragment0.AddChunk(objectCallFactory.CreateObjectCall(topicAddedReference, "SetValueInt", new TES5ObjectCallArguments()
                        {
                            new TES5Integer(1)
                        }));
                    }
                }
            }
        }
        /*
         *  The stage ID
         *  List of integers describing targets being enabled or disabled for given stage
         */
        public TES5FunctionCodeBlock CreateEnclosedFragment(TES5GlobalScope globalScope, int stageId, List <int> stageMap)
        {
            string                fragmentName  = TES5FragmentFactory.GetFragmentName(stageId);
            TES5FunctionScope     functionScope = TES5FragmentFunctionScopeFactory.CreateFromFragmentType(fragmentName, TES5FragmentType.T_QF);
            TES5CodeScope         codeScope     = TES5CodeScopeFactory.CreateCodeScopeRoot(functionScope);
            TES5FunctionCodeBlock codeBlock     = new TES5FunctionCodeBlock(functionScope, codeScope, TES5VoidType.Instance, false, true);
            List <ITES5CodeChunk> chunks        = GenerateObjectiveHandling(codeBlock, globalScope, stageMap);

            foreach (var chunk in chunks)
            {
                codeBlock.AddChunk(chunk);
            }
            return(codeBlock);
        }
        public static BuildTargetAdvanced ConstructAdvanced(BuildTargetSimple buildTarget, BuildLogServiceCollection buildLogServices, ESMAnalyzer esmAnalyzer, TES5TypeInferencer typeInferencer)
        {
            switch (buildTarget.Name)
            {
            case StandaloneName:
            {
                StandaloneParsingService standaloneParsingService = new StandaloneParsingService(new SyntaxErrorCleanParser(new TES4OBScriptGrammar()));
                return(new BuildTargetAdvanced(buildTarget, new Standalone.TranspileCommand(standaloneParsingService, buildLogServices.MetadataLogService, esmAnalyzer), new Standalone.BuildScopeCommand(standaloneParsingService, esmAnalyzer, new TES5PropertyFactory(esmAnalyzer)), new Standalone.WriteCommand()));
            }

            case TIFName:
            {
                FragmentsParsingService fragmentsParsingService = new FragmentsParsingService(new SyntaxErrorCleanParser(new TES4ObscriptCodeGrammar()));
                return(new BuildTargetAdvanced(buildTarget, new TIF.TranspileCommand(fragmentsParsingService, buildLogServices.MetadataLogService, esmAnalyzer), new TIF.BuildScopeCommand(new TES5PropertyFactory(esmAnalyzer), new FragmentsReferencesBuilder(esmAnalyzer)), new TIF.WriteCommand()));
            }

            case PFName:
            {
                return(new BuildTargetAdvanced(buildTarget, new PF.TranspileCommand(), new PF.BuildScopeCommand(), new PF.WriteCommand()));
            }

            case QFName:
            {
                FragmentsParsingService        fragmentsParsingService    = new FragmentsParsingService(new SyntaxErrorCleanParser(new TES4ObscriptCodeGrammar()));
                TES5ObjectCallFactory          objectCallFactory          = new TES5ObjectCallFactory(typeInferencer);
                TES5ObjectPropertyFactory      objectPropertyFactory      = new TES5ObjectPropertyFactory(typeInferencer);
                TES5ReferenceFactory           referenceFactory           = new TES5ReferenceFactory(objectCallFactory, objectPropertyFactory, esmAnalyzer);
                TES5ValueFactory               valueFactory               = new TES5ValueFactory(objectCallFactory, referenceFactory, esmAnalyzer);
                TES5ObjectCallArgumentsFactory objectCallArgumentsFactory = new TES5ObjectCallArgumentsFactory(valueFactory);
                TES5ValueFactoryFunctionFiller.FillFunctions(valueFactory, objectCallFactory, objectCallArgumentsFactory, referenceFactory, objectPropertyFactory, buildLogServices.MetadataLogService, esmAnalyzer);
                TES5VariableAssignationConversionFactory assignationConversionFactory = new TES5VariableAssignationConversionFactory(objectCallFactory, referenceFactory, valueFactory, typeInferencer);
                TES5ReturnFactory           returnFactory            = new TES5ReturnFactory(objectCallFactory);
                TES5ChainedCodeChunkFactory chainedCodeChunkFactory  = new TES5ChainedCodeChunkFactory(valueFactory, returnFactory, assignationConversionFactory);
                TES5FragmentFactory         fragmentFactory          = new TES5FragmentFactory(chainedCodeChunkFactory);
                ObjectiveHandlingFactory    objectiveHandlingFactory = new ObjectiveHandlingFactory(objectCallFactory);
                QFFragmentFactory           qfFragmentFactory        = new QFFragmentFactory(buildLogServices.MappedTargetsLogService, objectiveHandlingFactory, esmAnalyzer);
                QF.WriteCommand             writeCommand             = new QF.WriteCommand(qfFragmentFactory);
                return(new BuildTargetAdvanced(buildTarget, new QF.TranspileCommand(fragmentsParsingService, fragmentFactory), new QF.BuildScopeCommand(new TES5PropertyFactory(esmAnalyzer), new FragmentsReferencesBuilder(esmAnalyzer)), writeCommand));
            }

            default:
            {
                throw new InvalidOperationException("Unknown target " + buildTarget.Name);
            }
            }
        }
Ejemplo n.º 7
0
 public TES4ToTES5ASTQFFragmentConverter(TES5FragmentFactory fragmentFactory)
 {
     this.fragmentFactory = fragmentFactory;
 }
Ejemplo n.º 8
0
        /*
         * Joins N QF subfragments into one QF fragment that can be properly binded into Skyrim VM
         * @throws ConversionException
         */
        public TES5Target JoinQFFragments(IBuildTarget target, string resultingFragmentName, List <QuestStageScript> subfragmentsTrees)
        {
            int      tes4FormID = GetTES4FormID(resultingFragmentName);
            StageMap stageMap   = StageMapBuilder.Build(target, resultingFragmentName, esmAnalyzer, tes4FormID);

            /*
             * We need script fragment for objective handling for each stage, so when parsing the script fragments,
             * we"ll be marking them there, and intersecting this with stage.
             * This will give us an array of stages which don"t have script fragment, but will need it anyways
             * for objective handling.
             */
            TES5ScriptHeader resultingScriptHeader = TES5ScriptHeaderFactory.GetFromCacheOrConstructByBasicType(resultingFragmentName, TES5BasicType.T_QUEST, TES5TypeFactory.TES4_Prefix, true);
            TES5GlobalScope  resultingGlobalScope  = new TES5GlobalScope(resultingScriptHeader);

            string[] referenceAliases = ReferenceAliasBuilder.Build(target, resultingFragmentName, esmAnalyzer, tes4FormID).ToArray();
            foreach (string propertyName in referenceAliases)
            {
                resultingGlobalScope.AddProperty(TES5PropertyFactory.ConstructWithoutFormID(propertyName, TES5BasicType.T_REFERENCEALIAS, propertyName));
            }

            List <QuestStageBlock> questStageBlocks        = new List <QuestStageBlock>();
            HashSet <int>          implementedStages       = new HashSet <int>();
            HashSet <string>       propertiesNamesDeclared = new HashSet <string>();

            foreach (var subfragment in subfragmentsTrees)
            {
                TES5Target      subfragmentsTree       = subfragment.Script;
                TES5Script      subfragmentScript      = subfragmentsTree.Script;
                TES5GlobalScope subfragmentGlobalScope = subfragmentScript.GlobalScope;
                foreach (TES5Property subfragmentProperty in subfragmentGlobalScope.Properties)
                {
                    /*
                     * Move over the properties to the new global scope
                     */
                    if (propertiesNamesDeclared.Add(subfragmentProperty.Name))
                    {
                        resultingGlobalScope.AddProperty(subfragmentProperty);
                    }
                    else
                    {
                        if (subfragmentProperty.IsPlayerRef)
                        {
                            continue;
                        }
                        //WTM:  Change:  I don't think renaming these properties actually helps anything.

                        /*
                         * string propertyName = GeneratePropertyName(subfragmentScript.ScriptHeader, subfragmentProperty);
                         * subfragmentProperty.Rename(propertyName);
                         * if (!propertiesNamesDeclared.Add(subfragmentProperty.Name))
                         * {
                         *  throw new ConversionException(nameof(propertiesNamesDeclared) + " already contained property " + subfragmentProperty.Name + ".");
                         * }
                         */
                        //WTM:  Change:  I'm trying to unify properties and include extended type declarations.
                        TES5Property existingProperty = resultingGlobalScope.GetPropertyByName(subfragmentProperty.Name);
                        if (TES5InheritanceGraphAnalyzer.IsTypeOrExtendsType(existingProperty.TES5Type, subfragmentProperty.TES5Type))
                        {
                            continue;
                        }
                        if (TES5InheritanceGraphAnalyzer.IsExtending(subfragmentProperty.TES5Type, existingProperty.TES5Type))
                        {
                            existingProperty.TES5Type = subfragmentProperty.TES5Type;
                            continue;
                        }
                        if (TES5InheritanceGraphAnalyzer.IsExtending(existingProperty.TES5Type, subfragmentProperty.TES5Type.NativeType))
                        {
                            subfragmentProperty.TES5Type.NativeType = existingProperty.TES5Type.NativeType;
                            existingProperty.TES5Type = subfragmentProperty.TES5Type;
                            continue;
                        }
                        throw new ConversionException("Types were not compatible for property " + subfragmentProperty.Name + ":  " + subfragmentProperty.TES5Type.Value + " should extend " + existingProperty.TES5Type.Value + " (" + existingProperty.TES5Type.NativeType.Value + ").");
                    }
                }

                List <ITES5CodeBlock> subfragmentBlocks = subfragmentScript.BlockList.Blocks;
                if (subfragmentBlocks.Count != 1)
                {
                    throw new ConversionException("Wrong QF fragment, actual function count: " + subfragmentBlocks.Count + "..");
                }

                ITES5CodeBlock subfragmentBlock = subfragmentBlocks[0];
                if (subfragmentBlock.FunctionScope.BlockName != TES5FragmentFactory.GetFragmentName(0))
                {
                    throw new ConversionException("Wrong QF fragment funcname, actual function name: " + subfragmentBlock.FunctionScope.BlockName + ".");
                }

                string newFragmentFunctionName = TES5FragmentFactory.GetFragmentName(subfragment.Stage, subfragment.LogIndex);

                subfragmentBlock.FunctionScope.Rename(newFragmentFunctionName);
                List <int>?stageMapOfStage = stageMap.TryGetStageTargetsMap(subfragment.Stage);
                if (stageMapOfStage != null)
                {
                    var objectiveCodeChunks = objectiveHandlingFactory.GenerateObjectiveHandling(subfragmentBlock, resultingGlobalScope, stageMapOfStage);
                    foreach (var newCodeChunk in objectiveCodeChunks)
                    {
                        subfragmentBlock.AddChunk(newCodeChunk);
                    }
                }

                questStageBlocks.Add(new QuestStageBlock(subfragment.Stage, subfragment.LogIndex, subfragmentBlock));
                implementedStages.Add(subfragment.Stage);
            }

            /*
             * Diff to find stages which we still need to mark
             */
            int[] nonDoneStages = stageMap.StageIDs.Where(stageID => !implementedStages.Contains(stageID)).ToArray();
            foreach (int nonDoneStage in nonDoneStages)
            {
                TES5FunctionCodeBlock fragment = objectiveHandlingFactory.CreateEnclosedFragment(resultingGlobalScope, nonDoneStage, stageMap.GetStageTargetsMap(nonDoneStage));
                questStageBlocks.Add(new QuestStageBlock(nonDoneStage, 0, fragment));
            }

            this.mappedTargetsLogService.WriteScriptName(resultingFragmentName);
            foreach (var kvp in stageMap.MappedTargetsIndex)
            {
                var originalTargetIndex = kvp.Key;
                var mappedTargetIndexes = kvp.Value;
                this.mappedTargetsLogService.WriteLine(originalTargetIndex, mappedTargetIndexes);
            }

            TES5BlockList resultingBlockList = new TES5BlockList(questStageBlocks.OrderBy(b => b.StageID).ThenBy(b => b.LogIndex).Select(b => b.CodeBlock));
            TES5Script    resultingTree      = new TES5Script(resultingGlobalScope, resultingBlockList, true);
            string        outputPath         = target.GetTranspileToPath(resultingFragmentName);

            return(new TES5Target(resultingTree, outputPath));
        }
 public TranspileCommand(FragmentsParsingService fragmentsParsingService, TES5FragmentFactory fragmentFactory)
     : base(fragmentsParsingService)
 {
     converter = new TES4ToTES5ASTQFFragmentConverter(fragmentFactory);
 }