code: public static function fromArray(array $node) : Node
      {
          if (! isset($node['kind']) || ! isset(NodeKind::$classMap[$node['kind']])) {
              throw new InvariantViolation('Unexpected node structure: ' . Utils::printSafeJson($node));
          }
  
          $kind     = $node['kind'] ?? null;
          $class    = NodeKind::$classMap[$kind];
          $instance = new $class([]);
  
          if (isset($node['loc'], $node['loc']['start'], $node['loc']['end'])) {
              $instance->loc = Location::create($node['loc']['start'], $node['loc']['end']);
          }
  
          foreach ($node as $key => $value) {
              if ($key === 'loc' || $key === 'kind') {
                  continue;
              }
              if (is_array($value)) {
                  if (isset($value[0]) || empty($value)) {
                      $value = new NodeList($value);
                  } else {
                      $value = self::fromArray($value);
                  }
              }
              $instance->{$key} = $value;
          }
  
          return $instance;
      }
docs: Convert representation of AST as an associative array to instance of GraphQL\Language\AST\Node.
  
  For example:
  
  ```php
  AST::fromArray([
  'kind' => 'ListValue',
  'values' => [
  ['kind' => 'StringValue', 'value' => 'my str'],
  ['kind' => 'StringValue', 'value' => 'my other str']
  ],
  'loc' => ['start' => 21, 'end' => 25]
  ]);
  ```
  
  Will produce instance of `ListValueNode` where `values` prop is a lazily-evaluated `NodeList`
  returning instances of `StringValueNode` on access.
  
  This is a reverse operation for AST::toArray($node)
  
  @param mixed[] $node
  
  @api