public function createProperties(TES4VariableDeclarationList $variableList, TES5GlobalScope $globalScope)
 {
     /**
      * @var TES4VariableDeclaration[] $alreadyDefinedVariables
      */
     $alreadyDefinedVariables = [];
     foreach ($variableList->getVariableList() as $variable) {
         $theVariableName = strtolower($variable->getVariableName());
         if (isset($alreadyDefinedVariables[$theVariableName])) {
             if ($variable->getVariableType() == $alreadyDefinedVariables[$theVariableName]->getVariableType()) {
                 continue;
                 //Same variable defined twice, smack the original script developer and fallthrough silently.
             }
             throw new ConversionException("Double definition of variable named " . $variable->getVariableName() . " with different types ( " . $alreadyDefinedVariables[$theVariableName]->getVariableType()->value() . " and " . $variable->getVariableType()->value() . " )");
         }
         switch ($variable->getVariableType()) {
             case TES4Type::T_FLOAT():
                 $property = new TES5Property($variable->getVariableName(), TES5BasicType::T_FLOAT(), null);
                 break;
             case TES4Type::T_INT():
             case TES4Type::T_SHORT():
             case TES4Type::T_LONG():
                 $property = new TES5Property($variable->getVariableName(), TES5BasicType::T_INT(), null);
                 break;
             case TES4Type::T_REF():
                 $property = $this->createPropertyFromReference($variable);
                 break;
             default:
                 throw new ConversionException("Unknown variable declaration type.");
         }
         $globalScope->add($property);
         $alreadyDefinedVariables[$theVariableName] = $variable;
     }
 }
 public function output()
 {
     $output = [];
     $output = array_merge($output, $this->scriptHeader->output());
     $output = array_merge($output, $this->propertyList->output());
     $output = array_merge($output, $this->blockList->output());
     return implode(PHP_EOL, $output);
 }
 public function createGlobalScopes()
 {
     $globalScopes = [];
     $globalScope = new TES5GlobalScope(new TES5ScriptHeader("TES4TimerHelper", "TES4TimerHelper", TES5BasicType::T_QUEST(), ""));
     $globalScopes[] = $globalScope;
     $globalScope = new TES5GlobalScope(new TES5ScriptHeader("TES4Container", "TES4Container", TES5BasicType::T_QUEST(), ""));
     $globalScope->add(new TES5Property("isInJail", TES5BasicType::T_BOOL(), "isInJail"));
     $globalScope->add(new TES5Property("isMurderer", TES5BasicType::T_BOOL(), "isMurderer"));
     $globalScopes[] = $globalScope;
     return $globalScopes;
 }
 /**
  * @param string $scriptName
  * @param TES4VariableDeclarationList $variableList
  * @param TES4CodeChunks $script
  * @return TES5Script
  * @throws ConversionException
  */
 public function convert($scriptName, TES4VariableDeclarationList $variableList, TES4CodeChunks $script)
 {
     //Create the header.
     $scriptHeader = new TES5ScriptHeader($this->nameTransformer->transform($scriptName, ''), $scriptName, TES5BasicType::T_TOPICINFO(), '', true);
     $globalScope = new TES5GlobalScope($scriptHeader);
     foreach ($this->esmAnalyzer->getGlobalVariables() as $globalVariable) {
         $globalScope->addGlobalVariable($globalVariable);
     }
     if ($variableList !== null) {
         //Converting the variables to the properties.
         $this->propertiesFactory->createProperties($variableList, $globalScope);
     }
     $fragment = $this->fragmentFactory->createFragment(TES5FragmentType::T_TIF(), "Fragment_0", $globalScope, new TES5MultipleScriptsScope([$globalScope]), $script);
     $blockList = new TES5BlockList();
     $blockList->add($fragment);
     return new TES5Script($scriptHeader, $globalScope, $blockList);
 }
 public function createReferenceToSelf(TES5GlobalScope $globalScope)
 {
     //todo perhaps move tes5scriptAsVariable to a new factory
     return new TES5SelfReference(new TES5ScriptAsVariable($globalScope->getScriptHeader()));
 }
 /**
  * Extracts implicit reference from calls.
  * Returns a reference from calls like:
  * Enable
  * Disable
  * Activate
  * GetInFaction whatsoever
  * @param TES5GlobalScope $globalScope
  * @param TES5MultipleScriptsScope $multipleScriptsScope
  * @param TES5LocalScope $localScope
  * @return TES5Referencer
  * @throws \Ormin\OBSLexicalParser\TES5\Exception\ConversionException
  */
 private function extractImplicitReference(TES5GlobalScope $globalScope, TES5MultipleScriptsScope $multipleScriptsScope, TES5LocalScope $localScope)
 {
     switch ($globalScope->getScriptHeader()->getBasicScriptType()) {
         case TES5BasicType::T_OBJECTREFERENCE():
             return $this->referenceFactory->createReferenceToSelf($globalScope);
         case TES5BasicType::T_ACTIVEMAGICEFFECT():
             $self = $this->referenceFactory->createReferenceToSelf($globalScope);
             return $this->createObjectCall($self, "GetTargetActor", $multipleScriptsScope);
         case TES5BasicType::T_QUEST():
             //todo - this should not be done like this
             //we should actually not try to extract the implicit reference on the non-reference oblivion functions like "stopQuest"
             //think of this line as a hacky way to just get code forward.
             return $this->referenceFactory->createReferenceToSelf($globalScope);
             /**
              * TIF Fragments
              */
         /**
          * TIF Fragments
          */
         case TES5BasicType::T_TOPICINFO():
             return $this->createReadReference('akSpeakerRef', $globalScope, $multipleScriptsScope, $localScope);
         default:
             throw new ConversionException("Cannot extract implicit reference - unknown basic script type.");
     }
 }
 /**
  * @param TES4ScriptCollection $scripts
  * @return TES5ScriptCollection
  * @throws ConversionException
  */
 public function convert(TES4ScriptCollection $scripts)
 {
     $transpiledCollection = new TES5ScriptCollection();
     $scriptHeaders = [];
     $globalScopes = [];
     /**
      * @var TES4Target $scriptTarget
      */
     foreach ($scripts->getIterator() as $k => $scriptTarget) {
         $script = $scriptTarget->getScript();
         //Create the header.
         $scriptHeader = $this->createHeader($script);
         $variableList = $script->getVariableDeclarationList();
         $globalScope = new TES5GlobalScope($scriptHeader);
         foreach ($this->esmAnalyzer->getGlobalVariables() as $globalVariable) {
             $globalScope->addGlobalVariable($globalVariable);
         }
         if ($variableList !== null) {
             $this->propertiesFactory->createProperties($variableList, $globalScope);
         }
         $scriptHeaders[$k] = $scriptHeader;
         $globalScopes[$k] = $globalScope;
     }
     //Add the static global scopes which are added by complimenting scripts..
     $staticGlobalScopes = $this->staticGlobalScopesFactory->createGlobalScopes();
     foreach ($staticGlobalScopes as $staticGlobalScope) {
         $globalScopes[] = $staticGlobalScope;
     }
     $multipleScriptsScope = new TES5MultipleScriptsScope($globalScopes);
     /**
      * @var TES4Target $scriptTarget
      */
     foreach ($scripts->getIterator() as $k => $scriptTarget) {
         $scriptHeader = $scriptHeaders[$k];
         $globalScope = $globalScopes[$k];
         $script = $scriptTarget->getScript();
         $blockList = new TES5BlockList();
         $parsedBlockList = $script->getBlockList();
         $createdBlocks = [];
         if ($parsedBlockList !== null) {
             foreach ($parsedBlockList->getBlocks() as $block) {
                 $newBlockList = $this->blockFactory->createBlock($multipleScriptsScope, $globalScope, $block);
                 foreach ($newBlockList->getBlocks() as $newBlock) {
                     if (!isset($createdBlocks[$newBlock->getBlockType()])) {
                         $createdBlocks[$newBlock->getBlockType()] = [];
                     }
                     $createdBlocks[$newBlock->getBlockType()][] = $newBlock;
                 }
             }
         }
         //todo encapsulate it to a different class.
         foreach ($createdBlocks as $blockType => $blocks) {
             if (count($blocks) > 1) {
                 /**
                  * @var TES5FunctionCodeBlock[] $functions
                  */
                 $functions = [];
                 $i = 1;
                 $localScopeArguments = null;
                 /**
                  * @var TES5EventCodeBlock $block
                  */
                 foreach ($blocks as $block) {
                     $function = new TES5FunctionCodeBlock($blockType . "_" . $i, null, $block->getLocalScope(), $block->getCodeScope());
                     $functions[] = $function;
                     if ($localScopeArguments === null) {
                         $localScopeArguments = new TES5ObjectCallArguments();
                         foreach ($block->getLocalScope()->getLocalVariables() as $localVariable) {
                             $localScopeArguments->add($this->referenceFactory->createReferenceToVariable($localVariable));
                         }
                     }
                     ++$i;
                 }
                 //Create the proxy block.
                 $proxyBlock = $this->blockFactory->createNewBlock($blockType, clone $block->getLocalScope());
                 foreach ($functions as $function) {
                     $blockList->add($function);
                     $functionCall = $this->valueFactory->createObjectCall($this->referenceFactory->createReferenceToSelf($globalScope), $function->getFunctionName(), $multipleScriptsScope, $localScopeArguments, false);
                     $proxyBlock->addChunk($functionCall);
                 }
                 $blockList->add($proxyBlock);
             } else {
                 $block = current($blocks);
                 $blockList->add($block);
             }
         }
         $tesScript = new TES5Script($scriptHeader, $globalScope, $blockList);
         $transpiledCollection->add($tesScript, $scriptTarget->getOutputPath());
     }
     return $transpiledCollection;
 }