packages feed

phino-0.0.158: src/Dataize.hs

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_GHC -Wno-name-shadowing #-}

-- SPDX-FileCopyrightText: Copyright (c) 2025 Objectionary.com
-- SPDX-License-Identifier: MIT

module Dataize (dataize, dataize', reduction, Outcome (..)) where

import AST
import Control.Exception (throwIO, try)
import Control.Monad (unless, when)
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NE
import Data.Maybe (listToMaybe)
import qualified Data.Text as T
import Deps (Evaluation (..), Judgment (..), State (..), resited)
import Engine (Engine (..))
import qualified Inference as In
import Locator (locatedExpression)
import Morph (Morphed, ReduceContext (..), ReduceException (..), ReductionFunc, deeper, entering, inferred, insideUniverse, leadsTo, onward, opening, parking, universed)
import Rewriter (Rewritten)

type Dataized = (Bytes, [Rewritten])

type Dataizable = Morphed

data Outcome
  = Dataized Bytes
  | Residual Expression
  deriving stock (Eq, Show)

dataize :: Expression -> State -> ReduceContext -> IO (Outcome, [Rewritten], State)
dataize universe state ctx@ReduceContext{..} = do
  expr <- locatedExpression _locator universe
  result <- try (dataize' (expr, (universe, Nothing) :| []) universe state ctx)
  case result of
    Right ((bytes, seq), state') -> pure (Dataized bytes, reverse seq, state')
    Left (StuckAt func seq parked) | _partial -> residual seq parked{_stuck = Just func}
    Left (OutOfStepsAt _ seq parked) | _partial -> residual seq parked
    Left (LoopingAt _ seq parked) | _partial -> residual seq parked
    Left (Undataizable term seq parked) | _partial -> do
      unless (dead `elem` _parked) (_saveEval (EvStuck _nesting dead Dataization term))
      residual seq parked{_stuck = Just dead}
    Left failure -> throwIO (failure :: ReduceException)
  where
    dead :: T.Text
    dead = "⊥"
    residual :: NonEmpty Rewritten -> State -> IO (Outcome, [Rewritten], State)
    residual seq parked = do
      residue <- locatedExpression _locator (fst (NE.head seq))
      pure (Residual residue, reverse (NE.toList seq), parked)

dataize' :: Dataizable -> Expression -> State -> ReduceContext -> IO (Dataized, State)
dataize' (expr, seq) univ state caller = do
  ctx <- opening Dataization =<< deeper =<< entering expr =<< parking seq state (universed univ caller{_judgment = Dataization})
  parking seq state $ case unknown expr of
    Just idx -> manufactured idx ctx
    Nothing -> do
      reached <- inferred expr univ state ctx ctx._engine._dataization
      case reached of
        Just (In.Answered step bts, state') -> do
          when (step == (Dataization, "delta")) (ctx._saveEval (EvDelta ctx._nesting bts))
          seq' <- leadsTo seq step (ExBytes bts) ctx
          pure ((bts, NE.toList seq'), state'{_manufactured = Nothing})
        Just (In.Onward way built world, state') -> do
          ctx' <- boxing way built ctx
          (dataizable, state'') <- onward seq state' way built ctx'
          dataize' dataizable world state'' ctx'
        Nothing -> throwIO (Undataizable expr seq state)
  where
    boxing :: In.Way -> Expression -> ReduceContext -> IO ReduceContext
    boxing way built ctx
      | way == In.Normalized (Dataization, "box") = do
          ctx._saveEval (EvBoxed ctx._nesting built)
          pure ctx{_saveEval = ctx._saveEval . resited ctx._site built}
      | otherwise = pure ctx
    unknown :: Expression -> Maybe Int
    unknown (ExFormation bds) = listToMaybe [idx | BiLambda (FnSymbol idx) <- bds]
    unknown _ = Nothing
    manufactured :: Int -> ReduceContext -> IO (Dataized, State)
    manufactured idx ctx = do
      ctx._saveEval (EvManufactured ctx._nesting idx)
      seq' <- leadsTo seq (Dataization, "symbol") (ExBytes datum) ctx
      pure ((datum, NE.toList seq'), state{_manufactured = Just idx})

reduction :: ReductionFunc
reduction univ ctx expr state = do
  (universe, aiming) <- insideUniverse expr univ ctx
  (outcome, _, state') <- dataize universe state aiming
  pure (reached outcome, state')
  where
    reached :: Outcome -> Maybe Bytes
    reached (Dataized bytes) = Just bytes
    reached (Residual _) = Nothing

datum :: Bytes
datum = BtMany ["40", "45", "00", "00", "00", "00", "00", "00"]