src/basilisp/lang/compiler/generator.py
def _var_sym_to_py_ast(
    ctx: GeneratorContext, node: VarRef, is_assigning: bool = False
) -> GeneratedPyAST:
    """Generate a Python AST node for accessing a Var.

    If the Var is marked as :dynamic or :redef or the compiler option
    USE_VAR_INDIRECTION is active, do not compile to a direct access.
    If the corresponding function name is not defined in a Python module,
    no direct variable access is possible and Var.find indirection must be
    used."""
    assert node.op == NodeOp.VAR

    var = node.var
    ns = var.ns
    ns_name = ns.name
    ns_module = ns.module
    safe_ns = munge(ns_name)
    var_name = var.name.name
    py_var_ctx = ast.Store() if is_assigning else ast.Load()

    # Return the actual var, rather than its value if requested
    if node.return_var:
        return GeneratedPyAST(
            node=ast.Call(
                func=_FIND_VAR_FN_NAME,
                args=[
                    ast.Call(
                        func=_NEW_SYM_FN_NAME,
                        args=[ast.Str(var_name)],
                        keywords=[ast.keyword(arg="ns", value=ast.Str(ns_name))],
                    )
                ],
                keywords=[],
            )
        )

    # Check if we should use Var indirection
    if ctx.use_var_indirection or _is_dynamic(var) or _is_redefable(var):
        return __var_find_to_py_ast(var_name, ns_name, py_var_ctx)

    # Otherwise, try to direct-link it like a Python variable
    # Try without allowing builtins first
    safe_name = munge(var_name)
    if safe_name not in ns_module.__dict__:
        # Try allowing builtins
        safe_name = munge(var_name, allow_builtins=True)

    if safe_name in ns_module.__dict__:
        if ns is ctx.current_ns:
            return GeneratedPyAST(node=ast.Name(id=safe_name, ctx=py_var_ctx))
        return GeneratedPyAST(node=_load_attr(f"{safe_ns}.{safe_name}", ctx=py_var_ctx))

    if ctx.warn_on_var_indirection:
        logger.warning(f"could not resolve a direct link to Var '{var_name}'")

    return __var_find_to_py_ast(var_name, ns_name, py_var_ctx)
def _var_sym_to_py_ast(
    ctx: GeneratorContext, node: VarRef, is_assigning: bool = False
) -> GeneratedPyAST:
    """Generate a Python AST node for accessing a Var.

    If the Var is marked as :dynamic or :redef or the compiler option
    USE_VAR_INDIRECTION is active, do not compile to a direct access.
    If the corresponding function name is not defined in a Python module,
    no direct variable access is possible and Var.find indirection must be
    used."""
    assert node.op == NodeOp.VAR

    var = node.var
    ns = var.ns
    ns_name = ns.name
    ns_module = ns.module
    safe_ns = munge(ns_name)
    var_name = var.name.name
    py_var_ctx = ast.Store() if is_assigning else ast.Load()

    # Return the actual var, rather than its value if requested
    if node.return_var:
        return GeneratedPyAST(
            node=ast.Call(
                func=_FIND_VAR_FN_NAME,
                args=[
                    ast.Call(
                        func=_NEW_SYM_FN_NAME,
                        args=[ast.Str(var_name)],
                        keywords=[ast.keyword(arg="ns", value=ast.Str(ns_name))],
                    )
                ],
                keywords=[],
            )
        )

    # Check if we should use Var indirection
    if ctx.use_var_indirection or _is_dynamic(var) or _is_redefable(var):
        return __var_find_to_py_ast(var_name, ns_name, py_var_ctx)

    # Otherwise, try to direct-link it like a Python variable
    # Try without allowing builtins first
    safe_name = munge(var_name)
    if safe_name not in ns_module.__dict__:
        # Try allowing builtins
        safe_name = munge(var_name, allow_builtins=True)

    if safe_name in ns_module.__dict__:
        if ns is ctx.current_ns:
            return GeneratedPyAST(node=ast.Name(id=safe_name, ctx=py_var_ctx))
        return GeneratedPyAST(node=_load_attr(f"{safe_ns}.{safe_name}", ctx=py_var_ctx))

    if ctx.warn_on_var_indirection:
        logger.warning(f"could not resolve a direct link to Var '{var_name}'")

    return __var_find_to_py_ast(var_name, ns_name, py_var_ctx)
Generate a Python AST node for accessing a Var.

    If the Var is marked as :dynamic or :redef or the compiler option
    USE_VAR_INDIRECTION is active, do not compile to a direct access.
    If the corresponding function name is not defined in a Python module,
    no direct variable access is possible and Var.find indirection must be
    used.