<commit_before>{-# LANGUAGE GADTs #-}

{-|
Given a Technique Procedure, transform it into an Instance that can be executed.
-}
module Technique.Evaluator where

import Core.Data
import Core.Text
import Data.UUID.Types (UUID)

import Technique.Language
import Technique.Quantity

-- Need names? Science names newly discovered creatures in Latin. I don't
-- speak Latin, but neither does anyone else so we can just make words up.
-- Yeay! (The lengths some people will go to in order to avoid qualified
-- imports is really impressive, isn't it?)
data Value
    = Unitus
    | Literali Rope
    | Quanticle Quantity
    | Tabularum [(Rope,Value)]

data Context = Context (Map Identifier Value)

data Environment = Environment (Map Identifier Value)


{-
data Expression b where
    Binding :: Variable b -> Expression a -> Expression b
    Comment :: Rope -> Expression ()
    Declaration :: (a -> b) -> Expression (a -> b)
    Application :: Expression (a -> b) -> Expression a -> Expression b 
    Attribute :: Role -> Expression a -> Expression a
-}


{-
-- aka apply
execute :: Procedure -> Value -> b
execute proc value =
  let
    body = procedureBlock proc
  in
    evaluate body

type Context = Map String Value -- ?


evaluate = undefined
-}
evaluate :: Context -> Procedure -> Value
evaluate c procedure = case procedure of
    Comment _ -> ()
    _ -> undefined

data Instance = Instance
    { instanceProcedure :: Procedure
    , instanceUniversal :: UUID
    , instancePath :: Rope -- ?
    }

instantiate :: Context -> Procedure -> Instance
instantiate context procedure = undefined
<commit_msg>Preliminary attempt at folding over Expression<commit_after>{-# LANGUAGE GADTs #-}

{-|
Given a Technique Procedure, transform it into an Instance that can be executed.
-}
module Technique.Evaluator where

import Core.Data
import Core.Text
import Data.UUID.Types (UUID)

import Technique.Language
import Technique.Quantity

-- Need names? Science names newly discovered creatures in Latin. I don't
-- speak Latin, but neither does anyone else so we can just make words up.
-- Yeay! (The lengths some people will go to in order to avoid qualified
-- imports is really impressive, isn't it?)
data Value
    = Unitus
    | Literali Rope
    | Quanticle Quantity
    | Tabularum [(Rope,Value)]
    | Parametri [Value]         -- TODO hmm

data Context = Context (Map Identifier Value)

data Environment = Environment (Map Identifier Value)

{-
data Expression b where
    Binding :: Variable b -> Expression a -> Expression b
    Comment :: Rope -> Expression ()
    Declaration :: (a -> b) -> Expression (a -> b)
    Application :: Expression (a -> b) -> Expression a -> Expression b 
    Attribute :: Role -> Expression a -> Expression a
-}

evaluate :: Environment -> Expression -> Value
evaluate env expr' = case expr' of
    Application i expr -> functionApplication (lookupProcedure env i) (evaluate env expr)    -- lookup needs to return a function?
    None    -> Unitus
    Text text -> Literali text
    Amount qty -> Quanticle qty
    Undefined -> error "?!?" -- not error but "hole, stop here"
    Object (Tablet bindings) -> Tabularum (fmap (\(Binding label expr) -> (label,evaluate env expr)) bindings)
    Variable is -> Parametri (fmap (lookupValue env) is)    -- TODO hmm
    Operation op expr1 expr2 -> case op of
        WaitEither  -> waitEither (evaluate env expr1) (evaluate env expr2)
        WaitBoth    -> waitBoth (evaluate env expr1) (evaluate env expr2)
        Combine     -> combineValues (evaluate env expr1) (evaluate env expr2)
    Grouping expr -> evaluate env expr
    Restriction attr block -> applyRestriction attr block


functionApplication :: Procedure -> Value -> Value
functionApplication = undefined

lookupProcedure :: Environment -> Identifier -> Procedure
lookupProcedure = undefined

lookupValue :: Environment -> Identifier -> Value
lookupValue = undefined

waitEither :: Value -> Value -> Value
waitEither = undefined

waitBoth :: Value -> Value -> Value
waitBoth = undefined

combineValues :: Value -> Value -> Value
combineValues = undefined

applyRestriction :: Attribute -> Block -> Value
applyRestriction = undefined

data Instance = Instance
    { instanceProcedure :: Procedure
    , instanceUniversal :: UUID
    , instancePath :: Rope -- ?
    }

instantiate :: Context -> Procedure -> Instance
instantiate context procedure = Instance
    { instanceProcedure = procedure
    , instanceUniversal = -- ** we need IO here now!!! **
    , instancePath :: Rope -- ?
    }

{'fraction_non_alphanumeric': 0.0967100905277103, 'fraction_numerical': 0.0017663943475380878, 'mean_word_length': 3.217877094972067, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1330094', 'n_tokens_mistral': 1237, 'n_tokens_neox': 1180, 'n_words': 495}