def evaluate(node, sphinxContext, value=False, fallback=None, hsBoundFact=False):
    if isinstance(node, astNode):
        if fallback is None:
            result = evaluator[node.__class__.__name__](node, sphinxContext)
        else:
            try:
                result = evaluator[node.__class__.__name__](node, sphinxContext)
            except __HOLE__:
                if sphinxContext.formulaOptions.traceVariableSetExpressionEvaluation:
                    sphinxContext.modelXbrl.info("sphinx:trace",
                         _("%(node)s has unbound evaluation"), 
                         sourceFileLine=node.sourceFileLine, node=str(node))
                return fallback
        if sphinxContext.formulaOptions.traceVariableSetExpressionEvaluation:
            sphinxContext.modelXbrl.info("sphinx:trace",
                 _("%(node)s evaluation: %(value)s"), 
                 sourceFileLine=node.sourceFileLine, node=str(node), value=result)
        if result is not None:
            if isinstance(result, HyperspaceBinding):
                if hsBoundFact:  # return fact, not the value of fact
                    return result.yieldedFact
                elif value:
                    return result.value
            # dereference nodes to their value
            if (value or hsBoundFact) and isinstance(result, astNode):
                return evaluate(result, sphinxContext, value, fallback, hsBoundFact)
            return result
        return result
    elif isinstance(node, (tuple,list)):
        return [evaluate(item, sphinxContext, value, fallback, hsBoundFact)
                for item in node]
    elif isinstance(node, set):
        return set(evaluate(item, sphinxContext, value, fallback, hsBoundFact)
                   for item in node)
    else:
        return node
dataset/ETHPy150Open Arelle/Arelle/arelle/plugin/sphinx/SphinxEvaluator.py/evaluate