gt:         if (obj == null) {
context: /*
   *  Copyright (C) 2010-2021 JPEXS, All rights reserved.
   * 
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 3.0 of the License, or (at your option) any later version.
   * 
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   * 
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library.
   */
  package com.jpexs.decompiler.flash.abc.avm2.parser.script;
  
  import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
  import com.jpexs.decompiler.flash.abc.ABC;
  import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
  import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
  import com.jpexs.decompiler.flash.abc.types.Multiname;
  import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
  import com.jpexs.decompiler.graph.CompilationException;
  import com.jpexs.decompiler.graph.DottedChain;
  import com.jpexs.decompiler.graph.GraphSourceItem;
  import com.jpexs.decompiler.graph.GraphTargetItem;
  import com.jpexs.decompiler.graph.SourceGenerator;
  import com.jpexs.decompiler.graph.TypeItem;
  import com.jpexs.decompiler.graph.model.LocalData;
  import com.jpexs.helpers.Reference;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;
  import java.util.Objects;
  
  /**
   *
   * @author JPEXS
   */
  public class NamespacedAVM2Item extends AssignableAVM2Item {
  
      public GraphTargetItem ns;
  
      public String name;
  
      public GraphTargetItem nameItem;
  
      public GraphTargetItem obj;
  
      public boolean attr;
  
      public List<NamespaceItem> openedNamespaces;
  
      public NamespacedAVM2Item(GraphTargetItem ns, String name, GraphTargetItem nameItem, GraphTargetItem obj, boolean attr, List<NamespaceItem> openedNamespaces, GraphTargetItem storeValue) {
          super(storeValue);
          this.ns = ns;
          this.nameItem = nameItem;
          this.name = name;
          this.obj = obj;
          this.attr = attr;
          this.openedNamespaces = openedNamespaces;
      }
  
      private int allNsSet(AbcIndexing abc) throws CompilationException {
          int[] nssa = new int[openedNamespaces.size()];
          for (int i = 0; i < nssa.length; i++) {
              nssa[i] = openedNamespaces.get(i).getCpoolIndex(abc);
          }
          return abc.getSelectedAbc().constants.getNamespaceSetId(nssa, true);
      }
  
      @Override
      public AssignableAVM2Item copy() {
          return new NamespacedAVM2Item(ns, name, nameItem, obj, attr, openedNamespaces, assignedValue);
      }
  
      @Override
      public List<GraphSourceItem> toSourceChange(SourceGeneratorLocalData localData, SourceGenerator generator, boolean post, boolean decrement, boolean needsReturn) throws CompilationException {
          AVM2SourceGenerator g = (AVM2SourceGenerator) generator;
          boolean isInteger = returnType().toString().equals("int");
          Reference<Integer> ns_temp = new Reference<>(-1);
          Reference<Integer> name_temp = new Reference<>(-1);
          Reference<Integer> ret_temp = new Reference<>(-1);
          /*if (name == null && index != null) {
           return toSourceMerge(localData, generator,
           ns, generateCoerce(generator, new TypeItem("Namespace")), index, ins(AVM2Instructions.ConvertS),
           ins(AVM2Instructions.FindPropertyStrict, g.abc.getLastAbc().constants.getMultinameId(new Multiname(Multiname.RTQNAMEL, 0, 0, 0, 0, new ArrayList<Integer>()), true)),
           dupSetTemp(localData, generator, name_temp),
           ns, generateCoerce(generator, new TypeItem("Namespace")),
           dupSetTemp(localData, generator, ns_temp),
           ins(AVM2Instructions.GetProperty, g.abc.getLastAbc().constants.getMultinameId(new Multiname(Multiname.MULTINAMEL, 0, 0, allNsSet(g.abc), 0, new ArrayList<Integer>()), true)),
           !isInteger ? ins(AVM2Instructions.ConvertD) : null,
           //End get original
           (!post) ? (decrement ? ins(isInteger ? AVM2Instructions.DecrementI : AVM2Instructions.Decrement) : ins(isInteger ? AVM2Instructions.IncrementI : AVM2Instructions.Increment())) : null,
           needsReturn ? ins(AVM2Instructions.Dup) : null,
           (post) ? (decrement ? ins(isInteger ? AVM2Instructions.DecrementI : AVM2Instructions.Decrement) : ins(isInteger ? AVM2Instructions.IncrementI : AVM2Instructions.Increment)) : null,
           setTemp(localData, generator, ret_temp),
           getTemp(localData, generator, name_temp),
           getTemp(localData, generator, ns_temp),
           getTemp(localData, generator, ret_temp),
           ins(AVM2Instructions.SetProperty, g.abc.getLastAbc().constants.getMultinameId(new Multiname(Multiname.MULTINAMEL, 0, 0, allNsSet(g.abc), 0, new ArrayList<Integer>()), true)),
           killTemp(localData, generator, Arrays.asList(ret_temp, name_temp, ns_temp)));
           } else
           */
          ABC abc = g.abcIndex.getSelectedAbc();
          AVM2ConstantPool constants = abc.constants;
          if (name != null) {
              return toSourceMerge(localData, generator,
                      ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)),
                      ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(false, constants.getStringId(name, true)), true)),
                      dupSetTemp(localData, generator, name_temp),
                      ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)),
                      dupSetTemp(localData, generator, ns_temp),
                      //Start get original
                      //getTemp(localData, generator, ns_temp), generateCoerce(generator, "Namespace"), ins(AVM2Instructions.FindPropertyStrict, g.abc.getLastAbc().constants.getMultinameId(new Multiname(Multiname.RTQNAME, g.abc.getLastAbc().constants.getStringId(variableName, true), 0, 0, 0, new ArrayList<Integer>()), true)),
                      //getTemp(localData, generator, ns_temp), generateCoerce(generator, "Namespace"),
                      ins(AVM2Instructions.GetProperty, constants.getMultinameId(Multiname.createMultinameL(false, allNsSet(g.abcIndex)), true)),
                      !isInteger ? ins(AVM2Instructions.ConvertD) : null,
                      //End get original
                      (!post) ? (decrement ? ins(isInteger ? AVM2Instructions.DecrementI : AVM2Instructions.Decrement) : ins(isInteger ? AVM2Instructions.IncrementI : AVM2Instructions.Increment)) : null,
                      needsReturn ? ins(AVM2Instructions.Dup) : null,
                      (post) ? (decrement ? ins(isInteger ? AVM2Instructions.DecrementI : AVM2Instructions.Decrement) : ins(isInteger ? AVM2Instructions.IncrementI : AVM2Instructions.Increment)) : null,
                      setTemp(localData, generator, ret_temp),
                      getTemp(localData, generator, name_temp),
                      getTemp(localData, generator, ns_temp),
                      getTemp(localData, generator, ret_temp),
                      ins(AVM2Instructions.SetProperty, constants.getMultinameId(Multiname.createMultinameL(false, allNsSet(g.abcIndex)), true)),
                      killTemp(localData, generator, Arrays.asList(ret_temp, name_temp, ns_temp))
              );
          } else {
              return new ArrayList<>();
          }
      }
  
      @Override
      public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
          return null;
      }
  
      @Override
      public boolean hasReturnValue() {
          return true;
      }
  
      @Override
      public GraphTargetItem returnType() {
          return TypeItem.UNBOUNDED;
      }
  
      public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator, boolean needsReturn, boolean call, List<GraphTargetItem> callargs, boolean delete, boolean construct) throws CompilationException {
          AVM2SourceGenerator g = (AVM2SourceGenerator) generator;
          Reference<Integer> ns_temp = new Reference<>(-1);
          Reference<Integer> index_temp = new Reference<>(-1);
          Reference<Integer> ret_temp = new Reference<>(-1);
  
          Reference<Integer> obj_temp = new Reference<>(-1);
  
          AVM2ConstantPool constants = g.abcIndex.getSelectedAbc().constants;
          if (name == null) {
              if (assignedValue != null) {
                  return toSourceMerge(localData, generator,
                          obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, nameItem, ins(AVM2Instructions.ConvertS), obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQNameL(false), true)),
                          ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)), nameItem, ins(AVM2Instructions.ConvertS), assignedValue,
                          needsReturn ? dupSetTemp(localData, generator, ret_temp) : null,
                          ins(AVM2Instructions.SetProperty, constants.getMultinameId(Multiname.createRTQNameL(false), true)),
                          needsReturn ? getTemp(localData, generator, ret_temp) : null,
                          killTemp(localData, generator, Arrays.asList(ns_temp, index_temp, ret_temp))
                  );
              } else {
                  return toSourceMerge(localData, generator,
                          obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, nameItem, ins(AVM2Instructions.ConvertS), obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQNameL(false), true)),
                          call ? dupSetTemp(localData, generator, obj_temp) : null,
                          ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)), nameItem, ins(AVM2Instructions.ConvertS),
                          construct ? callargs : null,
                          ins(construct ? AVM2Instructions.ConstructProp : delete ? AVM2Instructions.DeleteProperty : AVM2Instructions.GetProperty, constants.getMultinameId(Multiname.createRTQNameL(false), true), construct ? callargs.size() : null),
                          call ? getTemp(localData, generator, obj_temp) : null,
                          call ? callargs : null,
                          call ? ins(AVM2Instructions.Call, callargs.size()) : null,
                          needsReturn ? null : ins(AVM2Instructions.Pop),
                          killTemp(localData, generator, Arrays.asList(obj_temp))
                  );
              }
          } else if (assignedValue != null) {
              return toSourceMerge(localData, generator,
                      obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
                      ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)), assignedValue,
                      needsReturn ? dupSetTemp(localData, generator, ret_temp) : null,
                      ins(AVM2Instructions.SetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
                      needsReturn ? getTemp(localData, generator, ret_temp) : null,
                      killTemp(localData, generator, Arrays.asList(ns_temp, index_temp, ret_temp))
              );
          } else {
              return toSourceMerge(localData, generator,
                      obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
                      call ? dupSetTemp(localData, generator, obj_temp) : null,
                      ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)),
                      construct ? callargs : null,
                      ins(construct ? AVM2Instructions.ConstructProp : delete ? AVM2Instructions.DeleteProperty : AVM2Instructions.GetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true), construct ? callargs.size() : null),
                      call ? getTemp(localData, generator, obj_temp) : null,
                      call ? callargs : null,
                      call ? ins(AVM2Instructions.Call, callargs.size()) : null,
                      needsReturn ? null : ins(AVM2Instructions.Pop),
                      killTemp(localData, generator, Arrays.asList(obj_temp))
              );
          }
      }
  
      @Override
      public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
          return toSource(localData, generator, true, false, new ArrayList<>(), false, false);
      }
  
      @Override
      public List<GraphSourceItem> toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
          return toSource(localData, generator, false, false, new ArrayList<>(), false, false);
      }
  
      @Override
      public int hashCode() {
          int hash = 3;
          hash = 59 * hash + Objects.hashCode(this.ns);
          hash = 59 * hash + Objects.hashCode(this.name);
          hash = 59 * hash + Objects.hashCode(this.nameItem);
          hash = 59 * hash + Objects.hashCode(this.obj);
          hash = 59 * hash + (this.attr ? 1 : 0);
          hash = 59 * hash + Objects.hashCode(this.openedNamespaces);
          return hash;
      }
  
      @Override
      public boolean equals(Object obj) {
          if (this == obj) {
              return true;
          }
  