{-  Exploring Languages with Interpreters and Functional Programming
    ELI Calculator Language; Abstract Syntax
    Copyright (C) 2017, 2018, H. Conrad Cunningham

1234567890123456789012345678901234567890123456789012345678901234567890

2017-09-19: New module separated from PrefixParser06 with changes
            similar to current AbSynImpCore module
2017-09-20: Corrected show functionality for "*" (kam)
2018-08-09: Updated for 2018 ELIFP textbook, Expression Language
            renamed ELI Calculator language, file AbSynExpr renamed
            AbSynCalc

The intention of this module is to encapsulate the abstract syntax as
much as is practical---such as to centralize the data type definitions
and the Show functionality.

However, given that the abstract syntax consists of algebraic data
type definitions, the semantics of the abstract syntax tree is known
by modules that must create (e.g., parser) and use (e.g., evaluator)
the abstract syntax trees.

TODO:

- Decide whether to use explicit Show instance or default given that
  will be used with two concrete syntaxes

-}

module AbSynCalc
    ( ValType, Name, Expr(..) )
where

-- Haskell libraries
import Data.List ( intercalate )

-- ELI Calculator modules
import Values ( ValType, Name )

{- ABSTRACT SYNTAX TREE (AST) -}

data Expr = Add Expr Expr 
          | Sub Expr Expr
          | Mul Expr Expr
          | Div Expr Expr
          | Var Name
          | Val ValType 

-- Define Show instance for Expr to enable convenient string format
instance Show Expr where
    show (Val v)   = show v
    show (Var n)   = n
    show (Add l r) = showParExpr "+" [l,r]
    show (Sub l r) = showParExpr "-" [l,r]
    show (Mul l r) = showParExpr "*" [l,r]
    show (Div l r) = showParExpr "/" [l,r]

showParExpr :: String -> [Expr] -> String
showParExpr op es = "(" ++ op ++ " " ++ showExprList es ++ ")"
    
showExprList :: [Expr] -> String
showExprList es = intercalate " " (map show es)

