------------------------------------------------------------------------

-- | Process a "points_to" statement from the postcondition section of
-- the CrucibleSetup block. First we compute the value indicated by
-- 'val', and then write it to the address indicated by 'ptr'.
executePointsTo ::
  Options                    ->
  SharedContext              ->
  JVMCrucibleContext            ->
  CrucibleMethodSpecIR       ->
  JVMPointsTo                   ->
  OverrideMatcher CJ.JVM w ()
executePointsTo opts sc cc spec pt =
  jccWithBackend cc $ \bak -> do
  let sym = backendGetSym bak
  globals <- OM (use overrideGlobals)
  let jc = cc ^. jccJVMContext
  case pt of

    JVMPointsToField _loc ptr fid val ->
      do dyn <- maybe (pure CJ.unassignedJVMValue) (injectSetupValueJVM sym opts cc sc spec) val
         rval <- resolveAllocIndexJVM ptr
         globals' <- liftIO $ CJ.doFieldStore bak globals rval fid dyn
         OM (overrideGlobals .= globals')

    JVMPointsToStatic _loc fid val ->
      do dyn <- maybe (pure CJ.unassignedJVMValue) (injectSetupValueJVM sym opts cc sc spec) val
         globals' <- liftIO $ CJ.doStaticFieldStore bak jc globals fid dyn
         OM (overrideGlobals .= globals')

    JVMPointsToElem _loc ptr idx val ->
      do dyn <- maybe (pure CJ.unassignedJVMValue) (injectSetupValueJVM sym opts cc sc spec) val
         rval <- resolveAllocIndexJVM ptr
         globals' <- liftIO $ CJ.doArrayStore bak globals rval idx dyn
         OM (overrideGlobals .= globals')

    JVMPointsToArray _loc ptr (Just tt) ->
      do (_ety, tts) <-
           liftIO (destVecTypedTerm sc tt) >>=
           \case
             Nothing -> fail "jvm_array_is: not a monomorphic sequence type"
             Just x -> pure x
         rval <- resolveAllocIndexJVM ptr
         vs <- traverse (injectSetupValueJVM sym opts cc sc spec . MS.SetupTerm) tts
         globals' <- liftIO $ doEntireArrayStore bak globals rval vs
         OM (overrideGlobals .= globals')

    JVMPointsToArray _loc ptr Nothing ->
      case Map.lookup ptr (MS.csAllocations spec) of
        Just (_, AllocArray len _) ->
          do let vs = replicate len CJ.unassignedJVMValue
             rval <- resolveAllocIndexJVM ptr
             globals' <- liftIO $ doEntireArrayStore bak globals rval vs
             OM (overrideGlobals .= globals')
        _ -> panic "JVMSetup" ["executePointsTo", "expected array allocation"]
executePointsTo ::
  Options                    ->
  SharedContext              ->
  JVMCrucibleContext            ->
  CrucibleMethodSpecIR       ->
  JVMPointsTo                   ->
  OverrideMatcher CJ.JVM w ()
executePointsTo opts sc cc spec pt =
  jccWithBackend cc $ \bak -> do
  let sym = backendGetSym bak
  globals <- OM (use overrideGlobals)
  let jc = cc ^. jccJVMContext
  case pt of

    JVMPointsToField _loc ptr fid val ->
      do dyn <- maybe (pure CJ.unassignedJVMValue) (injectSetupValueJVM sym opts cc sc spec) val
         rval <- resolveAllocIndexJVM ptr
         globals' <- liftIO $ CJ.doFieldStore bak globals rval fid dyn
         OM (overrideGlobals .= globals')

    JVMPointsToStatic _loc fid val ->
      do dyn <- maybe (pure CJ.unassignedJVMValue) (injectSetupValueJVM sym opts cc sc spec) val
         globals' <- liftIO $ CJ.doStaticFieldStore bak jc globals fid dyn
         OM (overrideGlobals .= globals')

    JVMPointsToElem _loc ptr idx val ->
      do dyn <- maybe (pure CJ.unassignedJVMValue) (injectSetupValueJVM sym opts cc sc spec) val
         rval <- resolveAllocIndexJVM ptr
         globals' <- liftIO $ CJ.doArrayStore bak globals rval idx dyn
         OM (overrideGlobals .= globals')

    JVMPointsToArray _loc ptr (Just tt) ->
      do (_ety, tts) <-
           liftIO (destVecTypedTerm sc tt) >>=
           \case
             Nothing -> fail "jvm_array_is: not a monomorphic sequence type"
             Just x -> pure x
         rval <- resolveAllocIndexJVM ptr
         vs <- traverse (injectSetupValueJVM sym opts cc sc spec . MS.SetupTerm) tts
         globals' <- liftIO $ doEntireArrayStore bak globals rval vs
         OM (overrideGlobals .= globals')

    JVMPointsToArray _loc ptr Nothing ->
      case Map.lookup ptr (MS.csAllocations spec) of
        Just (_, AllocArray len _) ->
          do let vs = replicate len CJ.unassignedJVMValue
             rval <- resolveAllocIndexJVM ptr
             globals' <- liftIO $ doEntireArrayStore bak globals rval vs
             OM (overrideGlobals .= globals')
        _ -> panic "JVMSetup" ["executePointsTo", "expected array allocation"]
executePointsTo opts sc cc spec pt =
  jccWithBackend cc $ \bak -> do
  let sym = backendGetSym bak
  globals <- OM (use overrideGlobals)
  let jc = cc ^. jccJVMContext
  case pt of

    JVMPointsToField _loc ptr fid val ->
      do dyn <- maybe (pure CJ.unassignedJVMValue) (injectSetupValueJVM sym opts cc sc spec) val
         rval <- resolveAllocIndexJVM ptr
         globals' <- liftIO $ CJ.doFieldStore bak globals rval fid dyn
         OM (overrideGlobals .= globals')

    JVMPointsToStatic _loc fid val ->
      do dyn <- maybe (pure CJ.unassignedJVMValue) (injectSetupValueJVM sym opts cc sc spec) val
         globals' <- liftIO $ CJ.doStaticFieldStore bak jc globals fid dyn
         OM (overrideGlobals .= globals')

    JVMPointsToElem _loc ptr idx val ->
      do dyn <- maybe (pure CJ.unassignedJVMValue) (injectSetupValueJVM sym opts cc sc spec) val
         rval <- resolveAllocIndexJVM ptr
         globals' <- liftIO $ CJ.doArrayStore bak globals rval idx dyn
         OM (overrideGlobals .= globals')

    JVMPointsToArray _loc ptr (Just tt) ->
      do (_ety, tts) <-
           liftIO (destVecTypedTerm sc tt) >>=
           \case
             Nothing -> fail "jvm_array_is: not a monomorphic sequence type"
             Just x -> pure x
         rval <- resolveAllocIndexJVM ptr
         vs <- traverse (injectSetupValueJVM sym opts cc sc spec . MS.SetupTerm) tts
         globals' <- liftIO $ doEntireArrayStore bak globals rval vs
         OM (overrideGlobals .= globals')

    JVMPointsToArray _loc ptr Nothing ->
      case Map.lookup ptr (MS.csAllocations spec) of
        Just (_, AllocArray len _) ->
          do let vs = replicate len CJ.unassignedJVMValue
             rval <- resolveAllocIndexJVM ptr
             globals' <- liftIO $ doEntireArrayStore bak globals rval vs
             OM (overrideGlobals .= globals')
        _ -> panic "JVMSetup" ["executePointsTo", "expected array allocation"]