public function render() : string
    {
        // assign data if any
        if (\func_num_args() > 0) {
            // php 7.2.0 is crazy
            $args = \func_get_args();
            $this->assign($args[0]);
        }

        $result = '';
        $shared = [];

        foreach ($this as $box) {
            // if box has no shared data
            if ($box->child === $box) {
                // render, concat, and continue
                $result .= $box->renderer->render($box->interior, $box->data);
                continue;
            }

            // cache union sets of shared data arrays using root as key
            $root = $box->find();
            $key = \spl_object_hash($root);
            if (!isset($shared[$key])) {
                $shared[$key] = [];
                $shared[$key][] = &$root->data;
                for ($i = $root->child; $i !== $root; $i = $i->child) {
                    $shared[$key][] = &$i->data;
                }
            }

            // render with shared data and concat results
            $result .= $box->renderer->render($box->interior, $box->data, $shared[$key]);
        }

        return $result;
    }