content: package org.graalphp.nodes.assign;
  
  import com.oracle.truffle.api.dsl.NodeChild;
  import com.oracle.truffle.api.dsl.Specialization;
  import com.oracle.truffle.api.library.CachedLibrary;
  import org.graalphp.nodes.PhpExprNode;
  import org.graalphp.runtime.array.ArrayAllocator;
  import org.graalphp.runtime.array.ArrayFactory;
  import org.graalphp.runtime.array.ArrayLibrary;
  import org.graalphp.runtime.array.PhpArray;
  
  /**
   * Node which forwards all values but arrays and copy arrays before forwarding.
   * This implements PHP default assign by value semantics
   *
   * @author abertschi
   */
  @NodeChild(value = "source", type = PhpExprNode.class)
  public abstract class AssignByValueNode extends AssignSemanticNode {
  
      public static AssignByValueNode createWithoutChild() {
          return AssignByValueNodeGen.create(null);
      }
  
      @Specialization
      protected boolean forwardBool(boolean val) {
          return val;
      }
  
      @Specialization
      protected long forwardLong(long val) {
          return val;
      }
  
      @Specialization
      protected double forwardDouble(double val) {
          return val;
      }
  
      @Specialization
      protected Object copyArray(
              PhpArray array,
              @CachedLibrary(limit = ArrayLibrary.SPECIALIZATION_LIMIT) ArrayLibrary lib) {
  
          ArrayAllocator allocator = lib.getArrayAllocator(array.getBackend());
          Object newBackend = allocator.createArray(array.getCapacity());
          lib.copyDeepContents(array.getBackend(), newBackend, array.getCapacity());
          return ArrayFactory.newArray(newBackend, array.getCapacity());
      }
  
      @Specialization(guards = "notArray(val)")
      protected Object forwardObject(Object val) {
          // Objects are copied by reference (their reference is copied)
          return val;
      }
  
      protected final boolean notArray(Object o) {
          return !(o instanceof PhpArray);
      }
  
      protected abstract PhpExprNode getSource();
  
      @Override
      public String toString() {
          return "AssignByValueNode{" + getSource() + "}";
      }
  }
  