{- |
Module : $Header$
Description : Definition of the intermediate language (IL)
Copyright : (c) 1999 - 2003 Wolfgang Lux
Martin Engelke
2016 - 2017 Finn Teegen
License : BSD-3-clause
Maintainer : bjp@informatik.uni-kiel.de
Stability : experimental
Portability : portable
The module 'IL' defines the intermediate language which will be
compiled into abstract machine code. The intermediate language removes
a lot of syntactic sugar from the Curry source language. Top-level
declarations are restricted to data type and function definitions. A
newtype definition serves mainly as a hint to the backend that it must
provide an auxiliary function for partial applications of the
constructor (Newtype constructors must not occur in patterns
and may be used in expressions only as partial applications.).
Type declarations use a de-Bruijn indexing scheme (starting at 0) for
type variables. In the type of a function, all type variables are
numbered in the order of their occurence from left to right, i.e., a
type '(Int -> b) -> (a,b) -> c -> (a,c)' is translated into the
type (using integer numbers to denote the type variables)
'(Int -> 0) -> (1,0) -> 2 -> (1,2)'.
Pattern matching in an equation is handled via flexible and rigid
'Case' expressions. Overlapping rules are translated with the
help of 'Or' expressions. The intermediate language has three
kinds of binding expressions, 'Exist' expressions introduce a
new logical variable, 'Let' expression support a single
non-recursive variable binding, and 'Letrec' expressions
introduce multiple variables with recursive initializer expressions.
The intermediate language explicitly distinguishes (local) variables
and (global) functions in expressions.
Note: this modified version uses haskell type 'Integer'
instead of 'Int' for representing integer values. This provides
an unlimited range of integer constants in Curry programs.
-}
module IL.Type
( -- * Data types
Module (..), Decl (..), ConstrDecl (..), Type (..), Literal (..)
, ConstrTerm (..), Expression (..), Eval (..), Alt (..), Binding (..)
) where
import Curry.Base.Ident
import Base.Expr
data Module = Module ModuleIdent [ModuleIdent] [Decl]
deriving (Eq, Show)
data Decl
= DataDecl QualIdent Int [ConstrDecl]
| ExternalDataDecl QualIdent Int
| FunctionDecl QualIdent [(Type, Ident)] Type Expression
| ExternalDecl QualIdent Type
deriving (Eq, Show)
data ConstrDecl = ConstrDecl QualIdent [Type]
deriving (Eq, Show)
data Type
= TypeConstructor QualIdent [Type]
| TypeVariable Int
| TypeArrow Type Type
| TypeForall [Int] Type
deriving (Eq, Show)
data Literal
= Char Char
| Int Integer
| Float Double
deriving (Eq, Show)
data ConstrTerm
-- |literal patterns
= LiteralPattern Type Literal
-- |constructors
| ConstructorPattern Type QualIdent [(Type, Ident)]
-- |default
| VariablePattern Type Ident
deriving (Eq, Show)
data Expression
-- |literal constants
= Literal Type Literal
-- |variables
| Variable Type Ident
-- |functions
| Function Type QualIdent Int
-- |constructors
| Constructor Type QualIdent Int
-- |applications
| Apply Expression Expression
-- |case expressions
| Case Eval Expression [Alt]
-- |non-deterministic or
| Or Expression Expression
-- |exist binding (introduction of a free variable)
| Exist Ident Type Expression
-- |let binding
| Let Binding Expression
-- |letrec binding
| Letrec [Binding] Expression
-- |typed expression
| Typed Expression Type
deriving (Eq, Show)
data Eval
= Rigid
| Flex
deriving (Eq, Show)
data Alt = Alt ConstrTerm Expression
deriving (Eq, Show)
data Binding = Binding Ident Expression
deriving (Eq, Show)
instance Expr Expression where
fv (Variable _ v) = [v]
fv (Apply e1 e2) = fv e1 ++ fv e2
fv (Case _ e alts) = fv e ++ fv alts
fv (Or e1 e2) = fv e1 ++ fv e2
fv (Exist v _ e) = filter (/= v) (fv e)
fv (Let (Binding v e1) e2) = fv e1 ++ filter (/= v) (fv e2)
fv (Letrec bds e) = filter (`notElem` vs) (fv es ++ fv e)
where (vs, es) = unzip [(v, e') | Binding v e' <- bds]
fv (Typed e _) = fv e
fv _ = []
instance Expr Alt where
fv (Alt (ConstructorPattern _ _ vs) e) = filter (`notElem` map snd vs) (fv e)
fv (Alt (VariablePattern _ v) e) = filter (v /=) (fv e)
fv (Alt _ e) = fv e