code: def _recursive_lazyop(
      buf: LazyBuffer,
      inputs: List[LazyBuffer],
      var_vals: Dict[Variable, int],
      st: ShapeTracker,
      realizes: Set[LazyBuffer],
      cache,
      first=True,
  ) -> LazyOp:
      if (buf, st) in cache:
          return cache[(buf, st)]
      if buf != buf.base:
          st = buf.st + st
          buf = buf.base
      # all buffers here are base now
      assert buf.op is not None
  
      # consts are always fused and generated
      if buf.op is LoadOps.CONST:
          unbound_st, st_var_vals = st.simplify().unbind()
          var_vals.update(st_var_vals)
          return LazyOp(
              BufferOps.CONST,
              (),
              ConstBuffer(float(buf.arg), buf.dtype, unbound_st),
          )
  
      # if we aren't fusing it, it's a load and we add it to the inputs
      if buf.realized or (buf in realizes and not first):
          if buf not in inputs:
              inputs.append(buf)
          unbound_st, st_var_vals = st.simplify().unbind()
          var_vals.update(st_var_vals)
          return LazyOp(
              BufferOps.LOAD,
              (),
              MemBuffer(inputs.index(buf) + 1, buf.dtype, unbound_st),
          )
  
      # if a CONTIGUOUS made it all the way here, just skip it
      if buf.op is LoadOps.CONTIGUOUS:
          assert first
          return _recursive_lazyop(
              buf.srcs[0], inputs, var_vals, st, realizes, cache, False
          )
  
      # if it's a reduce, we have to change the shapetracker
      if buf.op in ReduceOps:
          assert (
              st.contiguous
          ), "ReduceOps late fusion must be contiguous"
          st = ShapeTracker.from_shape(buf.srcs[0].shape)
  
      # otherwise we fuse it like normal
      cache[(buf, st)] = ret = LazyOp(
          buf.op,
          tuple(
              _recursive_lazyop(
                  x, inputs, var_vals, st, realizes, cache, False
              )
              for x in buf.srcs
          ),
          buf.arg,
      )
      return ret
  
imports: from __future__ import annotations
  import sys, math
  from collections import defaultdict
  from typing import Union, Optional, Any, Tuple, List, Set, Dict, DefaultDict, cast
  from tinygrad.dtype import dtypes, DType, ImageDType
  from tinygrad.helpers import prod, flatten, getenv, dedup, DEBUG, all_int, all_same, GRAPH
  from tinygrad.ops import LoadOps, UnaryOps, BinaryOps, TernaryOps, ReduceOps, BufferOps, Op, LazyOp, ConstBuffer, MemBuffer, ScheduleItem
  from tinygrad.shape.symbolic import sint, Variable
  from tinygrad.shape.shapetracker import ShapeTracker
  from tinygrad.device import Buffer
  from tinygrad.graph import log_lazybuffer
  from weakref import ref, ReferenceType
label_desc: Use image node_id 2 for calling a global function with example usage: _recursive_lazyop(buf, inputs, var_vals, st, realizes, cache, first) and returns: ret, cache, LazyOp, LazyOp, _recursive_lazyop