code: def apply_mop(
      st: ShapeTracker, mop_arg: Tuple[MovementOps, Tuple]
  ) -> ShapeTracker:
      mop, arg = mop_arg
      if mop == MovementOps.RESHAPE:
          # shapetracker doesn't allow flattening with -1 but required for MovementOps.RESHAPE
          if arg == (-1,):
              return st.reshape((prod(st.views[-1].shape),))
          return st.reshape(arg)
      if mop == MovementOps.PERMUTE:
          return st.permute(arg)
      if mop == MovementOps.EXPAND:
          if len(arg) != len(st.shape):
              st = st.reshape((1, *st.shape))
          return st.expand(arg)
      if mop == MovementOps.PAD:
          return st.pad(arg)
      if mop == MovementOps.SHRINK:
          return st.shrink(arg)
      if mop == MovementOps.STRIDE:
          return st.stride(arg)
      raise ValueError("invalid mop")
  
file_path: tinygrad/extra/to_movement_ops.py
imports: from tqdm import tqdm
  import itertools
  from collections import defaultdict
  from typing import List, Tuple, DefaultDict
  from extra.optimization.helpers import load_worlds, ast_str_to_ast
  from tinygrad.ops import MovementOps, BufferOps, LazyOp
  from tinygrad.helpers import prod
  from tinygrad.shape.shapetracker import ShapeTracker
  from tinygrad.shape.symbolic import sym_infer, Node
label_desc: Use image node_id 1 for calling a global function with example usage: apply_mop(st, mop_arg) and returns: st, st, st, st, st, st, st