{-# LANGUAGE DeriveTraversable #-}

{- |
Module      : Language.Egison.AST
Licence     : MIT

This module defines the syntax of Egison.
-}

module Language.Egison.AST
  ( TopExpr (..)
  , ConstantExpr (..)
  , Expr (..)
  , Pattern (..)
  , VarWithIndices (..)
  , makeApply
  , Arg (..)
  , ArgPattern (..)
  , IndexExpr (..)
  , VarIndex (..)
  , PMMode (..)
  , BindingExpr (..)
  , MatchClause
  , PatternDef (..)
  , LoopRange (..)
  , PrimitivePatPattern (..)
  , PDPatternBase (..)
  , PrimitiveDataPattern
  , Op (..)
  , Assoc (..)
  , reservedExprOp
  , reservedPatternOp
  , findOpFrom
  , stringToVarWithIndices
  , extractNameFromVarWithIndices
  -- Type annotations
  , TypeExpr (..)
  , TensorShapeExpr (..)
  , ShapeDim (..)
  , TensorIndexExpr (..)
  , TypedParam (..)
  , TypedVarWithIndices (..)
  -- Inductive data types
  , InductiveConstructor (..)
  -- Pattern inductive types
  , PatternConstructor (..)
  -- Type classes
  , ClassDecl (..)
  , ClassMethod (..)
  , InstanceDecl (..)
  , InstanceMethod (..)
  , ConstraintExpr (..)
  ) where

import           Data.List  (find)
import           Data.Maybe (fromJust)
import           Data.Text  (Text)

data TopExpr
  = Define VarWithIndices Expr
  | DefineWithType TypedVarWithIndices Expr  -- ^ Definition with type annotation
  | Test Expr
  | Execute Expr
    -- temporary : we will replace load to import and export
  | LoadFile String
  | Load String
  | InfixDecl Bool Op -- True for pattern infix; False for expression infix
  | InductiveDecl String [String] [InductiveConstructor]
    -- ^ Inductive data type declaration with type parameters
    -- e.g., inductive Ordering := | Less | Equal | Greater
    --       inductive Maybe a := | Nothing | Just a
    -- String: type name, [String]: type parameters, [InductiveConstructor]: constructors
  | ClassDeclExpr ClassDecl
    -- ^ Type class declaration
    -- e.g., class Eq a where (==) (x: a) (y: a) : Bool
  | InstanceDeclExpr InstanceDecl
    -- ^ Type class instance declaration
    -- e.g., instance Eq Integer where (==) x y := x = y
  | PatternInductiveDecl String [String] [PatternConstructor]
    -- ^ Pattern inductive type declaration
    -- e.g., inductive pattern MyList a := | myNil | myCons a (MyList a)
    -- String: pattern type name, [String]: type parameters, [PatternConstructor]: constructors
  | PatternFunctionDecl String [String] [(String, TypeExpr)] TypeExpr Pattern
    -- ^ Pattern function declaration
    -- e.g., def pattern twin {a} (p1 : a) (p2 : MyList a) : MyList a := ...
    -- String: function name, [String]: type parameters, [(String, TypeExpr)]: parameters, TypeExpr: return type, Pattern: body
  | DeclareSymbol [String] (Maybe TypeExpr)
    -- ^ Symbol declaration
    -- e.g., declare symbol a11, a12, a21, a22
    --       declare symbol x, y, z : Float
    -- [String]: symbol names, Maybe TypeExpr: optional type (defaults to Integer)
 deriving Int -> TopExpr -> ShowS
[TopExpr] -> ShowS
TopExpr -> String
(Int -> TopExpr -> ShowS)
-> (TopExpr -> String) -> ([TopExpr] -> ShowS) -> Show TopExpr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TopExpr -> ShowS
showsPrec :: Int -> TopExpr -> ShowS
$cshow :: TopExpr -> String
show :: TopExpr -> String
$cshowList :: [TopExpr] -> ShowS
showList :: [TopExpr] -> ShowS
Show

-- | Type class declaration
-- e.g., class Eq a where ...
--       class Eq a => Ord a where ...
data ClassDecl = ClassDecl
  { ClassDecl -> String
className       :: String           -- ^ Class name (e.g., "Eq", "Ord")
  , ClassDecl -> [String]
classTypeParams :: [String]         -- ^ Type parameters (e.g., ["a"])
  , ClassDecl -> [ConstraintExpr]
classSuperclasses :: [ConstraintExpr] -- ^ Superclass constraints (e.g., [Eq a] for Ord)
  , ClassDecl -> [ClassMethod]
classMethods    :: [ClassMethod]    -- ^ Method declarations
  } deriving Int -> ClassDecl -> ShowS
[ClassDecl] -> ShowS
ClassDecl -> String
(Int -> ClassDecl -> ShowS)
-> (ClassDecl -> String)
-> ([ClassDecl] -> ShowS)
-> Show ClassDecl
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ClassDecl -> ShowS
showsPrec :: Int -> ClassDecl -> ShowS
$cshow :: ClassDecl -> String
show :: ClassDecl -> String
$cshowList :: [ClassDecl] -> ShowS
showList :: [ClassDecl] -> ShowS
Show

-- | Type class method declaration
-- e.g., (==) (x: a) (y: a) : Bool
--       (/=) (x: a) (y: a) : Bool := not (x == y)
data ClassMethod = ClassMethod
  { ClassMethod -> String
methodName    :: String             -- ^ Method name (e.g., "==")
  , ClassMethod -> [TypedParam]
methodParams  :: [TypedParam]       -- ^ Method parameters with types
  , ClassMethod -> TypeExpr
methodRetType :: TypeExpr           -- ^ Return type
  , ClassMethod -> Maybe Expr
methodDefault :: Maybe Expr         -- ^ Optional default implementation
  } deriving Int -> ClassMethod -> ShowS
[ClassMethod] -> ShowS
ClassMethod -> String
(Int -> ClassMethod -> ShowS)
-> (ClassMethod -> String)
-> ([ClassMethod] -> ShowS)
-> Show ClassMethod
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ClassMethod -> ShowS
showsPrec :: Int -> ClassMethod -> ShowS
$cshow :: ClassMethod -> String
show :: ClassMethod -> String
$cshowList :: [ClassMethod] -> ShowS
showList :: [ClassMethod] -> ShowS
Show

-- | Type class instance declaration
-- e.g., instance Eq Integer where ...
--       instance Eq a => Eq [a] where ...
data InstanceDecl = InstanceDecl
  { InstanceDecl -> [ConstraintExpr]
instanceConstraints :: [ConstraintExpr] -- ^ Instance constraints (e.g., [Eq a] for Eq [a])
  , InstanceDecl -> String
instanceClass       :: String           -- ^ Class name (e.g., "Eq")
  , InstanceDecl -> [TypeExpr]
instanceTypes       :: [TypeExpr]       -- ^ Instance types (e.g., [Integer] or [[a]])
  , InstanceDecl -> [InstanceMethod]
instanceMethods     :: [InstanceMethod] -- ^ Method implementations
  } deriving Int -> InstanceDecl -> ShowS
[InstanceDecl] -> ShowS
InstanceDecl -> String
(Int -> InstanceDecl -> ShowS)
-> (InstanceDecl -> String)
-> ([InstanceDecl] -> ShowS)
-> Show InstanceDecl
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InstanceDecl -> ShowS
showsPrec :: Int -> InstanceDecl -> ShowS
$cshow :: InstanceDecl -> String
show :: InstanceDecl -> String
$cshowList :: [InstanceDecl] -> ShowS
showList :: [InstanceDecl] -> ShowS
Show

-- | Instance method implementation
-- e.g., (==) x y := x = y
data InstanceMethod = InstanceMethod
  { InstanceMethod -> String
instMethodName   :: String          -- ^ Method name
  , InstanceMethod -> [String]
instMethodParams :: [String]        -- ^ Parameter names
  , InstanceMethod -> Expr
instMethodBody   :: Expr            -- ^ Method body
  } deriving Int -> InstanceMethod -> ShowS
[InstanceMethod] -> ShowS
InstanceMethod -> String
(Int -> InstanceMethod -> ShowS)
-> (InstanceMethod -> String)
-> ([InstanceMethod] -> ShowS)
-> Show InstanceMethod
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InstanceMethod -> ShowS
showsPrec :: Int -> InstanceMethod -> ShowS
$cshow :: InstanceMethod -> String
show :: InstanceMethod -> String
$cshowList :: [InstanceMethod] -> ShowS
showList :: [InstanceMethod] -> ShowS
Show

-- | Type constraint expression
-- e.g., Eq a, Ord a
data ConstraintExpr = ConstraintExpr
  { ConstraintExpr -> String
constraintClass :: String           -- ^ Class name
  , ConstraintExpr -> [TypeExpr]
constraintTypes :: [TypeExpr]       -- ^ Type arguments
  } deriving (Int -> ConstraintExpr -> ShowS
[ConstraintExpr] -> ShowS
ConstraintExpr -> String
(Int -> ConstraintExpr -> ShowS)
-> (ConstraintExpr -> String)
-> ([ConstraintExpr] -> ShowS)
-> Show ConstraintExpr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ConstraintExpr -> ShowS
showsPrec :: Int -> ConstraintExpr -> ShowS
$cshow :: ConstraintExpr -> String
show :: ConstraintExpr -> String
$cshowList :: [ConstraintExpr] -> ShowS
showList :: [ConstraintExpr] -> ShowS
Show, ConstraintExpr -> ConstraintExpr -> Bool
(ConstraintExpr -> ConstraintExpr -> Bool)
-> (ConstraintExpr -> ConstraintExpr -> Bool) -> Eq ConstraintExpr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ConstraintExpr -> ConstraintExpr -> Bool
== :: ConstraintExpr -> ConstraintExpr -> Bool
$c/= :: ConstraintExpr -> ConstraintExpr -> Bool
/= :: ConstraintExpr -> ConstraintExpr -> Bool
Eq)

-- | Constructor for inductive data type
-- e.g., Less, S Nat, Node Tree Tree
data InductiveConstructor = InductiveConstructor
  { InductiveConstructor -> String
inductiveCtorName :: String      -- ^ Constructor name (e.g., "Less", "S", "Node")
  , InductiveConstructor -> [TypeExpr]
inductiveCtorArgs :: [TypeExpr]  -- ^ Constructor argument types (e.g., [], [Nat], [Tree, Tree])
  } deriving (Int -> InductiveConstructor -> ShowS
[InductiveConstructor] -> ShowS
InductiveConstructor -> String
(Int -> InductiveConstructor -> ShowS)
-> (InductiveConstructor -> String)
-> ([InductiveConstructor] -> ShowS)
-> Show InductiveConstructor
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InductiveConstructor -> ShowS
showsPrec :: Int -> InductiveConstructor -> ShowS
$cshow :: InductiveConstructor -> String
show :: InductiveConstructor -> String
$cshowList :: [InductiveConstructor] -> ShowS
showList :: [InductiveConstructor] -> ShowS
Show, InductiveConstructor -> InductiveConstructor -> Bool
(InductiveConstructor -> InductiveConstructor -> Bool)
-> (InductiveConstructor -> InductiveConstructor -> Bool)
-> Eq InductiveConstructor
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: InductiveConstructor -> InductiveConstructor -> Bool
== :: InductiveConstructor -> InductiveConstructor -> Bool
$c/= :: InductiveConstructor -> InductiveConstructor -> Bool
/= :: InductiveConstructor -> InductiveConstructor -> Bool
Eq)

-- | Constructor for pattern inductive type
-- e.g., myNil, myCons a (MyList a)
data PatternConstructor = PatternConstructor
  { PatternConstructor -> String
patternCtorName :: String      -- ^ Pattern constructor name (e.g., "myNil", "myCons")
  , PatternConstructor -> [TypeExpr]
patternCtorArgs :: [TypeExpr]  -- ^ Pattern constructor argument types (e.g., [], [a, MyList a])
  } deriving (Int -> PatternConstructor -> ShowS
[PatternConstructor] -> ShowS
PatternConstructor -> String
(Int -> PatternConstructor -> ShowS)
-> (PatternConstructor -> String)
-> ([PatternConstructor] -> ShowS)
-> Show PatternConstructor
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PatternConstructor -> ShowS
showsPrec :: Int -> PatternConstructor -> ShowS
$cshow :: PatternConstructor -> String
show :: PatternConstructor -> String
$cshowList :: [PatternConstructor] -> ShowS
showList :: [PatternConstructor] -> ShowS
Show, PatternConstructor -> PatternConstructor -> Bool
(PatternConstructor -> PatternConstructor -> Bool)
-> (PatternConstructor -> PatternConstructor -> Bool)
-> Eq PatternConstructor
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PatternConstructor -> PatternConstructor -> Bool
== :: PatternConstructor -> PatternConstructor -> Bool
$c/= :: PatternConstructor -> PatternConstructor -> Bool
/= :: PatternConstructor -> PatternConstructor -> Bool
Eq)

data ConstantExpr
  = CharExpr Char
  | StringExpr Text
  | BoolExpr Bool
  | IntegerExpr Integer
  | FloatExpr Double
  | SomethingExpr
  | UndefinedExpr
  deriving Int -> ConstantExpr -> ShowS
[ConstantExpr] -> ShowS
ConstantExpr -> String
(Int -> ConstantExpr -> ShowS)
-> (ConstantExpr -> String)
-> ([ConstantExpr] -> ShowS)
-> Show ConstantExpr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ConstantExpr -> ShowS
showsPrec :: Int -> ConstantExpr -> ShowS
$cshow :: ConstantExpr -> String
show :: ConstantExpr -> String
$cshowList :: [ConstantExpr] -> ShowS
showList :: [ConstantExpr] -> ShowS
Show

data Expr
  = ConstantExpr ConstantExpr
  | VarExpr String
  | FreshVarExpr
  | IndexedExpr Bool Expr [IndexExpr Expr]  -- True -> delete old index and append new one
  | SubrefsExpr Bool Expr Expr
  | SuprefsExpr Bool Expr Expr
  | UserrefsExpr Bool Expr Expr
  | TupleExpr [Expr]
  | CollectionExpr [Expr]
  | ConsExpr Expr Expr
  | JoinExpr Expr Expr
  | HashExpr [(Expr, Expr)]
  | VectorExpr [Expr]

  | LambdaExpr [Arg ArgPattern] Expr
  | LambdaExpr' [Arg VarWithIndices] Expr
  | TypedLambdaExpr [(String, TypeExpr)] TypeExpr Expr  -- ^ Lambda with typed parameters and return type
  | MemoizedLambdaExpr [String] Expr
  | TypedMemoizedLambdaExpr [TypedParam] TypeExpr Expr  -- ^ Memoized lambda with typed parameters
  | CambdaExpr String Expr
  | PatternFunctionExpr [String] Pattern

  | IfExpr Expr Expr Expr
  | LetExpr [BindingExpr] Expr
  | LetRecExpr [BindingExpr] Expr
  | WithSymbolsExpr [String] Expr

  | MatchExpr PMMode Expr Expr [MatchClause]
  | MatchAllExpr PMMode Expr Expr [MatchClause]
  | MatchLambdaExpr Expr [MatchClause]
  | MatchAllLambdaExpr Expr [MatchClause]

  | MatcherExpr [PatternDef]
  | AlgebraicDataMatcherExpr [(String, [Expr])]

  | QuoteExpr Expr
  | QuoteSymbolExpr Expr
  | WedgeApplyExpr Expr [Expr]

  | DoExpr [BindingExpr] Expr

  | PrefixExpr String Expr
  | InfixExpr Op Expr Expr
  | SectionExpr Op (Maybe Expr) (Maybe Expr) -- There cannot be 'SectionExpr op (Just _) (Just _)'

  | SeqExpr Expr Expr
  | ApplyExpr Expr [Expr]
  | AnonParamFuncExpr Integer Expr      -- e.g. 2#2, 3#$1, 2#($1 + $2)
  | AnonTupleParamFuncExpr Integer Expr -- e.g. (2)#2, (3)#$1, (2)#($1 + $2)
  | AnonListParamFuncExpr Integer Expr  -- e.g. [2]#2, [3]#$1, [2]#($1 + $2)
  | AnonParamExpr Integer               -- e.g. $1, $2

  | GenerateTensorExpr Expr Expr
  | TensorExpr Expr Expr
  | TensorContractExpr Expr
  | TensorMapExpr Expr Expr
  | TensorMap2Expr Expr Expr Expr
  | TransposeExpr Expr Expr
  | FlipIndicesExpr Expr

  | FunctionExpr [String]

  | TypeAnnotation Expr TypeExpr  -- ^ Expression with type annotation (expr : type)
  deriving Int -> Expr -> ShowS
[Expr] -> ShowS
Expr -> String
(Int -> Expr -> ShowS)
-> (Expr -> String) -> ([Expr] -> ShowS) -> Show Expr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Expr -> ShowS
showsPrec :: Int -> Expr -> ShowS
$cshow :: Expr -> String
show :: Expr -> String
$cshowList :: [Expr] -> ShowS
showList :: [Expr] -> ShowS
Show

data VarWithIndices = VarWithIndices String [VarIndex]
  deriving (Int -> VarWithIndices -> ShowS
[VarWithIndices] -> ShowS
VarWithIndices -> String
(Int -> VarWithIndices -> ShowS)
-> (VarWithIndices -> String)
-> ([VarWithIndices] -> ShowS)
-> Show VarWithIndices
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> VarWithIndices -> ShowS
showsPrec :: Int -> VarWithIndices -> ShowS
$cshow :: VarWithIndices -> String
show :: VarWithIndices -> String
$cshowList :: [VarWithIndices] -> ShowS
showList :: [VarWithIndices] -> ShowS
Show, VarWithIndices -> VarWithIndices -> Bool
(VarWithIndices -> VarWithIndices -> Bool)
-> (VarWithIndices -> VarWithIndices -> Bool) -> Eq VarWithIndices
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: VarWithIndices -> VarWithIndices -> Bool
== :: VarWithIndices -> VarWithIndices -> Bool
$c/= :: VarWithIndices -> VarWithIndices -> Bool
/= :: VarWithIndices -> VarWithIndices -> Bool
Eq)

data Arg a
  = Arg a
  | InvertedArg a
  deriving Int -> Arg a -> ShowS
[Arg a] -> ShowS
Arg a -> String
(Int -> Arg a -> ShowS)
-> (Arg a -> String) -> ([Arg a] -> ShowS) -> Show (Arg a)
forall a. Show a => Int -> Arg a -> ShowS
forall a. Show a => [Arg a] -> ShowS
forall a. Show a => Arg a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Arg a -> ShowS
showsPrec :: Int -> Arg a -> ShowS
$cshow :: forall a. Show a => Arg a -> String
show :: Arg a -> String
$cshowList :: forall a. Show a => [Arg a] -> ShowS
showList :: [Arg a] -> ShowS
Show

data ArgPattern
  = APWildCard
  | APPatVar VarWithIndices
  | APInductivePat String [Arg ArgPattern]
  | APTuplePat [Arg ArgPattern]
  | APEmptyPat
  | APConsPat (Arg ArgPattern) ArgPattern
  | APSnocPat ArgPattern (Arg ArgPattern)
  deriving Int -> ArgPattern -> ShowS
[ArgPattern] -> ShowS
ArgPattern -> String
(Int -> ArgPattern -> ShowS)
-> (ArgPattern -> String)
-> ([ArgPattern] -> ShowS)
-> Show ArgPattern
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ArgPattern -> ShowS
showsPrec :: Int -> ArgPattern -> ShowS
$cshow :: ArgPattern -> String
show :: ArgPattern -> String
$cshowList :: [ArgPattern] -> ShowS
showList :: [ArgPattern] -> ShowS
Show

data VarIndex
  = VSubscript String
  | VSuperscript String
  | VMultiSubscript String Integer String   -- _(a_1)..._(a_n) -> VMultiSubscript "a" 1 "n"
  | VMultiSuperscript String Integer String -- ~(a_1)...~(a_n) -> VMultiSuperscript "a" 1 "n"
  | VGroupScripts [VarIndex]
  | VSymmScripts [VarIndex]
  | VAntiSymmScripts [VarIndex]
  deriving (Int -> VarIndex -> ShowS
[VarIndex] -> ShowS
VarIndex -> String
(Int -> VarIndex -> ShowS)
-> (VarIndex -> String) -> ([VarIndex] -> ShowS) -> Show VarIndex
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> VarIndex -> ShowS
showsPrec :: Int -> VarIndex -> ShowS
$cshow :: VarIndex -> String
show :: VarIndex -> String
$cshowList :: [VarIndex] -> ShowS
showList :: [VarIndex] -> ShowS
Show, VarIndex -> VarIndex -> Bool
(VarIndex -> VarIndex -> Bool)
-> (VarIndex -> VarIndex -> Bool) -> Eq VarIndex
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: VarIndex -> VarIndex -> Bool
== :: VarIndex -> VarIndex -> Bool
$c/= :: VarIndex -> VarIndex -> Bool
/= :: VarIndex -> VarIndex -> Bool
Eq)

data IndexExpr a
  = Subscript a
  | Superscript a
  | SupSubscript a
  | MultiSubscript a a
  | MultiSuperscript a a
  | Userscript a
  deriving (Int -> IndexExpr a -> ShowS
[IndexExpr a] -> ShowS
IndexExpr a -> String
(Int -> IndexExpr a -> ShowS)
-> (IndexExpr a -> String)
-> ([IndexExpr a] -> ShowS)
-> Show (IndexExpr a)
forall a. Show a => Int -> IndexExpr a -> ShowS
forall a. Show a => [IndexExpr a] -> ShowS
forall a. Show a => IndexExpr a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> IndexExpr a -> ShowS
showsPrec :: Int -> IndexExpr a -> ShowS
$cshow :: forall a. Show a => IndexExpr a -> String
show :: IndexExpr a -> String
$cshowList :: forall a. Show a => [IndexExpr a] -> ShowS
showList :: [IndexExpr a] -> ShowS
Show, IndexExpr a -> IndexExpr a -> Bool
(IndexExpr a -> IndexExpr a -> Bool)
-> (IndexExpr a -> IndexExpr a -> Bool) -> Eq (IndexExpr a)
forall a. Eq a => IndexExpr a -> IndexExpr a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => IndexExpr a -> IndexExpr a -> Bool
== :: IndexExpr a -> IndexExpr a -> Bool
$c/= :: forall a. Eq a => IndexExpr a -> IndexExpr a -> Bool
/= :: IndexExpr a -> IndexExpr a -> Bool
Eq, (forall a b. (a -> b) -> IndexExpr a -> IndexExpr b)
-> (forall a b. a -> IndexExpr b -> IndexExpr a)
-> Functor IndexExpr
forall a b. a -> IndexExpr b -> IndexExpr a
forall a b. (a -> b) -> IndexExpr a -> IndexExpr b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> IndexExpr a -> IndexExpr b
fmap :: forall a b. (a -> b) -> IndexExpr a -> IndexExpr b
$c<$ :: forall a b. a -> IndexExpr b -> IndexExpr a
<$ :: forall a b. a -> IndexExpr b -> IndexExpr a
Functor, (forall m. Monoid m => IndexExpr m -> m)
-> (forall m a. Monoid m => (a -> m) -> IndexExpr a -> m)
-> (forall m a. Monoid m => (a -> m) -> IndexExpr a -> m)
-> (forall a b. (a -> b -> b) -> b -> IndexExpr a -> b)
-> (forall a b. (a -> b -> b) -> b -> IndexExpr a -> b)
-> (forall b a. (b -> a -> b) -> b -> IndexExpr a -> b)
-> (forall b a. (b -> a -> b) -> b -> IndexExpr a -> b)
-> (forall a. (a -> a -> a) -> IndexExpr a -> a)
-> (forall a. (a -> a -> a) -> IndexExpr a -> a)
-> (forall a. IndexExpr a -> [a])
-> (forall a. IndexExpr a -> Bool)
-> (forall a. IndexExpr a -> Int)
-> (forall a. Eq a => a -> IndexExpr a -> Bool)
-> (forall a. Ord a => IndexExpr a -> a)
-> (forall a. Ord a => IndexExpr a -> a)
-> (forall a. Num a => IndexExpr a -> a)
-> (forall a. Num a => IndexExpr a -> a)
-> Foldable IndexExpr
forall a. Eq a => a -> IndexExpr a -> Bool
forall a. Num a => IndexExpr a -> a
forall a. Ord a => IndexExpr a -> a
forall m. Monoid m => IndexExpr m -> m
forall a. IndexExpr a -> Bool
forall a. IndexExpr a -> Int
forall a. IndexExpr a -> [a]
forall a. (a -> a -> a) -> IndexExpr a -> a
forall m a. Monoid m => (a -> m) -> IndexExpr a -> m
forall b a. (b -> a -> b) -> b -> IndexExpr a -> b
forall a b. (a -> b -> b) -> b -> IndexExpr a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
$cfold :: forall m. Monoid m => IndexExpr m -> m
fold :: forall m. Monoid m => IndexExpr m -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> IndexExpr a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> IndexExpr a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> IndexExpr a -> m
foldMap' :: forall m a. Monoid m => (a -> m) -> IndexExpr a -> m
$cfoldr :: forall a b. (a -> b -> b) -> b -> IndexExpr a -> b
foldr :: forall a b. (a -> b -> b) -> b -> IndexExpr a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> IndexExpr a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> IndexExpr a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> IndexExpr a -> b
foldl :: forall b a. (b -> a -> b) -> b -> IndexExpr a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> IndexExpr a -> b
foldl' :: forall b a. (b -> a -> b) -> b -> IndexExpr a -> b
$cfoldr1 :: forall a. (a -> a -> a) -> IndexExpr a -> a
foldr1 :: forall a. (a -> a -> a) -> IndexExpr a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> IndexExpr a -> a
foldl1 :: forall a. (a -> a -> a) -> IndexExpr a -> a
$ctoList :: forall a. IndexExpr a -> [a]
toList :: forall a. IndexExpr a -> [a]
$cnull :: forall a. IndexExpr a -> Bool
null :: forall a. IndexExpr a -> Bool
$clength :: forall a. IndexExpr a -> Int
length :: forall a. IndexExpr a -> Int
$celem :: forall a. Eq a => a -> IndexExpr a -> Bool
elem :: forall a. Eq a => a -> IndexExpr a -> Bool
$cmaximum :: forall a. Ord a => IndexExpr a -> a
maximum :: forall a. Ord a => IndexExpr a -> a
$cminimum :: forall a. Ord a => IndexExpr a -> a
minimum :: forall a. Ord a => IndexExpr a -> a
$csum :: forall a. Num a => IndexExpr a -> a
sum :: forall a. Num a => IndexExpr a -> a
$cproduct :: forall a. Num a => IndexExpr a -> a
product :: forall a. Num a => IndexExpr a -> a
Foldable, Functor IndexExpr
Foldable IndexExpr
(Functor IndexExpr, Foldable IndexExpr) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> IndexExpr a -> f (IndexExpr b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    IndexExpr (f a) -> f (IndexExpr a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> IndexExpr a -> m (IndexExpr b))
-> (forall (m :: * -> *) a.
    Monad m =>
    IndexExpr (m a) -> m (IndexExpr a))
-> Traversable IndexExpr
forall (t :: * -> *).
(Functor t, Foldable t) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a.
Monad m =>
IndexExpr (m a) -> m (IndexExpr a)
forall (f :: * -> *) a.
Applicative f =>
IndexExpr (f a) -> f (IndexExpr a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> IndexExpr a -> m (IndexExpr b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> IndexExpr a -> f (IndexExpr b)
$ctraverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> IndexExpr a -> f (IndexExpr b)
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> IndexExpr a -> f (IndexExpr b)
$csequenceA :: forall (f :: * -> *) a.
Applicative f =>
IndexExpr (f a) -> f (IndexExpr a)
sequenceA :: forall (f :: * -> *) a.
Applicative f =>
IndexExpr (f a) -> f (IndexExpr a)
$cmapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> IndexExpr a -> m (IndexExpr b)
mapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> IndexExpr a -> m (IndexExpr b)
$csequence :: forall (m :: * -> *) a.
Monad m =>
IndexExpr (m a) -> m (IndexExpr a)
sequence :: forall (m :: * -> *) a.
Monad m =>
IndexExpr (m a) -> m (IndexExpr a)
Traversable)

data PMMode = BFSMode | DFSMode
  deriving Int -> PMMode -> ShowS
[PMMode] -> ShowS
PMMode -> String
(Int -> PMMode -> ShowS)
-> (PMMode -> String) -> ([PMMode] -> ShowS) -> Show PMMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PMMode -> ShowS
showsPrec :: Int -> PMMode -> ShowS
$cshow :: PMMode -> String
show :: PMMode -> String
$cshowList :: [PMMode] -> ShowS
showList :: [PMMode] -> ShowS
Show

data BindingExpr
  = Bind PrimitiveDataPattern Expr
  | BindWithIndices VarWithIndices Expr
  | BindWithType TypedVarWithIndices Expr  -- ^ Binding with type annotation (for where clauses)
  deriving Int -> BindingExpr -> ShowS
[BindingExpr] -> ShowS
BindingExpr -> String
(Int -> BindingExpr -> ShowS)
-> (BindingExpr -> String)
-> ([BindingExpr] -> ShowS)
-> Show BindingExpr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BindingExpr -> ShowS
showsPrec :: Int -> BindingExpr -> ShowS
$cshow :: BindingExpr -> String
show :: BindingExpr -> String
$cshowList :: [BindingExpr] -> ShowS
showList :: [BindingExpr] -> ShowS
Show

type MatchClause = (Pattern, Expr)

-- | Pattern definition in a matcher (with optional type class constraints)
data PatternDef = PatternDef
  { PatternDef -> PrimitivePatPattern
patDefPattern     :: PrimitivePatPattern
  , PatternDef -> Expr
patDefMatcher     :: Expr
  , PatternDef -> [(PrimitiveDataPattern, Expr)]
patDefClauses     :: [(PrimitiveDataPattern, Expr)]
  } deriving Int -> PatternDef -> ShowS
[PatternDef] -> ShowS
PatternDef -> String
(Int -> PatternDef -> ShowS)
-> (PatternDef -> String)
-> ([PatternDef] -> ShowS)
-> Show PatternDef
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PatternDef -> ShowS
showsPrec :: Int -> PatternDef -> ShowS
$cshow :: PatternDef -> String
show :: PatternDef -> String
$cshowList :: [PatternDef] -> ShowS
showList :: [PatternDef] -> ShowS
Show

data Pattern
  = WildCard
  | PatVar String
  | ValuePat Expr
  | PredPat Expr
  | IndexedPat Pattern [Expr]
  | LetPat [BindingExpr] Pattern
  | InfixPat Op Pattern Pattern -- Includes AndPat,OrPat,InductivePat(cons/join)
  | NotPat Pattern
  | AndPat Pattern Pattern
  | OrPat Pattern Pattern
  | ForallPat Pattern Pattern
  | TuplePat [Pattern]
  | InductivePat String [Pattern]
  | LoopPat String LoopRange Pattern Pattern
  | ContPat
  | PApplyPat Expr [Pattern]
  | VarPat String
  | InductiveOrPApplyPat String [Pattern]
  | SeqNilPat
  | SeqConsPat Pattern Pattern
  | LaterPatVar
  -- For symbolic computing
  | DApplyPat Pattern [Pattern]
  deriving Int -> Pattern -> ShowS
[Pattern] -> ShowS
Pattern -> String
(Int -> Pattern -> ShowS)
-> (Pattern -> String) -> ([Pattern] -> ShowS) -> Show Pattern
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Pattern -> ShowS
showsPrec :: Int -> Pattern -> ShowS
$cshow :: Pattern -> String
show :: Pattern -> String
$cshowList :: [Pattern] -> ShowS
showList :: [Pattern] -> ShowS
Show

data LoopRange = LoopRange Expr Expr Pattern
  deriving Int -> LoopRange -> ShowS
[LoopRange] -> ShowS
LoopRange -> String
(Int -> LoopRange -> ShowS)
-> (LoopRange -> String)
-> ([LoopRange] -> ShowS)
-> Show LoopRange
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LoopRange -> ShowS
showsPrec :: Int -> LoopRange -> ShowS
$cshow :: LoopRange -> String
show :: LoopRange -> String
$cshowList :: [LoopRange] -> ShowS
showList :: [LoopRange] -> ShowS
Show

data PrimitivePatPattern
  = PPWildCard
  | PPPatVar
  | PPValuePat String  -- Variable name
  | PPInductivePat String [PrimitivePatPattern]
  | PPTuplePat [PrimitivePatPattern]
  deriving Int -> PrimitivePatPattern -> ShowS
[PrimitivePatPattern] -> ShowS
PrimitivePatPattern -> String
(Int -> PrimitivePatPattern -> ShowS)
-> (PrimitivePatPattern -> String)
-> ([PrimitivePatPattern] -> ShowS)
-> Show PrimitivePatPattern
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PrimitivePatPattern -> ShowS
showsPrec :: Int -> PrimitivePatPattern -> ShowS
$cshow :: PrimitivePatPattern -> String
show :: PrimitivePatPattern -> String
$cshowList :: [PrimitivePatPattern] -> ShowS
showList :: [PrimitivePatPattern] -> ShowS
Show

data PDPatternBase var
  = PDWildCard
  | PDPatVar var
  | PDInductivePat String [PDPatternBase var]
  | PDTuplePat [PDPatternBase var]
  | PDEmptyPat
  | PDConsPat (PDPatternBase var) (PDPatternBase var)
  | PDSnocPat (PDPatternBase var) (PDPatternBase var)
  | PDConstantPat ConstantExpr
  -- ScalarData (MathExpr) primitive patterns
  | PDDivPat (PDPatternBase var) (PDPatternBase var)        -- Div: ScalarData -> PolyExpr, PolyExpr
  | PDPlusPat (PDPatternBase var)                           -- Plus: PolyExpr -> [TermExpr]
  | PDTermPat (PDPatternBase var) (PDPatternBase var)       -- Term: TermExpr -> Integer, [(SymbolExpr, Integer)]
  | PDSymbolPat (PDPatternBase var) (PDPatternBase var)     -- Symbol: SymbolExpr -> String, [IndexExpr]
  | PDApply1Pat (PDPatternBase var) (PDPatternBase var)     -- Apply1: SymbolExpr -> MathExpr, MathExpr
  | PDApply2Pat (PDPatternBase var) (PDPatternBase var) (PDPatternBase var) -- Apply2
  | PDApply3Pat (PDPatternBase var) (PDPatternBase var) (PDPatternBase var) (PDPatternBase var) -- Apply3
  | PDApply4Pat (PDPatternBase var) (PDPatternBase var) (PDPatternBase var) (PDPatternBase var) (PDPatternBase var) -- Apply4
  | PDQuotePat (PDPatternBase var)                          -- Quote: SymbolExpr -> MathExpr
  | PDFunctionPat (PDPatternBase var) (PDPatternBase var) -- Function: SymbolExpr -> MathExpr, [MathExpr]
  | PDSubPat (PDPatternBase var)                            -- Sub: IndexExpr -> MathExpr
  | PDSupPat (PDPatternBase var)                            -- Sup: IndexExpr -> MathExpr
  | PDUserPat (PDPatternBase var)                           -- User: IndexExpr -> MathExpr
  deriving ((forall a b. (a -> b) -> PDPatternBase a -> PDPatternBase b)
-> (forall a b. a -> PDPatternBase b -> PDPatternBase a)
-> Functor PDPatternBase
forall a b. a -> PDPatternBase b -> PDPatternBase a
forall a b. (a -> b) -> PDPatternBase a -> PDPatternBase b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> PDPatternBase a -> PDPatternBase b
fmap :: forall a b. (a -> b) -> PDPatternBase a -> PDPatternBase b
$c<$ :: forall a b. a -> PDPatternBase b -> PDPatternBase a
<$ :: forall a b. a -> PDPatternBase b -> PDPatternBase a
Functor, (forall m. Monoid m => PDPatternBase m -> m)
-> (forall m a. Monoid m => (a -> m) -> PDPatternBase a -> m)
-> (forall m a. Monoid m => (a -> m) -> PDPatternBase a -> m)
-> (forall a b. (a -> b -> b) -> b -> PDPatternBase a -> b)
-> (forall a b. (a -> b -> b) -> b -> PDPatternBase a -> b)
-> (forall b a. (b -> a -> b) -> b -> PDPatternBase a -> b)
-> (forall b a. (b -> a -> b) -> b -> PDPatternBase a -> b)
-> (forall a. (a -> a -> a) -> PDPatternBase a -> a)
-> (forall a. (a -> a -> a) -> PDPatternBase a -> a)
-> (forall a. PDPatternBase a -> [a])
-> (forall a. PDPatternBase a -> Bool)
-> (forall a. PDPatternBase a -> Int)
-> (forall a. Eq a => a -> PDPatternBase a -> Bool)
-> (forall a. Ord a => PDPatternBase a -> a)
-> (forall a. Ord a => PDPatternBase a -> a)
-> (forall a. Num a => PDPatternBase a -> a)
-> (forall a. Num a => PDPatternBase a -> a)
-> Foldable PDPatternBase
forall a. Eq a => a -> PDPatternBase a -> Bool
forall a. Num a => PDPatternBase a -> a
forall a. Ord a => PDPatternBase a -> a
forall m. Monoid m => PDPatternBase m -> m
forall a. PDPatternBase a -> Bool
forall a. PDPatternBase a -> Int
forall a. PDPatternBase a -> [a]
forall a. (a -> a -> a) -> PDPatternBase a -> a
forall m a. Monoid m => (a -> m) -> PDPatternBase a -> m
forall b a. (b -> a -> b) -> b -> PDPatternBase a -> b
forall a b. (a -> b -> b) -> b -> PDPatternBase a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
$cfold :: forall m. Monoid m => PDPatternBase m -> m
fold :: forall m. Monoid m => PDPatternBase m -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> PDPatternBase a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> PDPatternBase a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> PDPatternBase a -> m
foldMap' :: forall m a. Monoid m => (a -> m) -> PDPatternBase a -> m
$cfoldr :: forall a b. (a -> b -> b) -> b -> PDPatternBase a -> b
foldr :: forall a b. (a -> b -> b) -> b -> PDPatternBase a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> PDPatternBase a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> PDPatternBase a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> PDPatternBase a -> b
foldl :: forall b a. (b -> a -> b) -> b -> PDPatternBase a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> PDPatternBase a -> b
foldl' :: forall b a. (b -> a -> b) -> b -> PDPatternBase a -> b
$cfoldr1 :: forall a. (a -> a -> a) -> PDPatternBase a -> a
foldr1 :: forall a. (a -> a -> a) -> PDPatternBase a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> PDPatternBase a -> a
foldl1 :: forall a. (a -> a -> a) -> PDPatternBase a -> a
$ctoList :: forall a. PDPatternBase a -> [a]
toList :: forall a. PDPatternBase a -> [a]
$cnull :: forall a. PDPatternBase a -> Bool
null :: forall a. PDPatternBase a -> Bool
$clength :: forall a. PDPatternBase a -> Int
length :: forall a. PDPatternBase a -> Int
$celem :: forall a. Eq a => a -> PDPatternBase a -> Bool
elem :: forall a. Eq a => a -> PDPatternBase a -> Bool
$cmaximum :: forall a. Ord a => PDPatternBase a -> a
maximum :: forall a. Ord a => PDPatternBase a -> a
$cminimum :: forall a. Ord a => PDPatternBase a -> a
minimum :: forall a. Ord a => PDPatternBase a -> a
$csum :: forall a. Num a => PDPatternBase a -> a
sum :: forall a. Num a => PDPatternBase a -> a
$cproduct :: forall a. Num a => PDPatternBase a -> a
product :: forall a. Num a => PDPatternBase a -> a
Foldable, Int -> PDPatternBase var -> ShowS
[PDPatternBase var] -> ShowS
PDPatternBase var -> String
(Int -> PDPatternBase var -> ShowS)
-> (PDPatternBase var -> String)
-> ([PDPatternBase var] -> ShowS)
-> Show (PDPatternBase var)
forall var. Show var => Int -> PDPatternBase var -> ShowS
forall var. Show var => [PDPatternBase var] -> ShowS
forall var. Show var => PDPatternBase var -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall var. Show var => Int -> PDPatternBase var -> ShowS
showsPrec :: Int -> PDPatternBase var -> ShowS
$cshow :: forall var. Show var => PDPatternBase var -> String
show :: PDPatternBase var -> String
$cshowList :: forall var. Show var => [PDPatternBase var] -> ShowS
showList :: [PDPatternBase var] -> ShowS
Show)

type PrimitiveDataPattern = PDPatternBase String

data Op
  = Op { Op -> String
repr     :: String  -- syntastic representation
       , Op -> Int
priority :: Int
       , Op -> Assoc
assoc    :: Assoc
       , Op -> Bool
isWedge  :: Bool    -- True if operator is prefixed with '!'. Only used for expression infix.
       }
  deriving (Op -> Op -> Bool
(Op -> Op -> Bool) -> (Op -> Op -> Bool) -> Eq Op
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Op -> Op -> Bool
== :: Op -> Op -> Bool
$c/= :: Op -> Op -> Bool
/= :: Op -> Op -> Bool
Eq, Eq Op
Eq Op =>
(Op -> Op -> Ordering)
-> (Op -> Op -> Bool)
-> (Op -> Op -> Bool)
-> (Op -> Op -> Bool)
-> (Op -> Op -> Bool)
-> (Op -> Op -> Op)
-> (Op -> Op -> Op)
-> Ord Op
Op -> Op -> Bool
Op -> Op -> Ordering
Op -> Op -> Op
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Op -> Op -> Ordering
compare :: Op -> Op -> Ordering
$c< :: Op -> Op -> Bool
< :: Op -> Op -> Bool
$c<= :: Op -> Op -> Bool
<= :: Op -> Op -> Bool
$c> :: Op -> Op -> Bool
> :: Op -> Op -> Bool
$c>= :: Op -> Op -> Bool
>= :: Op -> Op -> Bool
$cmax :: Op -> Op -> Op
max :: Op -> Op -> Op
$cmin :: Op -> Op -> Op
min :: Op -> Op -> Op
Ord, Int -> Op -> ShowS
[Op] -> ShowS
Op -> String
(Int -> Op -> ShowS)
-> (Op -> String) -> ([Op] -> ShowS) -> Show Op
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Op -> ShowS
showsPrec :: Int -> Op -> ShowS
$cshow :: Op -> String
show :: Op -> String
$cshowList :: [Op] -> ShowS
showList :: [Op] -> ShowS
Show)

data Assoc
  = InfixL
  | InfixR
  | InfixN
  | Prefix
  deriving (Assoc -> Assoc -> Bool
(Assoc -> Assoc -> Bool) -> (Assoc -> Assoc -> Bool) -> Eq Assoc
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Assoc -> Assoc -> Bool
== :: Assoc -> Assoc -> Bool
$c/= :: Assoc -> Assoc -> Bool
/= :: Assoc -> Assoc -> Bool
Eq, Eq Assoc
Eq Assoc =>
(Assoc -> Assoc -> Ordering)
-> (Assoc -> Assoc -> Bool)
-> (Assoc -> Assoc -> Bool)
-> (Assoc -> Assoc -> Bool)
-> (Assoc -> Assoc -> Bool)
-> (Assoc -> Assoc -> Assoc)
-> (Assoc -> Assoc -> Assoc)
-> Ord Assoc
Assoc -> Assoc -> Bool
Assoc -> Assoc -> Ordering
Assoc -> Assoc -> Assoc
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Assoc -> Assoc -> Ordering
compare :: Assoc -> Assoc -> Ordering
$c< :: Assoc -> Assoc -> Bool
< :: Assoc -> Assoc -> Bool
$c<= :: Assoc -> Assoc -> Bool
<= :: Assoc -> Assoc -> Bool
$c> :: Assoc -> Assoc -> Bool
> :: Assoc -> Assoc -> Bool
$c>= :: Assoc -> Assoc -> Bool
>= :: Assoc -> Assoc -> Bool
$cmax :: Assoc -> Assoc -> Assoc
max :: Assoc -> Assoc -> Assoc
$cmin :: Assoc -> Assoc -> Assoc
min :: Assoc -> Assoc -> Assoc
Ord)

instance Show Assoc where
  show :: Assoc -> String
show Assoc
InfixL = String
"infixl"
  show Assoc
InfixR = String
"infixr"
  show Assoc
InfixN = String
"infix"
  show Assoc
Prefix = String
"prefix"

reservedExprOp :: [Op]
reservedExprOp :: [Op]
reservedExprOp =
  [ String -> Int -> Assoc -> Bool -> Op
Op String
"!"    Int
8 Assoc
Prefix Bool
False -- Wedge and InvertedArg prefix
  , String -> Int -> Assoc -> Bool -> Op
Op String
"-"    Int
7 Assoc
Prefix Bool
False -- Negate
  , String -> Int -> Assoc -> Bool -> Op
Op String
"%"    Int
7 Assoc
InfixL Bool
False -- primitive function
  , String -> Int -> Assoc -> Bool -> Op
Op String
"++"   Int
5 Assoc
InfixR Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"::"   Int
5 Assoc
InfixR Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"=="   Int
4 Assoc
InfixL Bool
False -- equality (from type class)
  , String -> Int -> Assoc -> Bool -> Op
Op String
"/="   Int
4 Assoc
InfixL Bool
False -- inequality (from type class)
  , String -> Int -> Assoc -> Bool -> Op
Op String
"="    Int
4 Assoc
InfixL Bool
False -- primitive function
  , String -> Int -> Assoc -> Bool -> Op
Op String
"<="   Int
4 Assoc
InfixL Bool
False -- primitive function
  , String -> Int -> Assoc -> Bool -> Op
Op String
">="   Int
4 Assoc
InfixL Bool
False -- primitive function
  , String -> Int -> Assoc -> Bool -> Op
Op String
"<"    Int
4 Assoc
InfixL Bool
False -- primitive function
  , String -> Int -> Assoc -> Bool -> Op
Op String
">"    Int
4 Assoc
InfixL Bool
False -- primitive function
  , String -> Int -> Assoc -> Bool -> Op
Op String
"&&"   Int
3 Assoc
InfixR Bool
False -- logical and (from base)
  , String -> Int -> Assoc -> Bool -> Op
Op String
"||"   Int
2 Assoc
InfixR Bool
False -- logical or (from base)
  , String -> Int -> Assoc -> Bool -> Op
Op String
"$"    Int
0 Assoc
InfixR Bool
False -- right-associative lowest-priority (application)
  , String -> Int -> Assoc -> Bool -> Op
Op String
"+"    Int
6 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"-"    Int
6 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"*"    Int
7 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"/"    Int
7 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"^"    Int
8 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"+'"   Int
6 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"-'"   Int
6 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"*'"   Int
7 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"/'"   Int
7 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"^'"   Int
8 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"∧"    Int
7 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"."    Int
7 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
".'"   Int
7 Assoc
InfixL Bool
False
  ]

reservedPatternOp :: [Op]
reservedPatternOp :: [Op]
reservedPatternOp =
  [ String -> Int -> Assoc -> Bool -> Op
Op String
"++" Int
5 Assoc
InfixR Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"*:" Int
5 Assoc
InfixL Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"+" Int
7 Assoc
InfixR Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"*" Int
8 Assoc
InfixR Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"/" Int
8 Assoc
InfixN Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"^" Int
9 Assoc
InfixN Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"::" Int
6 Assoc
InfixR Bool
False  -- required for desugaring collection pattern (priority 6 > ++ priority 5)
  , String -> Int -> Assoc -> Bool -> Op
Op String
"&"  Int
3 Assoc
InfixR Bool
False
  , String -> Int -> Assoc -> Bool -> Op
Op String
"|"  Int
2 Assoc
InfixR Bool
False
  ]

findOpFrom :: String -> [Op] -> Op
findOpFrom :: String -> [Op] -> Op
findOpFrom String
op [Op]
table = Maybe Op -> Op
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Op -> Op) -> Maybe Op -> Op
forall a b. (a -> b) -> a -> b
$ (Op -> Bool) -> [Op] -> Maybe Op
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
op) (String -> Bool) -> (Op -> String) -> Op -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Op -> String
repr) [Op]
table

makeApply :: String -> [Expr] -> Expr
makeApply :: String -> [Expr] -> Expr
makeApply String
func [Expr]
args = Expr -> [Expr] -> Expr
ApplyExpr (String -> Expr
VarExpr String
func) [Expr]
args

stringToVarWithIndices :: String -> VarWithIndices
stringToVarWithIndices :: String -> VarWithIndices
stringToVarWithIndices String
name = String -> [VarIndex] -> VarWithIndices
VarWithIndices String
name []

extractNameFromVarWithIndices :: VarWithIndices -> String
extractNameFromVarWithIndices :: VarWithIndices -> String
extractNameFromVarWithIndices (VarWithIndices String
name [VarIndex]
_) = String
name

--
-- Type expressions (for type annotations)
--

-- | Type expression in source code
data TypeExpr
  = TEInt                              -- ^ Integer (= MathExpr)
  | TEMathExpr                         -- ^ MathExpr (= Integer)
  | TEFloat                            -- ^ Float
  | TEBool                             -- ^ Bool
  | TEChar                             -- ^ Char
  | TEString                           -- ^ String
  | TEVar String                       -- ^ Type variable, e.g., a
  | TEList TypeExpr                    -- ^ List type, e.g., [a]
  | TETuple [TypeExpr]                 -- ^ Tuple type, e.g., (a, b)
  | TEFun TypeExpr TypeExpr            -- ^ Function type, e.g., a -> b
  | TEMatcher TypeExpr                 -- ^ Matcher type
  | TEPattern TypeExpr                 -- ^ Pattern type, e.g., Pattern a
  | TEIO TypeExpr                      -- ^ IO type, e.g., IO ()
  | TETensor TypeExpr                  -- ^ Tensor type, e.g., Tensor a
  | TEVector TypeExpr                  -- ^ Vector type, e.g., Vector a (1D tensor)
  | TEMatrix TypeExpr                  -- ^ Matrix type, e.g., Matrix a (2D tensor)
  | TEDiffForm TypeExpr                -- ^ DiffForm type, e.g., DiffForm a (differential form, alias for Tensor)
  | TEApp TypeExpr [TypeExpr]          -- ^ Type application, e.g., List a
  | TEConstrained [ConstraintExpr] TypeExpr
                                      -- ^ Constrained type, e.g., Eq a => a
  deriving (Int -> TypeExpr -> ShowS
[TypeExpr] -> ShowS
TypeExpr -> String
(Int -> TypeExpr -> ShowS)
-> (TypeExpr -> String) -> ([TypeExpr] -> ShowS) -> Show TypeExpr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TypeExpr -> ShowS
showsPrec :: Int -> TypeExpr -> ShowS
$cshow :: TypeExpr -> String
show :: TypeExpr -> String
$cshowList :: [TypeExpr] -> ShowS
showList :: [TypeExpr] -> ShowS
Show, TypeExpr -> TypeExpr -> Bool
(TypeExpr -> TypeExpr -> Bool)
-> (TypeExpr -> TypeExpr -> Bool) -> Eq TypeExpr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TypeExpr -> TypeExpr -> Bool
== :: TypeExpr -> TypeExpr -> Bool
$c/= :: TypeExpr -> TypeExpr -> Bool
/= :: TypeExpr -> TypeExpr -> Bool
Eq)

-- | Tensor shape expression
data TensorShapeExpr
  = TSLit [Integer]                    -- ^ Concrete shape, e.g., [2, 2]
  | TSVar String                       -- ^ Shape variable
  | TSMixed [ShapeDim]                 -- ^ Mixed shape, e.g., [n, m, 2]
  deriving (Int -> TensorShapeExpr -> ShowS
[TensorShapeExpr] -> ShowS
TensorShapeExpr -> String
(Int -> TensorShapeExpr -> ShowS)
-> (TensorShapeExpr -> String)
-> ([TensorShapeExpr] -> ShowS)
-> Show TensorShapeExpr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TensorShapeExpr -> ShowS
showsPrec :: Int -> TensorShapeExpr -> ShowS
$cshow :: TensorShapeExpr -> String
show :: TensorShapeExpr -> String
$cshowList :: [TensorShapeExpr] -> ShowS
showList :: [TensorShapeExpr] -> ShowS
Show, TensorShapeExpr -> TensorShapeExpr -> Bool
(TensorShapeExpr -> TensorShapeExpr -> Bool)
-> (TensorShapeExpr -> TensorShapeExpr -> Bool)
-> Eq TensorShapeExpr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TensorShapeExpr -> TensorShapeExpr -> Bool
== :: TensorShapeExpr -> TensorShapeExpr -> Bool
$c/= :: TensorShapeExpr -> TensorShapeExpr -> Bool
/= :: TensorShapeExpr -> TensorShapeExpr -> Bool
Eq)

-- | Shape dimension (can be concrete or variable)
data ShapeDim
  = SDLit Integer                      -- ^ Concrete dimension, e.g., 2
  | SDVar String                       -- ^ Dimension variable, e.g., n
  deriving (Int -> ShapeDim -> ShowS
[ShapeDim] -> ShowS
ShapeDim -> String
(Int -> ShapeDim -> ShowS)
-> (ShapeDim -> String) -> ([ShapeDim] -> ShowS) -> Show ShapeDim
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ShapeDim -> ShowS
showsPrec :: Int -> ShapeDim -> ShowS
$cshow :: ShapeDim -> String
show :: ShapeDim -> String
$cshowList :: [ShapeDim] -> ShowS
showList :: [ShapeDim] -> ShowS
Show, ShapeDim -> ShapeDim -> Bool
(ShapeDim -> ShapeDim -> Bool)
-> (ShapeDim -> ShapeDim -> Bool) -> Eq ShapeDim
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ShapeDim -> ShapeDim -> Bool
== :: ShapeDim -> ShapeDim -> Bool
$c/= :: ShapeDim -> ShapeDim -> Bool
/= :: ShapeDim -> ShapeDim -> Bool
Eq)

-- | Tensor index expression
data TensorIndexExpr
  = TISub String                       -- ^ Subscript, e.g., _i
  | TISup String                       -- ^ Superscript, e.g., ~i
  | TIPlaceholderSub                   -- ^ Subscript placeholder, _#
  | TIPlaceholderSup                   -- ^ Superscript placeholder, ~#
  deriving (Int -> TensorIndexExpr -> ShowS
[TensorIndexExpr] -> ShowS
TensorIndexExpr -> String
(Int -> TensorIndexExpr -> ShowS)
-> (TensorIndexExpr -> String)
-> ([TensorIndexExpr] -> ShowS)
-> Show TensorIndexExpr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TensorIndexExpr -> ShowS
showsPrec :: Int -> TensorIndexExpr -> ShowS
$cshow :: TensorIndexExpr -> String
show :: TensorIndexExpr -> String
$cshowList :: [TensorIndexExpr] -> ShowS
showList :: [TensorIndexExpr] -> ShowS
Show, TensorIndexExpr -> TensorIndexExpr -> Bool
(TensorIndexExpr -> TensorIndexExpr -> Bool)
-> (TensorIndexExpr -> TensorIndexExpr -> Bool)
-> Eq TensorIndexExpr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TensorIndexExpr -> TensorIndexExpr -> Bool
== :: TensorIndexExpr -> TensorIndexExpr -> Bool
$c/= :: TensorIndexExpr -> TensorIndexExpr -> Bool
/= :: TensorIndexExpr -> TensorIndexExpr -> Bool
Eq)

-- | Typed parameter pattern
data TypedParam
  = TPVar String TypeExpr                    -- ^ Simple variable with type: (x: a)
  | TPInvertedVar String TypeExpr            -- ^ Inverted variable with type: (!x: a)
  | TPTuple [TypedParam]                     -- ^ Tuple pattern: ((x: a), (y: b)) or (x: a, y: b)
  | TPWildcard TypeExpr                      -- ^ Wildcard with type: (_: a)
  | TPUntypedVar String                      -- ^ Untyped variable in tuple: x (inferred)
  | TPUntypedWildcard                        -- ^ Untyped wildcard: _
  deriving (Int -> TypedParam -> ShowS
[TypedParam] -> ShowS
TypedParam -> String
(Int -> TypedParam -> ShowS)
-> (TypedParam -> String)
-> ([TypedParam] -> ShowS)
-> Show TypedParam
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TypedParam -> ShowS
showsPrec :: Int -> TypedParam -> ShowS
$cshow :: TypedParam -> String
show :: TypedParam -> String
$cshowList :: [TypedParam] -> ShowS
showList :: [TypedParam] -> ShowS
Show, TypedParam -> TypedParam -> Bool
(TypedParam -> TypedParam -> Bool)
-> (TypedParam -> TypedParam -> Bool) -> Eq TypedParam
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TypedParam -> TypedParam -> Bool
== :: TypedParam -> TypedParam -> Bool
$c/= :: TypedParam -> TypedParam -> Bool
/= :: TypedParam -> TypedParam -> Bool
Eq)

-- | Variable with type annotation
data TypedVarWithIndices = TypedVarWithIndices
  { TypedVarWithIndices -> String
typedVarName        :: String
  , TypedVarWithIndices -> [VarIndex]
typedVarIndices     :: [VarIndex]
  , TypedVarWithIndices -> [ConstraintExpr]
typedVarConstraints :: [ConstraintExpr]  -- ^ Type class constraints
  , TypedVarWithIndices -> [TypedParam]
typedVarParams      :: [TypedParam]      -- ^ Typed parameters (can include tuples)
  , TypedVarWithIndices -> TypeExpr
typedVarRetType     :: TypeExpr          -- ^ Return type
  } deriving (Int -> TypedVarWithIndices -> ShowS
[TypedVarWithIndices] -> ShowS
TypedVarWithIndices -> String
(Int -> TypedVarWithIndices -> ShowS)
-> (TypedVarWithIndices -> String)
-> ([TypedVarWithIndices] -> ShowS)
-> Show TypedVarWithIndices
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TypedVarWithIndices -> ShowS
showsPrec :: Int -> TypedVarWithIndices -> ShowS
$cshow :: TypedVarWithIndices -> String
show :: TypedVarWithIndices -> String
$cshowList :: [TypedVarWithIndices] -> ShowS
showList :: [TypedVarWithIndices] -> ShowS
Show, TypedVarWithIndices -> TypedVarWithIndices -> Bool
(TypedVarWithIndices -> TypedVarWithIndices -> Bool)
-> (TypedVarWithIndices -> TypedVarWithIndices -> Bool)
-> Eq TypedVarWithIndices
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TypedVarWithIndices -> TypedVarWithIndices -> Bool
== :: TypedVarWithIndices -> TypedVarWithIndices -> Bool
$c/= :: TypedVarWithIndices -> TypedVarWithIndices -> Bool
/= :: TypedVarWithIndices -> TypedVarWithIndices -> Bool
Eq)