<commit_before>{-# LANGUAGE TemplateHaskell  #-}
{-# LANGUAGE TypeApplications #-}

module Test.Lang.InterpreterSpec
    ( spec
    ) where

import           Control.Lens    ((&))
import qualified Data.Map        as M
import           Test.Hspec      (Spec, describe, it)
import           Test.QuickCheck (Discard (..), Property, conjoin, property, within,
                                  (===), (==>))

import           Test.Arbitrary  ()
import           Test.Util       (ExecWay (..), TestRes (..), describeExecWays, (>-->),
                                  (~*~), (~~))
import           Toy.Exp
import           Toy.Lang        (ExecState (..), Stmt (..), simpleExecState)
import           Toy.Lang        (execute)


spec :: Spec
spec = do
    describeExecWays [Interpret] $ \_ -> do
        describe "examples" $ do
            it "Skip" $
                initSkipTest
            it "If true" $
                ifTrueTest
            it "If false" $
                ifFalseTest
            it "variables simple" $
                varsTest
            it "While simple" $
                whileTest
            it "If simple" $
                property minTest
            it "error simple" $
                errorTest
            it "different erroneous scenarios" $
                errorsTest
            describe "complex" $ do
                it "fib" $
                    property fibTest
                it "gcd" $
                    property gcdTest

        it "`execute` always ends with Skip" $
            property executeAlwaysEndsWithSkip

    describeExecWays [Interpret, Translate] $ \way -> do
        describe "examples" $ do
            it "io simple" $
                ioTest way


executeAlwaysEndsWithSkip :: ExecState -> Property
executeAlwaysEndsWithSkip initExecState@(ExecState _ _ _ initStmt) =
    within 1000000 $
    -- propability of initial action to be SkipS is too high
    initStmt /= Skip ==>
        case execute initExecState of
            Left _                      -> property Discard
            Right (ExecState _ _ _ end) -> end === Skip


initSkipTest :: Property
initSkipTest = execute sample === Right expected
  where
    sample   = simpleExecState Skip
    expected = simpleExecState Skip

ifTrueTest :: Property
ifTrueTest = sample & [] >--> [0]
  where
    sample = If (1 +: 2) (Write 0) (Write 1)

ifFalseTest :: Property
ifFalseTest = sample & [] >--> [1]
  where
    sample = If (1 -: 1) (Write 0) (Write 1)

varsTest :: Property
varsTest = execute sample === Right expected
  where
    sample = simpleExecState $ mconcat
        [ "a" := 1
        , "b" := 2
        , "a" := 3
        , While ("a" ==: 0) Skip  -- test variable access
        ]
    expected =
        let expectedVars = M.fromList
                [ ("a", 3)
                , ("b", 2)
                ]
        in  ExecState [] [] expectedVars Skip

ioTest :: ExecWay -> Property
ioTest = id @Value ~*~ sample
  where
    sample = mconcat
        [ Read "a"
        , Write "a"
        ]

whileTest :: Property
whileTest = sample & [] >--> [4, 3 .. 0]
  where
    sample = mconcat
        [ "i" := 0
        , While ("i" <: 5) $ mconcat
            [ Write "i"
            , "i" := "i" +: 1
            ]
        ]

errorTest :: Property
errorTest = sample & [] >--> X
  where
    sample = Write (5 /: 0)

errorsTest :: Property<commit_msg>Tests cleanup<commit_after>{-# LANGUAGE TemplateHaskell  #-}
{-# LANGUAGE TypeApplications #-}

module Test.Lang.InterpreterSpec
    ( spec
    ) where

import           Control.Lens    ((&))
import           Test.Hspec      (Spec, describe, it)
import           Test.QuickCheck (Discard (..), Property, conjoin, property, within,
                                  (===), (==>))

import           Test.Arbitrary  ()
import           Test.Util       (ExecWay (..), TestRes (..), describeExecWays, (>-->),
                                  (~*~), (~~))
import           Toy.Exp
import           Toy.Lang        (ExecState (..), Stmt (..), simpleExecState)
import           Toy.Lang        (execute)


spec :: Spec
spec = do
    describeExecWays [Interpret] $ \_ -> do
        describe "examples" $ do
            it "Skip" $
                initSkipTest
            it "If true" $
                ifTrueTest
            it "If false" $
                ifFalseTest
            it "variables simple" $
                varsTest
            it "While simple" $
                whileTest
            it "If simple" $
                property minTest
            it "different erroneous scenarios" $
                errorsTest
            describe "complex" $ do
                it "fib" $
                    property fibTest
                it "gcd" $
                    property gcdTest

        it "`execute` always ends with Skip" $
            property executeAlwaysEndsWithSkip

    describeExecWays [Interpret, Translate] $ \way -> do
        describe "examples" $ do
            it "io simple" $
                ioTest way


executeAlwaysEndsWithSkip :: ExecState -> Property
executeAlwaysEndsWithSkip initExecState@(ExecState _ _ _ initStmt) =
    within 1000000 $
    -- propability of initial action to be SkipS is too high
    initStmt /= Skip ==>
        case execute initExecState of
            Left _                      -> property Discard
            Right (ExecState _ _ _ end) -> end === Skip


initSkipTest :: Property
initSkipTest = execute sample === Right expected
  where
    sample   = simpleExecState Skip
    expected = simpleExecState Skip

ifTrueTest :: Property
ifTrueTest = sample & [] >--> [0]
  where
    sample = If 1 (Write 0) (Write 1)

ifFalseTest :: Property
ifFalseTest = sample & [] >--> [1]
  where
    sample = If 0 (Write 0) (Write 1)

varsTest :: Property
varsTest = execute sample === Right expected
  where
    sample = simpleExecState $ mconcat
        [ "a" := 1
        , "b" := 2
        , "a" := 3
        , While ("a" ==: 0) Skip  -- test variable access
        ]
    expected =
        let expectedVars =
                [ ("a", 3)
                , ("b", 2)
                ]
        in  ExecState [] [] expectedVars Skip

ioTest :: ExecWay -> Property
ioTest = id @Value ~*~ sample
  where
    sample = mconcat
        [ Read "a"
        , Write "a"
        ]

whileTest :: Property
whileTest = sample & [] >--> [4, 3 .. 0]
  where
    sample = mconcat
        [ "i" := 0
        , While ("i" <: 5) $ mconcat
            [ Write "i"
            , "i" := "i" +: 1
            ]
        ]

errorsTest :: Property
{'fraction_non_alphanumeric': 0.11017597551644988, 'fraction_numerical': 0.008875286916602908, 'mean_word_length': 1.4776345716451857, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4719049', 'n_tokens_mistral': 1909, 'n_tokens_neox': 1794, 'n_words': 532}