content: {-# LANGUAGE TypeSynonymInstances #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE DataKinds #-}
  
  module Test.Generators where
  
  import Data.Map.Strict
  import Test.QuickCheck
  
  import AST.V0_16
  import AST.Module (Module)
  import qualified AST.Module
  import AST.Structure
  import qualified AST.Listing
  import Data.Functor.Identity
  import qualified Data.Indexed as I
  import qualified Reporting.Annotation
  
  
  capitalLetter :: Gen Char
  capitalLetter =
      elements "ABCDEFGHIJKLMNOPQRSTUVWXYZÀΩЉԱႠḀℇ𐐅𝐴𝞨"
      -- Should also be capital, but Data.Char.isUpper does not agree: Ꭳ
  
  
  capitalAscii :: Gen Char
  capitalAscii =
      elements "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  
  
  lowerLetter :: Gen Char
  lowerLetter =
      elements "abcdefghijklmnopqrstuvwxyz"
  
  
  number :: Gen Char
  number =
      elements "0123456789"
  
  
  capIdentifier :: Gen UppercaseIdentifier
  capIdentifier =
      do
          first <- capitalLetter
          rest <- listOf $ oneof [ capitalLetter, lowerLetter, number ]
          return $ UppercaseIdentifier $ first:rest
  
  
  lowerIdentifier :: Gen LowercaseIdentifier
  lowerIdentifier =
      do
          first <- lowerLetter
          rest <- listOf $ oneof [ capitalLetter, lowerLetter, number ]
          return $ LowercaseIdentifier $ first:rest
  
  
  commented :: Gen a -> Gen (C2 before after a)
  commented inner =
      C ([], []) <$> inner
  
  
  instance Arbitrary AST.Listing.Value where
      arbitrary =
          do
              name <- capIdentifier
              return $ AST.Listing.Union (C [] name) AST.Listing.ClosedListing
  
  
  listing :: Gen (AST.Listing.Listing a)
  listing =
      return $ AST.Listing.OpenListing (C ([], []) ())
  
  
  instance Arbitrary (Module [UppercaseIdentifier] (ASTNS Identity [UppercaseIdentifier] 'TopLevelNK)) where
      arbitrary =
          do
              name <- listOf1 $ capIdentifier
              listing <- listing
              moduleType <- fmap (\x -> if x then AST.Module.Port [] else AST.Module.Normal) arbitrary
              return $ AST.Module.Module
                  []
                  (Just $ AST.Module.Header
                    moduleType
                    (C ([], []) name)
                    Nothing
                    (Just $ C ([], []) listing)
                  )
                  (Reporting.Annotation.at (Reporting.Annotation.Position 0 0) (Reporting.Annotation.Position 0 0) Nothing)
                  (C [] empty)
                  (I.Fix $ pure $ TopLevel [ Entry $ I.Fix $ pure $ CommonDeclaration $ I.Fix $ pure $ Definition (I.Fix $ pure $ Anything) [] [] (I.Fix $ pure $ TupleFunction 2)])
  