public static function fromPhp($phpFunctionName, $expressionFunctionName = null)
    {
        $phpFunctionName = ltrim($phpFunctionName, '\\');
        if (!\function_exists($phpFunctionName)) {
            throw new \InvalidArgumentException(sprintf('PHP function "%s" does not exist.', $phpFunctionName));
        }

        $parts = explode('\\', $phpFunctionName);
        if (!$expressionFunctionName && \count($parts) > 1) {
            throw new \InvalidArgumentException(sprintf('An expression function name must be defined when PHP function "%s" is namespaced.', $phpFunctionName));
        }

        $compiler = function () use ($phpFunctionName) {
            return sprintf('\%s(%s)', $phpFunctionName, implode(', ', \func_get_args()));
        };

        $evaluator = function () use ($phpFunctionName) {
            return $phpFunctionName(...\array_slice(\func_get_args(), 1));
        };

        return new self($expressionFunctionName ?: end($parts), $compiler, $evaluator);
    }