diff --git a/CSPM-Interpreter.cabal b/CSPM-Interpreter.cabal
new file mode 100644
--- /dev/null
+++ b/CSPM-Interpreter.cabal
@@ -0,0 +1,62 @@
+Name:                CSPM-Interpreter
+Version:             0.1.0.0
+
+Synopsis:            An interpreter for CSPM
+Description:
+  This module contains an interpreter for CSPM
+  and instance declarations than implement the interface defined in
+  the package CSPM-CoreLanguage.
+  All type family instances that belong to this implementation
+  are indexed with the phantom-type 'INT' ('INT' == interpreter).
+  The operational semantics of core-CSP is defined in a separate package.
+
+License:             BSD3
+category:            Language
+License-File:        License
+Author:              2010 Marc Fontaine
+Maintainer:          Marc Fontaine <fontaine@cs.uni-duesseldorf.de>
+cabal-Version:       >= 1.6
+build-type: Simple
+Extra-source-files:
+Library
+  Build-Depends:
+    CSPM-Frontend >= 0.3.0.0
+    ,CSPM-CoreLanguage >= 0.1 && <= 0.2
+    ,base >= 4.0 && < 5.0
+    ,containers >= 0.3 && < 0.4
+    ,mtl >= 1.1 && < 1.2
+    ,array >= 0.3 && <0.4
+    ,syb >= 0.1 && < 0.2
+ 
+  GHC-Options: -funbox-strict-fields -O2 -Wall
+  Extensions: DeriveDataTypeable, GeneralizedNewtypeDeriving
+  Hs-Source-Dirs:       src
+  Exposed-modules:
+    CSPM.Interpreter
+    CSPM.Interpreter.Types
+    CSPM.Interpreter.Eval
+    CSPM.Interpreter.CoreInstances
+    CSPM.Interpreter.Hash
+    CSPM.Interpreter.ClosureSet
+    CSPM.Interpreter.Test.CLI
+  Other-modules:
+    CSPM.Interpreter.Renaming
+    CSPM.Interpreter.PrepareAST
+    CSPM.Interpreter.Bindings
+    CSPM.Interpreter.PatternMatcher
+    CSPM.Interpreter.Prefix
+    CSPM.Interpreter.GenericBufferPrefix
+    CSPM.Interpreter.SSet
+    Data.Digest.Pure.MD5
+    Data.Digest.Pure.HashMD5
+
+Executable cspmEval
+  Build-Depends:
+    CSPM-Frontend >= 0.3.0.0
+    ,CSPM-CoreLanguage >= 0.1 && <= 0.2
+    ,base >= 4.0
+ 
+  GHC-Options: -funbox-strict-fields -O2 -Wall
+  Extensions: DeriveDataTypeable, GeneralizedNewtypeDeriving
+  Hs-Source-Dirs:      src
+  Main-is:             Main.hs
diff --git a/License b/License
new file mode 100644
--- /dev/null
+++ b/License
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+import Distribution.Simple
+main = defaultMain
diff --git a/src/CSPM/Interpreter.hs b/src/CSPM/Interpreter.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter.hs
@@ -0,0 +1,52 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter
+-- Copyright   :  (c) Fontaine 2008
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- An API for the Interpreter.
+--
+----------------------------------------------------------------------------
+
+module CSPM.Interpreter
+(
+   runFile
+  ,evalTest
+  ,getAllEvents
+  ,prepareAST
+  ,runInterpreter
+  ,module CSPM.Interpreter.Types
+  ,module CSPM.Interpreter.Bindings
+  ,module CSPM.Interpreter.CoreInstances
+)
+where
+
+import CSPM.Interpreter.Types
+import CSPM.Interpreter.CoreInstances ()
+import CSPM.Interpreter.Bindings
+import CSPM.Interpreter.Eval
+import CSPM.Interpreter.Hash (hs)
+import CSPM.Interpreter.PrepareAST
+import CSPM.Interpreter.Test.CLI
+
+import Language.CSPM.AST as AST
+
+import Data.IntMap as IntMap
+
+-- | Run the interpreter for a given module and top-level identifier.
+runInterpreter :: AST.LModule -> AST.UniqueIdent -> IO (Process,Env)
+runInterpreter ast entry = do
+  initEnv <- initialEnvirionment
+  let
+    env = processDeclList (hs "TopLevelEnvirionment") initEnv
+          $ AST.moduleDecls $ unLabel ast
+    val :: Value
+    val = (IntMap.!) (getLetBindings env) $ AST.uniqueIdentId entry
+  case val of
+    VProcess x -> return (x,env)
+    _ -> throwTypingError "entrypoint is not a CSPM-process" (Just $ AST.bindingLoc entry)
+           $  Just val
diff --git a/src/CSPM/Interpreter/Bindings.hs b/src/CSPM/Interpreter/Bindings.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/Bindings.hs
@@ -0,0 +1,43 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.Bindings
+-- Copyright   :  (c) Fontaine 2008
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+----------------------------------------------------------------------------
+module CSPM.Interpreter.Bindings
+where
+
+import CSPM.Interpreter.Types
+import Language.CSPM.AST hiding (Bindings)
+
+import Control.Exception
+import Control.Monad.Reader
+import Data.IntMap as IntMap
+import Data.List as List
+
+lookupIdent :: LIdent -> EM Value
+lookupIdent i = do
+  b <- getEnv
+  let binds = case bindType $ unUIdent $ unLabel i of
+        LetBound    -> getLetBindings b
+        NotLetBound -> getArgBindings b
+  case (IntMap.lookup (identId i) binds) of
+    Just v -> return v
+    Nothing -> throw $ InternalError ("Bindings lookup failure :" ++ show i) Nothing Nothing
+
+bindIdent :: LIdent -> Value -> Bindings -> Bindings
+bindIdent key value bind = IntMap.insert (identId key) value bind
+
+emptyBindings :: Bindings
+emptyBindings = IntMap.empty  
+
+lookupAllChannels :: EM [Channel]
+lookupAllChannels = do
+  letBinds <- liftM getLetBindings getEnv
+  return $ List.map getChannel $ List.filter isChannelField 
+    $ IntMap.elems letBinds
diff --git a/src/CSPM/Interpreter/ClosureSet.hs b/src/CSPM/Interpreter/ClosureSet.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/ClosureSet.hs
@@ -0,0 +1,164 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.ClosureSets
+-- Copyright   :  (c) Fontaine 2009
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- Utility functions dealing with closure sets.
+--
+----------------------------------------------------------------------------
+{-
+todo: redo this
+todo: add testcases
+this is all much to complex
+-}
+module CSPM.Interpreter.ClosureSet
+where
+
+import CSPM.Interpreter.Types as Types
+import CSPM.Interpreter.SSet as SSet
+import CSPM.Interpreter.Hash as Hash
+
+import Data.List as List
+import Data.Set (Set)
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import Data.Maybe
+import Data.Ord
+
+memberPrefixTrie :: [Field] -> PrefixTrie -> Bool
+memberPrefixTrie [] PTNil = True
+memberPrefixTrie _ (PTClosure _) = True
+memberPrefixTrie [] t
+  = throwInternalError ("memberPrefix : number of fields mismatch" ++ show t)
+     Nothing Nothing
+memberPrefixTrie (_h:r) (PTAny t) = memberPrefixTrie r t
+memberPrefixTrie (h:r) (PTMap m) = case Map.lookup h m of
+  Just t -> memberPrefixTrie r t
+  Nothing -> False
+memberPrefixTrie (h:r) (PTRec set t)
+  = if h `Set.member` set then memberPrefixTrie r t else False
+memberPrefixTrie (h:r) (PTSingle v t)
+  = if h == v then memberPrefixTrie r t else False
+
+prefixTrieNext :: PrefixTrie -> Field -> Maybe PrefixTrie
+prefixTrieNext t field = case t of
+  PTNil  -> throwInternalError
+    ("prefixTrieNext number of fields mismatch PTNil" ++ show field) Nothing Nothing
+  PTAny new -> Just new
+  PTMap m -> case Map.lookup field m of
+    Just new -> Just new
+    Nothing -> Nothing
+  PTRec s new -> if field `Set.member` s then Just new else Nothing
+  PTSingle v new -> if field == v then Just new else Nothing
+
+closureStateNext :: ClosureState -> Field -> ClosureState
+closureStateNext closure field = case closure of
+    ClosureStateFailed {} -> closure
+    ClosureStateSucc   {}
+     -> closure {currentPrefixTrie = fromJust ptNext }
+    ClosureStateNormal {} -> case prefixTrieNext (currentPrefixTrie closure) field of
+      Nothing -> ClosureStateFailed {origClosureSet = origClosureSet closure}
+      Just (PTClosure p) -> ClosureStateSucc
+        {currentPrefixTrie = p, origClosureSet = origClosureSet closure}
+      Just pt -> closure { currentPrefixTrie = pt}
+    where ptNext = prefixTrieNext (currentPrefixTrie closure) field
+
+
+setToClosure :: Set Value -> ClosureSet
+setToClosure = mkClosureSet . setToPrefixTrie
+
+mkClosureSet :: PrefixTrie -> ClosureSet
+mkClosureSet x
+  = ClosureSet {
+     closureSetTrie = x
+    ,closureSetDigest = mix (hs "ClosureSet") $ hash x }
+
+setToPrefixTrie :: Set Value -> PrefixTrie
+setToPrefixTrie = worker . map fromTuple . Set.toList
+  where
+    fromTuple (VDotTuple l ) = l
+    fromTuple x = [x] -- channel a  and [|{a}|] apears in one evans example
+
+    worker :: [[Value]] -> PrefixTrie
+    worker [] = throwInternalError "setToPrefixTrie worker []" Nothing Nothing
+    worker [[]] = PTNil
+    worker l = let
+      sl = sortBy (comparing head) l
+      grps :: [[[Value]]]
+      grps = groupBy (\a b -> (head a) == (head b)) sl
+      withkeys :: [(Value,PrefixTrie)]
+      withkeys = map (\g -> (head $ head g, worker $ map tail g)) grps
+      in PTMap $ Map.fromList withkeys
+
+closureToSet :: ClosureSet -> Set Value
+closureToSet = prefixTrieToSet . closureSetTrie
+
+
+hackValueToEvent :: Value -> Event
+hackValueToEvent (VDotTuple l ) = l
+hackValueToEvent x = [x] -- channel a  and [|{a}|] apears in one evans example
+
+{- todo : this is too lowlevel -}
+prefixTrieToSet :: PrefixTrie -> Set Value
+prefixTrieToSet trie
+  = Set.fromList $ worker [] [] trie
+  where
+    worker :: [Value] -> [Value] -> PrefixTrie -> [Value]
+    worker acc path t = case t of
+      PTNil -> (VDotTuple $ reverse path) : acc
+      PTAny {} -> throwFeatureNotImplemented "cannot enumerate PTAny (Set,Seq,INT)"
+                    Nothing Nothing
+      PTMap m -> foldl' (add path) acc $ Map.assocs m
+      PTRec s t -> foldl' (add path) acc $ zip (Set.elems s) $ repeat t
+      PTSingle v t -> worker acc (v:path) t
+      PTClosure l -> worker acc path l
+    add :: [Value] -> [Value] -> (Value,PrefixTrie) -> [Value]
+    add path acc (val,t) = worker acc (val:path) t
+{- {|a,b,c|} -}
+mkEventClosure :: [Value] -> EM ClosureSet
+mkEventClosure l = if List.null l
+  then throwScriptError "mkEventClosure : empty ClosureSet" Nothing Nothing
+  else return $ mkClosureSet $ ptUnions $ map valueToPT l
+
+{-
+convert the things inside a {| |} to a prefix trie
+-}
+valueToPT :: Value -> PrefixTrie
+valueToPT v = case v of
+  VChannel c -> fieldsToPT [v] $ (SSet.Total : chanFields c)
+  VDotTuple [] -> throwScriptError "valueToPT : empty dot-tuple" Nothing Nothing
+  VDotTuple l@(VChannel c : t) -> fieldsToPT l (SSet.Total : chanFields c)
+  VDotTuple l -> throwScriptError "valueToPT : dot-tuple does not start with a channel"
+        Nothing $ Just v
+  _ -> throwScriptError "valueToPT: cannot make a event-closure of value" 
+        Nothing $ Just v
+
+{- fieldsToPT is a kind of zip -}
+fieldsToPT :: [Value] -> [FieldSet] -> PrefixTrie
+fieldsToPT (v:vr) (f:fr) = if v `SSet.member` f
+    then PTSingle v $ fieldsToPT vr fr
+    else throwScriptError "fieldsToPT : value outside channel definition" Nothing (Just v)
+fieldsToPT [] f
+  = PTClosure $ foldr ( \(SSet.Proper s) pt -> PTRec s pt) PTNil f
+fieldsToPT v []
+  = throwScriptError "fieldsToPT : more fields than declared in channel definition"
+      Nothing (Just $ VDotTuple v)
+
+
+{-
+todo :
+more efficent, direkt implementation
+without converting to intermediate sets
+-}
+ptUnions :: [PrefixTrie] -> PrefixTrie
+ptUnions = setToPrefixTrie . Set.unions . map prefixTrieToSet
+
+
+singleEventToClosureSet :: Event -> ClosureSet
+singleEventToClosureSet e
+  = mkClosureSet $ foldr PTSingle PTNil $ e
diff --git a/src/CSPM/Interpreter/CoreInstances.hs b/src/CSPM/Interpreter/CoreInstances.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/CoreInstances.hs
@@ -0,0 +1,163 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.CoreInstances
+-- Copyright   :  (c) Fontaine 2008
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- This module defines some class instances that make the interpreter
+-- an implementation of the interface defined in package CSPM-CoreLanguage.
+--
+----------------------------------------------------------------------------
+
+{-# LANGUAGE StandaloneDeriving, FlexibleInstances, FlexibleContexts #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+module CSPM.Interpreter.CoreInstances
+(
+)
+where
+
+import CSPM.CoreLanguage as Core
+import CSPM.CoreLanguage.Field
+import CSPM.CoreLanguage.Event
+
+import CSPM.Interpreter.Types as Types
+import CSPM.Interpreter.Eval as Eval
+import CSPM.Interpreter.ClosureSet as ClosureSet
+import CSPM.Interpreter.Renaming as Renaming
+import CSPM.Interpreter.GenericBufferPrefix as Prefix
+import CSPM.Interpreter.SSet (SSet)
+import qualified CSPM.Interpreter.SSet as SSet
+
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import Data.List as List
+import Data.Maybe
+
+--instance EqOrd INT
+--instance CSP1 INT
+--instance CSP2 INT
+--instance FShow INT
+
+deriving instance Show (Core.TTE INT)
+
+noInstance :: String -> a
+noInstance i
+  = throwInternalError ("interpreter core-instances : no instance : " ++ i) Nothing Nothing
+
+instance BE INT where
+  eventEq _ty = (==)
+  member  _ty event c = ClosureSet.memberPrefixTrie event $ closureSetTrie c
+{-
+these functions are only needed for the total-event-view
+they are not needed for field-wise computation of events
+todo: make a seperate class for these functions
+
+  intersection  _ty = SSet.intersection
+  difference  _ty = SSet.difference
+  union  _ty = SSet.union
+  null  _ty = SSet.null
+  singleton _ty = SSet.singleton
+  insert  _ty = SSet.insert
+  delete  _ty = SSet.delete
+  eventSetToList  _ty = SSet.toList
+  allEvents = error "CoreInstances : BE :allEvents"
+-}
+  intersection  _ty = noInstance "BE : intersection"
+  difference  _ty = noInstance "BE : difference"
+  union  _ty = noInstance "BE : union"
+  null  _ty = noInstance "BE : null "
+  singleton _ty = noInstance "BE : singleton"
+  insert  _ty = noInstance "BE : insert"
+  delete  _ty = noInstance "BE : delete"
+  eventSetToList _ty = map hackValueToEvent . Set.toList . closureToSet
+  allEvents = noInstance "BE :allEvents"
+  isInRenaming _ty = Renaming.isInRelation
+  isInRenamingDomain _ty e rel = Set.member e $ renamingDomain rel
+  isInRenamingRange _ty e rel = Set.member e $ renamingRange rel
+  getRenamingDomain _ty = Set.toList . renamingDomain
+  getRenamingRange _ty = Set.toList . renamingRange
+  imageRenaming _ty = Renaming.imageRenaming2
+  preImageRenaming _ty = Renaming.imageRenaming1
+  singleEventToClosureSet _ty = ClosureSet.singleEventToClosureSet
+
+instance BF INT where
+  fieldEq  _ty = (==)
+  member  _ty = SSet.member
+  intersection _ty = SSet.intersection
+  difference  _ty = SSet.difference
+  union _ty = SSet.union
+  null _ty = SSet.null
+  singleton  _ty = SSet.singleton
+  insert _ty = SSet.insert
+  delete _ty = SSet.delete
+  fieldSetToList _ty = SSet.toList
+  fieldSetFromList _ty = SSet.fromList
+
+  joinFields  _ty = id
+  splitFields  _ty = id
+  channelLen  _ty (VChannel c) = chanLen c
+
+  closureStateInit _ty c
+    = ClosureStateNormal {origClosureSet = c ,currentPrefixTrie = closureSetTrie c}
+
+  closureStateNext _ty = ClosureSet.closureStateNext
+
+  closureRestore _ty closure = origClosureSet closure
+
+  viewClosureFields _ty c = case c of
+    ClosureStateFailed {} -> SSet.Empty
+    _ -> case currentPrefixTrie c of
+      PTAny _ -> SSet.Total
+      PTMap m -> SSet.Proper $ Map.keysSet m
+      PTRec s _ -> SSet.Proper s
+      PTSingle v _ -> SSet.singleton v
+  viewClosureState _ty closure = case closure of
+    ClosureStateNormal {} -> MaybeInClosure
+    ClosureStateFailed {} -> NotInClosure
+    ClosureStateSucc   {} -> InClosure
+  seenPrefixInClosure ty closure = case closure of
+    ClosureStateNormal {} -> True
+    ClosureStateFailed {} -> False
+    ClosureStateSucc   {} -> True
+  prefixStateInit _ty = Prefix.initPrefix
+  prefixStateNext _ty = Prefix.prefixStateNext
+  prefixStateFinalize  _ty = Prefix.prefixStateFinalize
+  viewPrefixState  _ty = Prefix.viewPrefixState
+
+{-
+todo:
+better modelling of prefix with multiple fields
+(all fields == one event) level
+-}
+instance BL INT where
+  prefixNext p _event = Just $ prefixRHS p -- todo maybe sanity check with _event
+  switchOn = switchedOffProcess
+
+
+instance ShowEvent Types.Event where
+  showEvent l = concat $ intersperse "." $ List.map showValue l
+
+showValue :: Value -> String
+showValue f = case f of
+  VChannel chan -> chanName chan
+  VInt i -> show i
+  VBool True -> "true"
+  VBool False -> "false"
+  VConstructor c -> constrName c
+  VTuple l -> "(" ++ listBody l ++ ")"
+  VSet l -> "{" ++ (listBody $ Set.toList l) ++ "}"
+  VList l -> "<" ++ listBody l ++ ">"
+  VDotTuple l -> (concat $ intersperse "." $ List.map showValue l)
+  _ -> throwFeatureNotImplemented ("showValue : missing match : " ++ show f) Nothing
+  where
+    listBody = concat . intersperse "," . List.map showValue
+
+instance ShowTTE (TTE INT) where
+  showTTE t = case t of
+    TickEvent -> "tick"
+    TauEvent -> "tau"
+    SEvent e -> showEvent e
diff --git a/src/CSPM/Interpreter/Eval.hs b/src/CSPM/Interpreter/Eval.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/Eval.hs
@@ -0,0 +1,697 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.Eval
+-- Copyright   :  (c) Fontaine 2009
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- The main eval function of the Interpreter.
+--
+----------------------------------------------------------------------------
+{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE BangPatterns #-}
+module CSPM.Interpreter.Eval
+(
+  eval
+ ,getAllEvents
+ ,processDeclList
+ ,runEM
+ ,evalOutField
+ ,evalFieldSet
+ ,evalProcess
+)
+where
+
+import qualified CSPM.CoreLanguage as Core
+
+import Language.CSPM.AST as AST hiding (Bindings)
+import qualified Language.CSPM.Frontend as Frontend
+
+import CSPM.Interpreter.Types as Types
+import CSPM.Interpreter.Bindings as Bindings
+import CSPM.Interpreter.PatternMatcher
+import CSPM.Interpreter.Hash as Hash
+import CSPM.Interpreter.SSet as SSet
+import CSPM.Interpreter.ClosureSet as ClosureSet
+import CSPM.Interpreter.Renaming as Renaming
+
+import Data.Digest.Pure.HashMD5 as HashClass
+
+import Control.Arrow
+import qualified Control.Monad.Reader as Reader
+import Control.Monad.RWS.Lazy as RWS hiding (guard)
+import Control.Monad hiding (guard)
+import Data.Ord
+import Data.List as List
+import qualified Data.Set as Set
+import Data.Set (Set)
+import qualified Data.Map as Map
+import qualified Data.IntMap as IntMap
+import qualified Data.List as List
+import Debug.Trace
+
+-- | Evaluate an expression in an envirionment.
+runEval :: Env -> AST.LExp -> Value
+runEval env expr = runEM (eval expr) env
+
+-- | Run the 'EM' monad with a given envirionment.
+runEM  :: EM x -> Env -> x
+runEM action env = Reader.runReader (unEM action) env
+
+runEnv :: Env -> EM x -> x
+runEnv env action = Reader.runReader (unEM action) env
+
+{- todo : check whether the order of the cases influences efficency. -}
+
+-- | Evaluate an expression in the 'EM' monad.
+eval :: LExp -> EM Value
+eval expr = case unLabel expr of
+  Var v -> lookupIdent v
+  IntExp i -> return $ VInt i
+  SetEnum s -> do
+    l <- mapM eval s
+    return $ VSet $ Set.fromList l
+  ListEnum l -> mapM eval l >>= return . VList
+  SetOpen _  -> throwFeatureNotImplemented "open sets" $ Just $ srcLoc expr
+  ListOpen s -> do
+  -- todo : this can easily give non-termination
+  -- maybe use an enumerator here ?
+    x <- evalInt s
+    return $ VList $ map VInt [x..]
+  SetClose (a,b) -> do
+    s <- evalInt a
+    e <- evalInt b
+    return $ VSet $ Set.fromList $ map VInt [s..e]
+  ListClose (a,b) -> do
+    s <- evalInt a
+    e <- evalInt b
+    return $ VList $ map VInt [s..e]
+  SetComprehension (el,comps) -> do
+    l <- evalSetComp ret comps 
+    return $ VSet l
+    where ret = mapM eval el >>= return . Set.fromList
+  ListComprehension (el, comps) -> do
+    l <- evalListComp (mapM eval el) comps
+    return $ VList l
+  ClosureComprehension (el, comps) -> do
+    l <- evalListComp (mapM eval el) comps
+    ClosureSet.mkEventClosure l >>= return . VClosure
+  LetI decls freenames e -> do
+    env <- getEnv
+    let digest = closureDigest expr env freenames
+    return $ runEval (processDeclList digest env decls) e
+  Ifte cond t e -> do
+    c <- evalBool cond
+    if c then eval t else eval e
+  CallFunction fkt args -> do
+    f <- eval fkt
+    parameter <- mapM eval $ concat args
+    functionCall f parameter
+  CallBuiltIn bi [[e]] -> builtIn1 bi e
+  CallBuiltIn bi [[a,b]] -> builtIn2 bi a b
+  CallBuiltIn _ _
+    -> throwScriptError "calling builtIn with worng number of args"
+         (Just $ srcLoc expr) Nothing
+  Lambda {} -> throwInternalError "not expection Constructor Lambda"
+                 (Just $ srcLoc expr) $ Nothing
+  LambdaI freeNames patL body -> do
+    env <- getEnv
+    return $ VFun $ FunClosure {
+       getFunCases = [FunCaseI patL body]
+      ,getFunEnv = env
+      ,getFunArgNum = length patL
+      ,getFunId = closureDigest expr env freeNames
+      }
+  Stop -> return  $ VProcess $ Core.stop
+  Skip -> return  $ VProcess $ Core.skip
+  CTrue  -> return $ VBool True
+  Events -> liftM VClosure evalAllEvents
+  CFalse -> return $ VBool False
+  BoolSet -> return $ VSet $ Set.fromList [VBool True,VBool False]
+{-
+  many prob test contain unboundet INT
+  IntSet -> return $ VAllInts
+-}
+  IntSet -> return $ VSet $ Set.fromList $ map VInt [0..100]
+  TupleExp l -> mapM eval l >>= return . VTuple
+  Parens e -> eval e
+  AndExp a b -> do
+    av <- evalBool a
+    if av then eval b else return $ VBool False
+  OrExp a b -> do
+    av <- evalBool a
+    if av then return $ VBool True else eval b
+  NotExp e -> evalBool e >>= return . VBool . not
+  Fun1 bi e -> builtIn1 bi e
+  Fun2 bi a b -> builtIn2 bi a b
+  DotTuple l -> mapM eval l >>= return . VDotTuple . concatMap flatTuple
+    where
+      flatTuple (VDotTuple l ) = l
+      flatTuple x = [x]
+  Closure l -> mapM eval l >>= ClosureSet.mkEventClosure >>= return . VClosure
+  ProcSharing s a b
+   -> liftM3 Core.sharing
+       (switchedOffProc a)
+       (evalClosureExp s)
+       (switchedOffProc b)
+      >>= return . VProcess
+  ProcAParallel aLeft aRight pLeft pRight
+    -> liftM4 Core.aparallel
+        (evalClosureExp aLeft)
+        (evalClosureExp aRight)
+        (switchedOffProc pLeft)
+        (switchedOffProc pRight)
+      >>= return . VProcess
+  ProcLinkParallel l p q
+    -> liftM3 Core.linkParallel
+        (evalLinkList l)
+        (switchedOffProc p)
+        (switchedOffProc q)
+       >>= return . VProcess
+  ProcRenaming rlist gen proc -> do
+    pairs <- case gen of
+      Nothing -> mapM evalRenaming rlist
+      Just gen -> evalListComp (mapM evalRenaming rlist ) $ unLabel gen
+    p <- switchedOffProc proc
+    return $ VProcess $ Core.renaming (toRenaming pairs) p
+    where
+      evalRenaming :: LRename -> EM (Value,Value)
+      evalRenaming (unLabel -> Rename a b) = liftM2 (,) (eval a) (eval b)
+  ProcRepSequence comp p
+    -> evalProcCompL p comp >>= return . VProcess . Core.repSeq
+  ProcRepInternalChoice comp p
+    -> evalProcCompS p comp >>= return . VProcess . Core.repInternalChoice
+  ProcRepExternalChoice comp p
+    -> evalProcCompS p comp >>= return . VProcess . Core.repExternalChoice
+  ProcRepInterleave comp p
+    -> evalProcCompS p comp >>= return . VProcess . Core.repInterleave
+  ProcRepAParallel comp c p
+    -> evalListComp ret (unLabel comp) 
+         >>= return . VProcess . Core.repAParallel
+    where ret = do { x <- evalClosureExp c; y <- switchedOffProc p; return [(x,y)]}
+  ProcRepLinkParallel comp link p
+    -> liftM2 Core.repLinkParallel
+        (evalLinkList link)
+        (evalProcCompL p comp)
+       >>= return . VProcess
+  ProcRepSharing comp closure p -> do
+    l <- evalProcCompS p comp
+    c <- evalClosureExp closure
+    return $ VProcess $ Core.repSharing c l
+  PrefixI free chan fields body -> do
+    env <- getEnv 
+    return $ VProcess $ Core.prefix $ PrefixState {
+        prefixEnv = env
+       ,prefixFields = chanOut:fields
+       ,prefixBody = body
+       ,prefixRHS = throwInternalError "prefixRHS undefiend" (Just $ srcLoc expr) Nothing
+       ,prefixDigest = closureDigest body env free
+       ,prefixPatternFailed = False
+     }
+      where chanOut = setNode chan $ OutComm chan
+  ExprWithFreeNames body en
+    -> throwInternalError "didn't expect ExprWithFreeNames" (Just $ srcLoc expr) Nothing
+  _ -> throwFeatureNotImplemented "hit catch-all case of eval function"
+         $ Just $ srcLoc expr 
+
+evalBool :: LExp -> EM Bool
+evalBool e = do
+  v <- eval e
+  case v of
+    VBool b -> return b
+    _  -> throwTypingError "expecting type Bool" (Just $ srcLoc e) $ Just v
+
+
+evalInt :: LExp -> EM Integer
+evalInt e = do
+  v <- eval e
+  case v of
+    VInt b -> return b
+    _ -> throwTypingError "expecting type Integer" (Just $ srcLoc e) $ Just v
+
+evalList :: LExp -> EM [Value]
+evalList e = do
+  v <- eval e
+  case v of
+    VList l -> return l
+
+--  used in mydemos/SimpleRepAlphParallel.csp SYSTEM
+    VDataType l -> return $ map VConstructor l
+
+--  because of a hack in RepAParalle
+    VSet l -> return $ Set.toList l
+--  because of a hack in evalProcCompS
+    VClosure c -> return $ Set.toList $ closureToSet c
+
+    _ -> throwTypingError "expecting type List" (Just $ srcLoc e) $ Just v
+
+setFromValue :: Value -> EM (Set Value)
+setFromValue v = case setFromValueM v of
+  Just l -> return l
+  Nothing -> throwTypingError "expecting type Set" Nothing $ Just v
+
+evalSet :: LExp -> EM (Set Value)
+evalSet e = do
+  v <- eval e
+  case setFromValueM v of
+    Just l -> return l
+    Nothing -> throwTypingError "expecting type Set" (Just $ srcLoc e) $ Just v
+
+setFromValueM :: Value -> Maybe (Set Value)
+setFromValueM v = case v of
+  VSet l -> Just l
+  VClosure c -> Just $ closureToSet c
+  VDataType l -> Just $ Set.fromList  --used in basin_olderog_bank.csp
+                     $ map VConstructor l
+  _ -> Nothing
+
+evalProcess :: LExp -> EM Process
+evalProcess e = do
+  v <- eval e
+  case v of
+    VProcess p -> return p
+    _  -> throwTypingError "expecting type Process" (Just $ srcLoc e) $ Just v
+
+evalClosureExp :: LExp -> EM ClosureSet
+evalClosureExp e = do
+  v <- eval e
+  case v of
+    VClosure x -> return x
+--    VAllEvents -> evalAllEvents
+    VSet s -> return $ setToClosure s
+    _ -> throwTypingError "expecting type Event-Closure" (Just $ srcLoc e) $ Just v
+
+listFromValue :: Value -> EM [Value]
+listFromValue (VList l) = return l
+listFromValue v = throwTypingError "expecting type List" Nothing $ Just v
+
+processFromValue :: Value -> EM Process
+processFromValue (VProcess p) = return p
+processFromValue v = throwTypingError "expecting type Process" Nothing $ Just v
+
+builtIn1 :: LBuiltIn -> LExp -> EM Value
+builtIn1 op expr 
+  = case lBuiltInToConst op of
+    F_Seq -> evalSet expr >>= return . VAllSequents
+    F_card -> do
+      s <- evalSet expr
+      return $ VInt $ fromIntegral $ Set.size s
+    F_empty  -> evalSet expr >>= return . VBool . Set.null
+    F_head   -> do
+      l <- evalList expr
+      case l of
+        [] -> throwScriptError "head of empty list" (Just $ srcLoc expr) Nothing
+        h:_tail -> return h
+    F_tail   -> do
+      l <- evalList expr
+      case l of
+        [] -> throwScriptError "tail of empty list" (Just $ srcLoc expr) Nothing
+        _head:rest -> return $ VList rest
+    F_length -> evalList expr >>= return . VInt . fromIntegral . List.length
+    F_Len2   -> evalList expr >>= return . VInt . fromIntegral . List.length
+    F_Union -> do
+      s <- evalSet expr 
+      setList <- mapM setFromValue $ Set.elems s
+      return $ VSet $ Set.unions setList
+    F_Inter  -> do
+      s <- evalSet expr 
+      setList <- mapM setFromValue $ Set.elems s
+      case setList of
+        [] ->  throwScriptError "intersection of empty set of sets" 
+                  (Just $ srcLoc expr) Nothing
+        l  -> return $ VSet $ List.foldl1' Set.intersection l
+    F_set    -> evalList expr >>= return . VSet . Set.fromList
+    F_Set    -> do
+      s <- evalSet expr
+      return $ VSet $ Set.fromList $ map (VSet . Set.fromList ) 
+        $ List.subsequences $ Set.toList s
+    F_concat -> do
+      l <- evalList expr >>= mapM listFromValue
+      return $ VList $ List.concat l
+    F_null -> do
+      l <- evalList expr
+      return $ VBool (List.null l)
+    F_CHAOS -> liftM (VProcess . Core.chaos) $ evalClosureExp expr
+    c -> throwInternalError "malformed AST1" (Just $ srcLoc expr) Nothing
+
+builtIn2 :: LBuiltIn -> LExp -> LExp -> EM Value
+builtIn2 op a b =
+  case lBuiltInToConst op of
+    F_union  -> setOp Set.union
+    F_inter  -> setOp Set.intersection
+    F_diff   -> setOp Set.difference
+    F_member -> do
+      av <- eval a
+      s <- evalSet b
+      return $ VBool $ Set.member av s
+    F_Seq    -> throwFeatureNotImplemented "builtIn2 FSeq" Nothing
+    F_elem   -> do
+      av <- eval a
+      l  <- evalList b
+      return $ VBool $ List.elem av l
+    F_Concat -> do
+      x <- evalList a
+      y <- evalList b
+      return $ VList $ x ++y
+    F_Mult   -> intOp (*)
+    F_Div    -> intOp div
+    F_Mod    -> intOp mod
+    F_Add    -> intOp (+)
+    F_Sub    -> intOp (-)
+    F_Eq     -> do
+      x <- eval a
+      y <- eval b
+      return $ VBool (x == y)
+    F_NEq    -> do
+      x <- eval a
+      y <- eval b
+      return $ VBool (x /= y)
+    F_GE     -> intCmp (>=)
+    F_LE     -> intCmp (<=)
+    F_LT     -> intCmp (<)
+    F_GT     -> intCmp (>)
+    F_Sequential -> procOp Core.seq
+    F_Interrupt  -> procOp Core.interrupt
+    F_ExtChoice  -> do
+      x <- switchedOffProc a
+      y <- switchedOffProc b
+      return $ VProcess $ Core.externalChoice x y
+    F_Timeout    -> procOp Core.timeout
+    F_IntChoice  -> do
+      x <- switchedOffProc a
+      y <- switchedOffProc b
+      return $ VProcess $ Core.internalChoice x y
+    F_Interleave -> do
+      x <- switchedOffProc a
+      y <- switchedOffProc b
+      return $ VProcess $ Core.interleave x y
+    F_Hiding -> do
+      proc <- switchedOffProc a
+      hidden <- evalClosureExp b
+      return $ VProcess $ Core.hide hidden proc
+    F_Guard -> do
+      cond <- evalBool a
+      if cond then liftM VProcess $ switchedOffProc b
+              else return $ VProcess Core.stop
+    c -> throwInternalError "malformed AST2" Nothing Nothing
+  where
+    intOp :: (Integer -> Integer -> Integer) -> EM Value
+    intOp o = do
+      x <- evalInt a
+      y <- evalInt b
+      return $ VInt $ o x y
+    intCmp :: (Integer -> Integer -> Bool) -> EM Value
+    intCmp rel = do
+      x <- evalInt a
+      y <- evalInt b
+      return $ VBool $ rel x y
+    setOp :: (Set Value -> Set Value -> Set Value) -> EM Value
+    setOp o = do
+      x <- evalSet a
+      y <- evalSet b
+      return $ VSet $ o x y
+    procOp :: (Process -> Process -> Process) -> EM Value
+    procOp o = do
+      x <- switchedOffProc a
+      y <- switchedOffProc b
+      return $ VProcess $ o x y
+
+type DeclM x = RWS (Digest,Env) () (Bindings, IntMap.IntMap Digest) x
+ 
+processDeclList :: Digest -> Env -> [LDecl] -> Env
+processDeclList digest oldEnv decls =
+-- todo :: really do a lot of testing that we do not end in a loop here
+  let
+    ((),(newBinds,newDigests),()) = runRWS action (digest,newEnv) 
+       (getLetBindings oldEnv, letDigests oldEnv)
+    action = mapM_ processDecl decls
+    newEnv = oldEnv { letBindings = newBinds, letDigests = newDigests}
+  in newEnv
+
+bindIdentM :: LIdent -> Value -> DeclM ()
+bindIdentM i v = do
+  d <- asks fst
+  modify $ \(values,digests) ->
+    (bindIdent i v values
+    ,IntMap.insert (identId i) (HashClass.mixInt d $ identId i) digests)
+
+processDecl :: LDecl -> DeclM ()
+processDecl decl = do 
+  case unLabel decl of
+    PatBind pat expr -> do
+      finalEnv <- asks snd
+      let rhs = runEval finalEnv expr  -- evaluate the righthand side
+      modify $ first $ \oldBinds -> tryMatchLazy oldBinds pat rhs
+      digest <- asks fst
+      forM_ (boundNames pat) $ \i -> modify $ second
+        $ IntMap.insert (identId i) (HashClass.mixInt digest $ identId i)
+    FunBind i cases -> do
+        finalEnv <- asks snd
+        digest <- asks fst
+        bindIdentM i $ VFun $ FunClosure {
+          getFunCases = cases 
+         ,getFunEnv = finalEnv
+         ,getFunArgNum = length $ (\(FunCaseI pl _) -> pl) $ head cases
+         ,getFunId  = mixInt digest $ AST.unNodeId $ AST.nodeId decl
+         }
+  -- Just Ignore
+    AssertRef _ _ _  -> return ()
+    AssertBool _ -> return ()
+    Transparent names ->  forM_ names $ \n -> bindIdentM n cspIdentityFunction
+    SubType _ _ -> throwFeatureNotImplemented "subtype declarations" $ Just $ srcLoc decl
+    DataType tname constrList -> do
+       constrs <- mapM constrDecl constrList
+       bindIdentM tname (VDataType constrs )
+    NameType tname t -> do
+      finalEnv <- asks snd
+      bindIdentM tname (VNameType $ runEnv finalEnv $ evalTypeDef t)
+    Print _expr -> return ()
+    AST.Channel idList t -> do
+      finalEnv <- asks snd
+      forM_ idList $ \i -> bindIdentM i $ VChannel $ Types.Channel {
+              chanId = AST.uniqueIdentId $ AST.unUIdent $ unLabel i
+             ,chanName = AST.realName $ AST.unUIdent $ AST.unLabel i
+             ,chanLen = case t of
+                Nothing -> 1
+                Just t -> case unLabel t of
+                  TypeTuple l -> 2
+                  TypeDot l  -> length l +1
+             ,chanFields = case t of
+                Nothing -> []
+                Just l -> runEnv finalEnv $ evalTypeDef l
+             }
+
+constrDecl :: LConstructor -> DeclM Types.Constructor
+constrDecl (unLabel -> AST.Constructor ident td) = do
+  finalEnv <- asks snd
+  let
+    cl = case td of
+      Nothing -> []
+      Just l -> runEnv finalEnv $ evalTypeDef l
+
+    constr = Types.Constructor
+               (AST.uniqueIdentId $ AST.unUIdent $ unLabel ident)
+               (AST.realName $ AST.unUIdent $ unLabel ident)
+               cl 
+  bindIdentM ident $ VConstructor constr
+  return constr
+
+evalTypeDef :: LTypeDef -> EM [FieldSet]
+evalTypeDef t = case unLabel t of
+  TypeDot l  -> mapM evalFieldSet l
+  TypeTuple l -> do
+    el <- mapM evalFieldSet l
+    -- cross-product
+    return [SSet.fromList $ map VTuple $ sequence $ map SSet.toList el]
+
+evalFieldSet :: LExp -> EM FieldSet
+evalFieldSet expr = do
+  v <- eval expr
+  case v of
+    VInt {} -> return $ SSet.singleton v
+    VChannel {} -> return $ SSet.singleton v
+    VSet s -> return $ SSet.Proper s
+-- todo : fixthis when we have ClosureExpressions
+-- todo: this does not work for constructors that have fields
+    VDataType constrList -> return $ SSet.fromList $ map VConstructor constrList
+    VAllInts -> return $ SSet.fromList $ map VInt [0..10] --todo
+    _ -> throwTypingError "valueToEventSet " (Just $ srcLoc expr) $ Just v
+
+switchedOffProc :: LExp -> EM Process
+switchedOffProc (unLabel -> ExprWithFreeNames free expr) = do
+  env <- getEnv
+  return $ Core.switchedOff $ SwitchedOffProc {
+    switchedOffDigest = (closureDigest expr env free)
+   ,switchedOffExpr = expr
+   ,switchedOffProcess = runEM (evalProcess expr) env
+   }
+switchedOffProc exp
+ = throwInternalError "cannot determine free variables" (Just $ srcLoc exp) Nothing
+
+evalOutField :: LExp -> EM Field
+evalOutField expr = do
+  v <- eval expr
+  case v of
+    VInt {} -> return v
+    VChannel {} -> return v
+    VConstructor {} -> return v
+    VTuple {} -> return v 
+    VDotTuple {} -> return v -- todo : fix for genric buffers
+    VBool {} -> return v
+{-
+todo: support lists and sets as channel fields
+write test for VSet and VList
+-}
+    VSet {} -> return v
+    VList {} -> return v        
+
+    _ -> throwTypingError "Eval.hs : evalOutField" (Just $ srcLoc expr) $ Just v
+
+
+{- redo this: most procComprehensions work on sets ! -}
+evalProcCompL :: LExp -> LCompGenList -> EM [Process]
+evalProcCompL p comp = evalListComp ret $ unLabel comp
+  where
+    ret = do
+      r <- switchedOffProc p
+      return [r]
+
+{-
+fdr does not remove duplicates from replicatesProc compostions 
+see examples/CSP/FDRFeatureTests/ReplicatedInterleaveSetDef.csp
+-}
+evalProcCompS :: LExp -> LCompGenList -> EM [Process]
+evalProcCompS = evalProcCompL
+{-
+evalProcCompS p comp
+  =     (evalSetComp ret $ unLabel comp)
+    >>= (mapM processFromValue) . Set.toList
+  where
+{- we intermediatley wrap processes with VProcess 
+if we make evalSetComp polymorphic we get the following error
+src/Language/CSPM/Interpreter/Eval.hs:536:0:
+    Contexts differ in length
+      (Use -XRelaxedPolyRec to allow this)
+-}
+    ret = switchedOffProc p >>= return . Set.singleton . VProcess 
+-}
+
+evalListComp :: EM [x] -> [LCompGen] -> EM [x]
+evalListComp ret [] = ret
+evalListComp ret (h:t) = case unLabel h of
+  Guard g -> do
+    b <- evalBool g
+    if b then evalListComp ret t
+         else return []
+  Generator pat gen -> do
+    list <- evalList gen
+    rets <- mapM (evalCompPat pat) list
+    return $ concat rets
+  where
+    evalCompPat pat val = do
+      e <- getEnv
+      case tryMatchStrict (getArgBindings e) pat val of
+        Nothing -> return []
+        Just newBinds 
+          -> return $ runEM
+               (evalListComp ret t) 
+               (setArgBindings e newBinds)
+
+evalSetComp :: EM (Set Value) -> [LCompGen] -> EM (Set Value)
+evalSetComp ret [] = ret
+evalSetComp ret (h:t) = case unLabel h of
+    Guard g -> do
+      b <- evalBool g
+      if b then evalSetComp ret t
+           else return Set.empty
+    Generator pat gen -> do
+      set <- evalSet gen
+      rets <- mapM (evalCompPat pat) $ Set.elems set
+      return $ Set.unions rets
+    where
+      evalCompPat pat val = do
+        e <- getEnv
+        case tryMatchStrict (getArgBindings e) pat val of
+          Nothing -> return Set.empty
+          Just newBinds 
+            -> return $ runEM
+                 (evalSetComp ret t) 
+                 (setArgBindings e newBinds)
+
+evalAllEvents :: EM ClosureSet
+evalAllEvents = do
+  channels <- lookupAllChannels
+  ClosureSet.mkEventClosure $ map VChannel channels
+
+getAllEvents :: Env -> ClosureSet
+getAllEvents = runEM evalAllEvents
+
+cspIdentityFunction :: Value
+cspIdentityFunction = VFun $ FunClosure {
+   getFunCases = [funCase]
+  ,getFunEnv = emptyEnvirionment
+  ,getFunArgNum = 1
+  ,getFunId = Hash.hash "cspIdentityFunction"
+  }
+  where
+    funCase = FunCaseI [ labeled $ VarPat someId] (labeled $ Var someId)
+    someId = labeled $ UIdent $ UniqueIdent {
+      uniqueIdentId = -1
+     ,bindingSide = e
+     ,bindingLoc = e
+     ,idType = e
+     ,realName = e
+     ,newName = e
+     ,prologMode = e
+     ,bindType = NotLetBound }
+    e = throwInternalError "use identityFunction magic constants" Nothing Nothing
+
+evalLinkList :: LLinkList -> EM RenamingRelation
+evalLinkList l = case unLabel l of
+  LinkList x -> liftM toRenaming $ mapM evalLink x
+  LinkListComprehension gen links
+    -> liftM toRenaming $ evalListComp (mapM evalLink links ) gen
+  where
+    evalLink :: LLink -> EM (Value,Value)
+    evalLink (unLabel -> Link a b) = liftM2 (,) (eval a) (eval b)
+
+functionCall :: Value -> [Value] -> EM (Value)
+functionCall v arguments = case v of
+  VFun fkt -> callFkt fkt arguments
+  VPartialApplied fkt oldArgs -> callFkt fkt (oldArgs ++ arguments)
+  f -> throwTypingError "calling non-function" Nothing $ Just f
+  where
+    tryFunCases :: [FunCase] -> [Value] -> Env -> Value
+    tryFunCases [] _ _ = throwPatternMatchError "no matching function case" Nothing
+    tryFunCases ((FunCaseI parameter fktBody) : moreCases) args env =
+      case matchList parameter args (getArgBindings env) of
+        Just newBinds -> runEval (setArgBindings env newBinds) fktBody
+        Nothing -> tryFunCases moreCases args env
+    tryFunCases (FunCase {} : _) _ _
+      = throwInternalError "not expecting FunCase-Constructor" Nothing Nothing
+
+    matchList :: [LPattern] -> [Value] -> Bindings -> Maybe Bindings
+    matchList patList valList env
+      = foldM (\e (pat,val) -> tryMatchStrict e pat val) 
+         env (zip patList valList)
+
+{-
+  going from
+  callFkt fkt args = return $ tryFunCases (getFunCases fkt) args (getFunEnv fkt)
+  to the version which supports partial application
+  costs ca 17 % in the fibonacci -example
+-}
+    callFkt :: FunClosure -> [Value] -> EM Value
+    callFkt fkt args
+       = case compare haveArgs needArgs of
+           EQ -> return $ tryFunCases (getFunCases fkt) args (getFunEnv fkt)
+           GT -> do
+             f2 <- callFkt fkt $ take needArgs args
+             functionCall f2 $ drop needArgs args
+           LT -> return $ VPartialApplied fkt args
+       where
+         haveArgs = length args
+         needArgs = getFunArgNum fkt
diff --git a/src/CSPM/Interpreter/GenericBufferPrefix.hs b/src/CSPM/Interpreter/GenericBufferPrefix.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/GenericBufferPrefix.hs
@@ -0,0 +1,99 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.GenricBufferPrefix
+-- Copyright   :  (c) Fontaine 2009
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- A wrapper around CSPM.Interpreter.Prefix with support for generic buffers.
+--
+----------------------------------------------------------------------------
+{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE BangPatterns #-}
+
+module CSPM.Interpreter.GenericBufferPrefix
+(
+  initPrefix
+ ,viewPrefixState
+ ,prefixStateNext
+ ,prefixStateFinalize
+)
+where
+
+import qualified CSPM.CoreLanguage as Core
+import Language.CSPM.AST as AST hiding (Bindings)
+
+import CSPM.Interpreter.Types as Types
+import CSPM.Interpreter.Bindings as Bindings
+import CSPM.Interpreter.PatternMatcher
+import CSPM.Interpreter.Eval
+import qualified CSPM.Interpreter.Prefix as BasePrefix
+import CSPM.Interpreter.SSet as SSet
+
+import Data.List as List
+import Control.Monad
+
+initPrefix :: PrefixState -> GenericBufferPrefix
+initPrefix = lookAhead . BasePrefix.initPrefix
+
+viewPrefixState :: GenericBufferPrefix -> Core.PrefixFieldView INT
+viewPrefixState p = case p of
+  GBOut (h:_) _ -> Core.FieldOut h
+  GBOut [] _ -> error "GenericBuffer.hs : viewPrefixState : internal error : empty buffer"
+  GBInput _ -> Core.FieldIn
+  GBInputGuard g _ -> Core.FieldGuard g
+  GBInputGeneric _ _ -> Core.FieldIn
+  GBFinished _ -> error "GenericBuffer.hs : viewPrefixState : no fields left"
+ 
+prefixStateNext :: GenericBufferPrefix -> Field -> Maybe GenericBufferPrefix
+prefixStateNext gbPrefix field = case gbPrefix of
+  GBOut [h] p -> do
+    guard $ h == field
+    liftM lookAhead $ BasePrefix.prefixStateNext p (error "GenericBufferDummyFields")
+  GBOut (h:t) p -> do
+    guard $ h == field
+    return $ GBOut t p
+  GBInput p -> liftM lookAhead $ BasePrefix.prefixStateNext p field
+  GBInputGuard g p -> do
+    guard $ field `SSet.member` g
+    liftM lookAhead $ BasePrefix.prefixStateNext p field
+  GBInputGeneric b p -> return $ GBInputGeneric (field:b) p
+  GBFinished _ -> error "GenericBuffer.hs : prefixStateNext : no fields left"
+
+prefixStateFinalize :: GenericBufferPrefix -> Maybe PrefixState
+prefixStateFinalize gbPrefix = case gbPrefix of
+  GBInputGeneric buffer p -> case buffer of
+   [] -> error "GenericBuffer.hs : empty dot tuple"
+   [v] -> BasePrefix.prefixStateNext p v >>= BasePrefix.prefixStateFinalize
+   l -> BasePrefix.prefixStateNext p (VDotTuple $ reverse l)
+      >>= BasePrefix.prefixStateFinalize
+  GBFinished p -> BasePrefix.prefixStateFinalize p
+  _ -> error "GenericBuffer.hs : stateError"
+
+lookAhead :: PrefixState -> GenericBufferPrefix
+lookAhead p | List.null $ prefixFields p = GBFinished p
+lookAhead p | isLastInputField p = GBInputGeneric [] p
+lookAhead p = case BasePrefix.viewPrefixState p of
+  Core.FieldOut v -> case v of
+    (VDotTuple l) -> GBOut (splitTuple l) p
+    x -> GBOut [x] p
+  Core.FieldIn -> GBInput p
+  Core.FieldGuard g -> GBInputGuard g p
+
+isLastInputField :: PrefixState -> Bool
+isLastInputField (PrefixState {
+  prefixFields =  [unLabel -> InComm (unLabel -> VarPat _ )] 
+  }) = True
+{- todo : fields that end with wildcard c?_ -> x -}
+isLastInputField _ = False
+
+splitTuple :: [Value] -> [Value]
+splitTuple [] = []
+splitTuple l@(h:t) = case h of
+  VConstructor c | not $ List.null $ constrFields c
+    -> VDotTuple (take len l) : splitTuple (drop len l)
+         where len = 1 + (length $ constrFields c)
+  _ -> h : splitTuple t
diff --git a/src/CSPM/Interpreter/Hash.hs b/src/CSPM/Interpreter/Hash.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/Hash.hs
@@ -0,0 +1,146 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.Hash
+-- Copyright   :  (c) Fontaine 2008
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+-- 
+-- Instances of the Hash class for interpreter types and core language types
+--
+----------------------------------------------------------------------------
+{-# LANGUAGE TypeSynonymInstances,FlexibleInstances #-}
+
+module CSPM.Interpreter.Hash
+(
+  mix
+ ,mix3
+ ,MD5Digest (..)
+ ,Hash (..)
+ ,hs
+ ,closureDigest
+ ,mixInt
+)
+where
+
+import CSPM.CoreLanguage hiding (PrefixState, Event)
+
+import qualified Language.CSPM.AST as AST
+import CSPM.Interpreter.Types as Types
+import CSPM.Interpreter.SSet
+
+import Data.Digest.Pure.HashMD5
+import Data.Digest.Pure.MD5
+
+import qualified Data.Set as Set
+import qualified Data.IntMap as IntMap
+import qualified Data.Map as Map
+
+hs :: String -> Digest
+hs = hash
+
+instance Hash Value where
+  hash = hashValue
+
+hashValue :: Value -> Digest
+hashValue v = case v of
+   VInt i -> if i == fromIntegral int
+     then mixInt (hs "VInt") int
+     else error $ "Hash.hs : integer out of bounds" ++ show i
+     where int = fromIntegral i
+   VBool True  -> hs "VBool True"
+   VBool False -> hs "VBool False"
+   VList l -> foldHash (hs "VList") l
+   VTuple l -> foldHash (hs "VTuple") l
+   VDotTuple l -> foldHash (hs "VDotTuple") l
+   VSet s  -> foldHash (hs "VSet") $ Set.toAscList s
+   VClosure c -> mix (hs "VClosure") $ hash c
+   VFun f     -> mix (hs "VFun") $ hash f
+   VProcess p -> hashProcess p
+   VChannel c -> mixInt (hs "VChannel") $ chanId c
+   VUnit -> hs "VUnit"
+   VAllInts -> hs "VAllInts"
+   VAllSequents s -> foldHash (hs "VAllSequents" ) $ Set.toAscList s
+--   VAllEvents -> hs "VAllEvents"
+   VConstructor c -> mix (hs "VConstructor") $ hash c
+   VDataType d -> foldHash (hs "VDataType") d
+   VNameType _d -> error "Hash : hash nametype " --foldHash (hs "VNameType") d
+   VPartialApplied f l -> mix3 (hs "VPartialApplied") (hash f) (hash l)
+
+-- todo :: cache the digests in the envrionments
+instance Hash AST.LExp where
+  hash expr = mixInt (hs "AST.LExp") $ AST.unNodeId $ AST.nodeId expr
+
+closureDigest :: AST.LExp -> Env -> AST.FreeNames -> Digest
+closureDigest expr env free = foldHash (hs "closureDigest") ( (hash expr) : binds)
+  where
+    binds = map lookupAndHash $ IntMap.elems free
+   {- todo : remove distinction between LetBound and NotLetBound
+      store precomputed CspCore.Digest in Bindings -}
+    lookupAndHash :: AST.UniqueIdent -> Digest
+    lookupAndHash ident
+      = mixInt h i
+      where
+        !i = AST.uniqueIdentId ident
+        !h = case AST.bindType ident of
+                AST.NotLetBound -> case IntMap.lookup i (argBindings env) of
+                    Just val -> hash val
+                    Nothing -> err
+                AST.LetBound    -> case IntMap.lookup i (letDigests env) of
+                    Just d -> d
+                    Nothing -> err
+
+        err = error ( "Hash.hs Bindings lookup failure :" 
+                        ++ "\n\n" ++ show expr
+                        ++ "\n\n" ++ show free
+                        ++ "\n\n" ++ show ident
+                        ++ "\n\n" ++ (show $ argBindings env)
+                        )
+
+
+hashProcess :: Types.Process -> Digest
+hashProcess proc = case proc of
+  Prefix e -> mix (hs "Prefix") $ hash e
+  ExternalChoice a b -> mix3 (hs "ExtChoice") (hash a) (hash b)
+  InternalChoice a b -> mix3 (hs "InternalChoice") (hash a) (hash b)
+  Interleave a b -> mix3 (hs "Interleave") (hash a) (hash b)
+  Interrupt a b -> mix3 (hs "Interrupt") (hash a) (hash b)
+  Timeout a b -> mix3 (hs "Timeout") (hash a) (hash b)
+  Sharing a e b -> mix (hs "Sharing") $ mix3 (hash a) (hash e) (hash b)
+  AParallel c1 c2 p q -> mix3 (hs "AParalle") (hash c1) $ mix3 (hash c2) (hash p) (hash q)
+  Seq a b -> mix3 (hs "Seq") (hash a) (hash b)
+  Hide s e -> mix3 (hs "Hide") (hash s) $ hash e
+  Stop -> hs "Stop"
+  Skip -> hs "Skip"
+  Omega -> hs "Omega"
+  AProcess i -> mixInt (hs "AProcess") i
+  SwitchedOff p -> mix (hs "SwitchedOff") $ hash p
+  RepAParallel l -> foldHash (hs "RepAParallel") l
+  Renaming r p -> mix3 (hs "Renaming") (hash r) (hash p)
+  Chaos c -> mix (hs "Chaos") $ hash c
+  LinkParallel c p q -> mix (hs "LinkParallel") $ mix3 (hash c) (hash p) (hash q)
+
+instance Hash Types.Process where hash = hashProcess
+instance Hash PrefixState where hash = prefixDigest
+instance Hash SwitchedOffProc where hash = switchedOffDigest
+instance Hash Types.ClosureSet where hash = closureSetDigest
+instance Hash Types.RenamingRelation where hash = renamingDigest
+instance Hash Constructor where hash c = mixInt (hs "Constructor") $ constrId c
+instance Hash FunClosure where hash = getFunId
+
+
+hashEventSlice :: SSet Event -> Digest
+hashEventSlice x = case x of
+  Total -> hs "EventSlice Total"
+  Empty -> hs "EventSlice Empty"
+  (Proper x) -> foldHash (hs "EventSlice") $ Set.elems x
+
+instance Hash PrefixTrie where
+  hash p = case p of
+    PTNil -> hs "PTNil"
+    PTAny l -> mix (hs "PTAny") $ hash l
+    PTMap l -> foldHash (hs "PTMap") $ Map.assocs l
+    PTRec s t -> mix (hs "PRRec") $ foldHash (hash t) $ Set.toList s
+    PTClosure t -> mix (hs "PTClosure") $ hash t
diff --git a/src/CSPM/Interpreter/PatternMatcher.hs b/src/CSPM/Interpreter/PatternMatcher.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/PatternMatcher.hs
@@ -0,0 +1,217 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.PatternMatcher
+-- Copyright   :  (c) Fontaine 2008
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- Execute the selectors of a compilied pattern with a Value.
+--
+----------------------------------------------------------------------------
+{-
+todo :
+Compiling selectors to pattern meight be an over-kill.
+maybe its simpler and faster to implement direct pattern-matching
+-}
+{-# LANGUAGE BangPatterns, ViewPatterns #-}
+module CSPM.Interpreter.PatternMatcher
+(
+ match
+,tryMatchStrict
+,tryMatchLazy
+,boundNames
+)
+where
+
+import Language.CSPM.AST as AST hiding (Bindings)
+import CSPM.Interpreter.Types as Types
+import CSPM.Interpreter.Bindings
+
+import Data.Maybe
+import qualified Data.Set as Set
+import Control.Exception
+import Data.Array.IArray as Array
+import qualified Data.List as List
+
+failedMatch :: Maybe Value
+failedMatch = Nothing
+
+typeError :: String -> Value -> Maybe Value
+typeError x v = throwTypingError ("error in pattern-match : "++ x) Nothing $ Just v
+
+-- todo make match strict !BangPattern
+match :: Value -> Selector -> Maybe Value
+match (VInt a) (IntSel b) = if a==b then return VUnit else failedMatch
+match v        (IntSel _) = typeError "expecting Int" v
+
+match (VBool True)  TrueSel = return VUnit
+match (VBool False) TrueSel = failedMatch
+match v             TrueSel = typeError "expecting Bool" v
+
+match (VBool True)  FalseSel = failedMatch
+match (VBool False) FalseSel = return VUnit
+match v             FalseSel = typeError "expecting Bool" v
+
+match x             SelectThis = return x
+
+match (VChannel ch)  (ConstrSel ident)
+  = if AST.uniqueIdentId ident == chanId ch then return VUnit else failedMatch
+match (VConstructor (Types.Constructor i _ _))  (ConstrSel ident)
+  = if AST.uniqueIdentId ident == i then return VUnit else failedMatch
+match v             (ConstrSel c) = typeError ("expecting constructor " ++ show c) v
+--  | DotSel Int Int Selector
+
+match (VSet _)      (SingleSetSel _)
+  = throwFeatureNotImplemented "single set pattern" Nothing
+match v             (SingleSetSel _) = typeError "expecting a set" v
+
+match (VSet s)      EmptySetSel
+  =  if Set.null s then return VUnit else failedMatch
+match v             EmptySetSel    = typeError "expecting a set" v
+
+-- todo : really test this
+match (VList l) p = case p of
+  ListIthSel i next -> match (l !! i) next
+  ListLengthSel 0 _next
+    -> if null l then return VUnit else failedMatch
+  ListLengthSel len next
+    -> if length l == len then matchList len l next else failedMatch
+  _ -> matchList (length l) l p
+
+
+match t@(VTuple b)  (TupleLengthSel len next)
+  = if length b == len then match t next else typeError "tuple wrong arity" t
+match v             (TupleLengthSel _ n) = typeError "expecting tuple" v
+
+match (VTuple b)    (TupleIthSel i next) = match (b !! i) next
+match v             (TupleIthSel _ n) = typeError "expecting tuple" v
+
+match (VDotTuple l) (DotSel i next) = match (l !! i) next
+match v             (DotSel _ _) = typeError "expecting dot-tuple" v
+
+match v p
+  = throwInternalError ("hit catchall case of pattern-matcher :" ++ show (v,p))
+      Nothing $ Just v
+
+matchList :: Int -> [Value] -> Selector -> Maybe Value
+matchList s !l !sel = case sel of
+  SelectThis -> return $ VList l
+  HeadSel next
+    -> if null l then failedMatch else match (head l) next
+  HeadNSel len next
+    -> if s >= len
+         then matchList len (take len l) next
+         else failedMatch
+  PrefixSel offset len next
+    -> if s >= offset + len
+         then matchList len (take len $ drop offset l) next
+         else failedMatch
+  TailSel next 
+    -> if not $ null l then matchList (s-1) (tail l) next else failedMatch
+  SliceSel offsetL offsetR next
+    -> if s >= offsetL + offsetR
+         then
+           let
+             newLen = s - offsetL -offsetR 
+           in matchList newLen (take newLen $ drop offsetL l) next              
+         else failedMatch
+  SuffixSel offset len next
+    -> if s >= offset + len
+         then 
+           let
+             offsetLeft = s - offset - len
+           in matchList len (take len $ drop offsetLeft l) next
+         else failedMatch
+  ListLengthSel len next
+    -> if s == len then matchList s l next else failedMatch
+  ListIthSel i next -> match (l !! i) next
+  other -> throwTypingError ("matchList : not excpecting a List :" ++ show other)
+    Nothing (Just $ VList l)
+
+
+{-
+If we force the result we first force the value we match against
+and then we check all selectors !
+We must be careful about lazyness/strictness here !
+todo: maybe use ST-Transformer to fold over the array / do some optimisations
+avoid detour via lists
+
+-}
+
+-- | tryMatchStrict returns Nothing or a new Binding
+tryMatchStrict :: Bindings -> LPattern -> Value -> Maybe Bindings
+tryMatchStrict !binds p !val = case unLabel p of
+  VarPat ident -> Just $ bindIdent ident val binds
+
+  Selector sel ident -> case match val sel of
+     Nothing -> Nothing
+     Just valPart -> case ident of
+       Nothing -> Just binds
+       Just i -> Just $ bindIdent i valPart binds
+
+  Selectors selectorL identArray -> do
+    values <- matchGroup val selectorL
+    let 
+      addBind b i = case identArray Array.! i of 
+        Just n -> bindIdent n (values Array.! i) b
+        Nothing -> b
+    return $ List.foldl' addBind binds $ Array.indices identArray
+  _ -> throwInternalError "PatternMatcher : unsupported Pattern in strict match"
+         (Just $ srcLoc p) Nothing
+
+-- | tryMatchLazy allways return a new Binding, but may throw a error when
+-- | any value in the binding is forced 
+-- | forcing one of the values causes all the selectors being tested
+
+{-
+todo : Fix THISBUG:
+If we have Selectors which all do not bind a new Ident,
+still should to force the value , so that we can detect a failing match
+-}
+
+tryMatchLazy :: Bindings -> LPattern -> Value -> Bindings
+tryMatchLazy binds p@(unLabel -> VarPat ident) val
+  = bindIdent ident val binds
+tryMatchLazy binds p@(unLabel -> Selector sel ident) val
+  = case ident of
+      Just i -> bindIdent i valPart binds
+      Nothing -> binds -- THISBUG
+  where
+    valPart = case match val sel of
+      Just v -> v
+      Nothing -> throwPatternMatchError "pattern-match failure" (Just $ srcLoc p) $ Just val
+
+tryMatchLazy binds sel@(unLabel -> Selectors selectorss identArray) val
+  = List.foldl' addBind binds $ Array.indices identArray
+  where
+    values = case matchGroup val selectorss of
+      Just x -> x
+      Nothing -> throwPatternMatchError "pattern-match failure"
+         (Just $ srcLoc sel) $ Just val
+    addBind b i = case identArray Array.! i of 
+      Just n -> bindIdent n (values Array.! i) b
+      Nothing -> b -- THISBUG
+tryMatchLazy _ p v
+  = throwInternalError "PatternMatcher : unsupported Pattern in lazyMatch"
+      (Just $ srcLoc p) $ Just v
+
+{-
+If we force one of the values, we also have to force all
+of the corresponding linear selectors !!
+todo : for efficiency specialize this for small selectors
+-}
+matchGroup :: Value -> Array Int Selector -> Maybe (Array Int Value)
+matchGroup val sel = do
+  l <- mapM (match val) $ Array.elems sel
+  return $ Array.listArray (Array.bounds sel) l
+
+
+boundNames :: LPattern -> [LIdent]
+boundNames pat = case unLabel pat of
+  VarPat i -> [i]
+  Selector _ Nothing -> []
+  Selector _ (Just i) -> [i]
+  x@(Selectors {}) -> catMaybes $ Array.elems $ idents x
diff --git a/src/CSPM/Interpreter/Prefix.hs b/src/CSPM/Interpreter/Prefix.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/Prefix.hs
@@ -0,0 +1,76 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.Prefix
+-- Copyright   :  (c) Fontaine 2009
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+--
+--
+----------------------------------------------------------------------------
+{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE BangPatterns #-}
+module CSPM.Interpreter.Prefix
+(
+  initPrefix
+ ,viewPrefixState
+ ,prefixStateNext
+ ,prefixStateFinalize
+)
+where
+
+import CSPM.Interpreter.Types as Types
+import CSPM.Interpreter.Bindings as Bindings
+import CSPM.Interpreter.PatternMatcher
+import CSPM.Interpreter.Eval
+import CSPM.Interpreter.SSet as SSet
+
+import qualified CSPM.CoreLanguage as Core
+import Language.CSPM.AST as AST hiding (Bindings)
+
+import Data.List as List
+import Control.Monad
+
+initPrefix :: PrefixState -> PrefixState
+initPrefix = id
+
+viewNextPrefixField :: PrefixState -> CommField
+viewNextPrefixField = unLabel . head . prefixFields
+
+viewPrefixState :: PrefixState -> Core.PrefixFieldView INT
+viewPrefixState p | List.null $ prefixFields p
+  = throwScriptError "viewPrefixState: no fields" Nothing Nothing
+viewPrefixState p = case viewNextPrefixField p of
+  OutComm out -> Core.FieldOut $ runEM (evalOutField out) env
+  InComm pat -> Core.FieldIn
+  InCommGuarded _pat g -> Core.FieldGuard $ runEM (evalFieldSet g) env
+  where env = prefixEnv p
+
+prefixStateNext :: PrefixState -> Field -> Maybe PrefixState
+prefixStateNext p field | List.null $ prefixFields p
+  = throwScriptError "prefixStateNext no fields" Nothing Nothing
+prefixStateNext p field = case viewNextPrefixField p of
+{- todo ::
+  we must check that the Field is OK here
+  we should use the lookahead scheme of the GenericBufferPrefix
+-}
+  OutComm out -> return $ p { prefixFields = tail $ prefixFields p }
+  InComm pat -> prefixBindInput field pat
+  InCommGuarded pat g -> prefixBindInput field pat
+  where
+    env = prefixEnv p
+    prefixBindInput field pat = do
+      newBinds <- tryMatchStrict (argBindings env) pat field
+      return p {
+           prefixFields = tail $ prefixFields p
+          ,prefixEnv = setArgBindings env newBinds }
+
+prefixStateFinalize :: PrefixState -> Maybe PrefixState
+prefixStateFinalize p | prefixPatternFailed p = Nothing
+prefixStateFinalize p | not $ List.null $ prefixFields p
+  = throwScriptError "prefixStateFinalize: unsynchronized fields left" Nothing Nothing
+prefixStateFinalize p
+  = Just $ p { prefixRHS = runEM (evalProcess $ prefixBody p) (prefixEnv p) }  
diff --git a/src/CSPM/Interpreter/PrepareAST.hs b/src/CSPM/Interpreter/PrepareAST.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/PrepareAST.hs
@@ -0,0 +1,125 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.PrepareAST
+-- Copyright   :  (c) Fontaine 2008
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- These are preprocessing steps which are specific for the interpreter.
+-- Those steps of general use are in the CSPM-Frontend-package
+--
+----------------------------------------------------------------------------
+{-# LANGUAGE ViewPatterns #-}
+module CSPM.Interpreter.PrepareAST
+(
+  prepareAST
+)
+where
+
+import Language.CSPM.AST as AST
+import qualified Language.CSPM.Frontend as Frontend
+
+import Data.Generics.Schemes (everywhere)
+import Data.Generics.Aliases (mkT)
+import Data.Generics.Basics (Data)
+
+prepareAST :: LModule -> LModule
+prepareAST ast = replaceFunCase $ addFreeNames ast
+{-
+ReplaceFunCase with funCaseNew.
+This is a quickfix
+In CSPM Syntax we have tree cases: fun(x)(y) fun(x,y) and fun((x,y))
+we want to map them to : fun x y and fun (x,y) in Haskell-Syntax.
+-}
+replaceFunCase :: LModule -> LModule
+replaceFunCase ast = everywhere (mkT compFC) ast
+  where
+    compFC :: FunCase -> FunCase
+    compFC (FunCase args expr)= FunCaseI (concat args) expr
+    compFC (FunCaseI _ _) 
+      = error "Internal Error : Did not expect FunCaseI in parse result"
+{-
+    flatArgs args = case args of
+      [x] -> x
+      _     -> map wrapTuple args
+
+    wrapTuple [a] = a  -- one-element lists are not Tuples ?
+    wrapTuple x   =(AST.labeled . TuplePat) x
+-}
+
+
+-- | Perform a freename analyzis for the body of prefixOperations
+-- | and expressions that can become process-closures.
+-- | This is ugly !!.
+addFreeNames :: LModule -> LModule
+addFreeNames ast = everywhere trans ast
+  where
+    trans :: Data a => a-> a
+    trans = mkT mkExp -- . mkT mkFunBind
+
+    fn :: LExp -> LExp
+    fn expr = setNode expr
+        $ ExprWithFreeNames (Frontend.computeFreeNames expr) expr
+
+{-
+    mkFunBind :: Decl -> Decl
+    mkFunBind (FunBind i c) = FunBindI i (Frontend.computeFreeNames c) c
+    mkFunBind o = o
+-}
+
+    mkExp :: Exp -> Exp
+    mkExp expr = case expr of
+      Let decls e
+        -> LetI decls (Frontend.computeFreeNames (decls,expr)) e
+      Lambda p e
+        -> LambdaI (Frontend.computeFreeNames (p,e)) p  e
+      PrefixExp c f p
+        -> PrefixI (Frontend.computeFreeNames (c,f,p) ) c f p
+      ProcSharing s a b
+        -> ProcSharing s (fn a) (fn b)
+      ProcAParallel l r a b
+        -> ProcAParallel l r (fn a) (fn b)
+      ProcLinkParallel l a b
+        -> ProcLinkParallel l (fn a) (fn b)
+      ProcRenaming r gen p
+        -> ProcRenaming r gen $ fn p
+      ProcRepSequence l p 
+        -> ProcRepSequence l $ fn p
+      ProcRepInternalChoice l p
+        -> ProcRepInternalChoice l $ fn p
+      ProcRepInterleave l p
+        -> ProcRepInterleave l $ fn p
+      ProcRepExternalChoice l p
+        -> ProcRepExternalChoice l $ fn p
+      ProcRepAParallel l a p
+        -> ProcRepAParallel l a $ fn p
+      ProcRepLinkParallel l e p
+        -> ProcRepLinkParallel l e $ fn p
+      ProcRepSharing l e p
+        -> ProcRepSharing l e $ fn p
+-- this is really ugly
+      CallBuiltIn x@(unLabel -> BuiltIn bi) [[a,b]]
+          -> let constr = CallBuiltIn x in case bi of
+        F_Sequential -> constr [[fn a,fn b]]
+        F_Interrupt -> constr [[fn a,fn b]]
+        F_ExtChoice -> constr [[fn a,fn b]]
+        F_Timeout -> constr [[fn a,fn b]]
+        F_IntChoice -> constr [[fn a,fn b]]
+        F_Interleave -> constr [[fn a,fn b]]
+        F_Hiding -> constr [[fn a,b]]
+        _ -> constr [[a,b]]
+      Fun2  x@(unLabel -> BuiltIn bi) a b
+          -> let constr = Fun2 x in case bi of
+        F_Sequential -> constr (fn a) (fn b)
+        F_Interrupt -> constr (fn a) (fn b)
+        F_ExtChoice -> constr (fn a) (fn b)
+        F_Timeout -> constr (fn a) (fn b)
+        F_IntChoice -> constr (fn a) (fn b)
+        F_Interleave -> constr (fn a) (fn b)
+        F_Hiding -> constr (fn a) b
+        F_Guard -> constr a (fn b)
+        _ -> constr a b
+      other -> other
diff --git a/src/CSPM/Interpreter/Renaming.hs b/src/CSPM/Interpreter/Renaming.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/Renaming.hs
@@ -0,0 +1,95 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.Renaming
+-- Copyright   :  (c) Fontaine 2009
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- Utility functions dealing with renaming relations.
+----------------------------------------------------------------------------
+{-
+naive implementation of a renaming relation.
+todo: mode efficent implementation
+-}
+module CSPM.Interpreter.Renaming
+where
+
+import CSPM.Interpreter.Types as Types
+import CSPM.Interpreter.Hash as Hash
+import CSPM.Interpreter.ClosureSet
+
+import qualified Data.List as List
+import Data.Set (Set)
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+
+{- todo speedup using hashing -}
+toRenaming :: [(Value,Value)]-> RenamingRelation
+toRenaming s = RenamingRelation {
+    renamingPairs = pairs
+   ,renamingDigest = renameDigest pairs
+   ,renamingDomain = Set.map fst pairs
+   ,renamingRange = Set.map snd pairs
+  } where
+  pairs = Set.unions $ map pairToRel s
+  pairToRel :: (Value,Value) -> Set (Event,Event)
+  pairToRel (a,b) = Set.fromList $ do
+   (VDotTuple p1) <- Set.toList $ prefixTrieToSet $ valueToPT a
+   return (p1, newPrefix ++ drop plen p1)
+   where
+     plen = prefixLen a    
+     newPrefix = valueToPrefix b
+
+  valueToPrefix :: Value -> [Value]
+  valueToPrefix v = case v of
+    VChannel _ -> [v]
+    VDotTuple l@(VChannel _ : _) -> l
+    VDotTuple [] -> throwScriptError "toRenaming1 : empty dot-tuple" Nothing Nothing
+    VDotTuple _ -> throwScriptError "toRenaming1 : dot-tuple does not start with a channel"
+                     Nothing (Just v)
+    _ -> throwScriptError "toRenaming1 : cannot make renaming"
+           Nothing $ Just v
+
+  prefixLen :: Value -> Int
+  prefixLen v = case v of
+    VChannel _ -> 1
+    VDotTuple l@(VChannel _ : _) -> length l
+    VDotTuple [] -> throwScriptError "toRenaming2 : empty dot-tuple" Nothing Nothing
+    VDotTuple _ -> throwScriptError "toRenaming2 : dot-tuple does not start with a channel"
+                     Nothing (Just v)
+    _ -> throwScriptError "toRenaming2 : cannot make renaming"
+           Nothing $ Just v
+
+renameDigest :: Set (Event,Event) -> Digest
+renameDigest pairs
+  = mix3 (hs "RenamingRelation")
+     (hash $ map fst $ Set.toList pairs)
+     (hash $ map snd $ Set.toList pairs)
+
+{-
+inverseRenaming :: RenamingRelation -> RenamingRelation
+inverseRenaming r
+  = RenamingRelation {
+    renamingPairs = pairs
+   ,renamingDigest = renameDigest pairs
+   ,renamingDomain = renamingRange r
+   ,renamingRange = renamingDomain r } 
+  where
+    pairs = Set.map (\(a,b) -> (b,a)) $ renamingPairs r
+-}
+
+{- sets have actually no advantage because we convert to lists anyway -} 
+
+imageRenaming1 :: RenamingRelation -> Event -> [Event]
+imageRenaming1 relation prefix
+  = List.map snd $ List.filter (\(x,_) -> x == prefix) $ Set.toList $ renamingPairs relation
+
+imageRenaming2 :: RenamingRelation -> Event -> [Event]
+imageRenaming2 relation prefix
+  = List.map fst $ List.filter (\(_,x) -> x == prefix) $ Set.toList $ renamingPairs relation
+
+isInRelation :: RenamingRelation -> Event -> Event -> Bool
+isInRelation rel a b = (a,b) `Set.member` renamingPairs rel
diff --git a/src/CSPM/Interpreter/SSet.hs b/src/CSPM/Interpreter/SSet.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/SSet.hs
@@ -0,0 +1,149 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.SSet
+-- Copyright   :  (c) Fontaine 2009
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- 
+--
+----------------------------------------------------------------------------
+
+{-
+probably obsolete
+
+Sets extended with a symbolic representations for
+Empty maps
+Total maps
+and the difference of a total map and an normal map.
+do we need a fiths case PosNeg Set Set ?
+this is a general datastructure that deserves its own package
+think of this in terms of the corresponding boolsche expressions !
+-}
+module CSPM.Interpreter.SSet
+where
+
+import Data.Set (Set)
+import qualified Data.Set as Set
+import qualified Data.List as List
+
+data SSet a=
+   Proper { fromProper :: (Set a)}
+ | Empty
+ | Total
+ | Inverse  { fromInverse :: (Set a)}
+ deriving (Eq,Ord)
+
+instance (Show a) => Show (SSet a) where
+  show (Proper m) = "(Set ::" ++ show  (Set.toList m) ++ ")"
+  show Empty = "EmptySet"
+  show Total = "TotalSet"
+  show (Inverse _) = "InverseSet"
+
+intersection :: Ord a => SSet a -> SSet a -> SSet a
+
+intersection(Proper s1) (Proper s2)
+  = let t = Set.intersection s1 s2 in 
+     if (Set.null t) then Empty else Proper t
+intersection (Proper _) Empty = Empty
+intersection (Proper m1) Total = Proper m1
+intersection Total (Proper m2) = Proper m2
+intersection Total Total = Total
+intersection Empty Empty = Empty
+intersection Empty (Proper _) = Empty
+intersection Total Empty = Empty
+intersection Empty Total = Empty
+intersection Empty  (Inverse _) = Empty
+intersection (Inverse _) Empty= Empty
+-- representation for diff not implemented
+intersection (Inverse s1) (Proper s2) = Proper $ Set.difference s2 s1
+intersection (Proper s1) (Inverse s2) = Proper $ Set.difference s1 s2
+intersection a@(Inverse _) Total = a
+intersection Total a@(Inverse _) = a
+intersection (Inverse s1) (Inverse s2) = Inverse $ Set.union s1 s2
+
+difference :: Ord a => SSet a -> SSet a -> SSet a
+difference(Proper s1) (Proper s2)
+  = let t = Set.difference s1 s2 in 
+     if (Set.null t) then Empty else Proper t
+
+difference a@(Proper _) Empty = a
+difference (Proper _) Total = Empty
+difference Total (Proper m2) = Inverse m2
+difference Total Total = Empty
+difference Empty Empty = Empty
+difference Empty (Proper _) = Empty
+difference Total Empty = Total
+difference Empty Total = Empty
+difference Empty  (Inverse _) = Empty
+difference a@ (Inverse _) Empty= a
+-- representation for diff not implemented
+difference (Inverse a) (Proper b) = Inverse $ Set.union a b
+difference (Proper a) (Inverse b) = Inverse $ Set.union a b
+difference (Inverse _) Total = Empty
+difference Total (Inverse s) = Proper s
+difference (Inverse a) (Inverse b) = Inverse $ Set.union a b
+
+member :: Ord a => a -> SSet a -> Bool
+member x (Proper s) = Set.member x s
+member _ Empty = False
+member _ Total = True
+member x (Inverse s) = not $ Set.member x s
+
+union :: Ord a => SSet a -> SSet a -> SSet a
+
+union(Proper s1) (Proper s2) = Proper $ Set.union s1 s2
+union a@(Proper _) Empty = a
+union (Proper _) Total = Total
+union Total (Proper _) = Total
+union Total Total = Total
+union Empty Empty = Empty
+union Empty a@(Proper _) = a
+union Total Empty = Total
+union Empty Total = Total
+
+union Empty  a@(Inverse _) = a
+union a@(Inverse _) Empty = a
+-- representation for diff not implemented
+union (Inverse i) (Proper s) = Inverse $ Set.difference i s
+union (Proper s) (Inverse i) = Inverse $ Set.difference i s
+union (Inverse _) Total = Total
+union Total (Inverse _) = Total
+union (Inverse s1) (Inverse s2) = Inverse $ Set.intersection s1 s2
+
+fromList :: Ord a => [a] -> SSet a
+fromList = Proper . Set.fromList
+
+unions :: Ord a => [SSet a] -> SSet a
+unions l = List.foldl' union Empty l 
+
+singleton :: Ord a => a -> SSet a
+singleton = Proper . Set.singleton 
+
+toList :: SSet a -> [a]
+toList m = case m of
+  Proper s -> Set.toList s
+  Empty -> []
+  Total -> error "SSet.hs : toList Total"
+  Inverse _ -> error "SSet.hs : toList Inverse"
+
+null :: SSet a -> Bool
+null Empty = True
+null (Proper m)
+  = if (Set.null m) then error "SSet.hs : isAllwayEmpty :: not symbolic"
+       else False
+null _ = False
+
+
+insert :: Ord a => a -> SSet a -> SSet a
+insert e sy = case sy of
+  Proper s -> Proper $ Set.insert e s
+  _ -> error "SSet.hs : todo: implement insert"
+
+delete :: Ord a => a -> SSet a -> SSet a
+delete e sy = case sy of
+  Proper s -> Proper $ Set.delete e s
+  _ -> error "SSet.hs : todo: implement delete"
diff --git a/src/CSPM/Interpreter/Test/CLI.hs b/src/CSPM/Interpreter/Test/CLI.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/Test/CLI.hs
@@ -0,0 +1,139 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.Test.CLI
+-- Copyright   :  (c) Fontaine 2008
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- This is mainly useful for testing the functional sub language.
+-- This module does not allow tracing of processes
+-- (tracing is implemented in an other package).
+--
+-- 'runFile' loads a CSPM-specification from a file and evaluates an expression in
+-- the context of that specification.
+--
+-- Example:
+--
+--    'runFile' fib.csp fib(10)
+--
+-- where the file fib.csp contains:
+--    fib(x)= if x <2 then 1 else fib(x-1)+fib(x-2)
+--
+-- 'runFile' writes to 'stdout' and handles some exceptions.
+--
+----------------------------------------------------------------------------
+
+module CSPM.Interpreter.Test.CLI
+(
+   evalTest
+  ,runFile
+)
+
+where
+import Language.CSPM.Frontend
+import qualified Language.CSPM.AST as AST
+
+import CSPM.Interpreter.Eval
+import qualified CSPM.Interpreter.Types as Types
+import CSPM.Interpreter.Types
+  (Value,initialEnvirionment,getLetBindings)
+import CSPM.Interpreter.PrepareAST (prepareAST)
+import CSPM.Interpreter.Hash
+import CSPM.Interpreter.CoreInstances ()
+
+import System.Exit
+import System.CPUTime
+
+import Control.Monad
+import qualified Data.IntMap as IntMap
+import qualified Data.Map as Map
+import Data.Maybe
+
+-- | Load a specification from a file and evaluate an expression in the context.
+-- Print the result to 'stdout' and handle some exceptions.
+runFile :: FilePath -> String -> IO ()
+runFile fileName expr
+  = handleLexError lexErrorHandler
+      $ handleParseError parseErrorHandler
+        $ handleRenameError renameErrorHandler $
+  do
+    val <- evalTest fileName expr
+    putStrLn $ show val
+    exitSuccess
+
+-- | Load a specification from a file and evaluate an expression in the context.
+evalTest :: FilePath -> String -> IO Value
+evalTest fileName expr = liftM fst $ evalEnv fileName expr
+
+{- Todo: clean up the mess below -}
+
+
+evalEnv :: FilePath -> String -> IO (Value,Types.Env)
+evalEnv fileName expr = do
+  srcPlain <- readFile fileName
+{- this is a hack:
+we simply append the expression to be evaluated at the end of the sourcefile
+and parse both together in one go
+todo : fix
+-}
+  let src = srcPlain ++ "\n--patch entrypoint\ntest__entry = " ++expr ++"\n"  
+
+--  putStrLn $ "Reading File " ++ fileName
+  _startTime <- (return $ length src) >> getCPUTime
+  tokenList <- lexInclude src >>= eitherToExc
+  _time_have_tokens <- getCPUTime
+
+  ast <- eitherToExc $ parse fileName tokenList
+  _time_have_ast <- getCPUTime
+
+  renaming <- eitherToExc $ getRenaming ast
+  let astNew = prepareAST $ applyRenaming renaming ast
+  case astNew of Labeled {} -> return () -- force astNew ?
+  _time_have_renaming <- getCPUTime
+
+--  putStrLn $ "Parsing OK"
+--  putStrLn $ "lextime : " ++ showTime (time_have_tokens - startTime)
+--  putStrLn $ "parsetime : " ++ showTime(time_have_ast - time_have_tokens)
+--  putStrLn $ "renamingtime : " ++ showTime (time_have_renaming - time_have_ast)
+--  putStrLn $ "total : " ++ showTime(time_have_ast - startTime)
+
+  time_start_execute <- getCPUTime
+  initEnv <- initialEnvirionment
+  let
+    entry :: AST.UniqueIdent
+    entry = fromJust $ Map.lookup "test__entry" $ (\(x,_,_) -> x) renaming
+    astP :: LModule
+    astP = compilePattern astNew
+    env = processDeclList (hs "TopLevelEnvirionment") initEnv
+          $ AST.moduleDecls $ unLabel astP
+    val :: Value
+    val = (IntMap.!) (getLetBindings env) $ AST.uniqueIdentId entry
+--  forM_ (IntMap.elems $ getLetBindings env)  $ \p -> putStrLn $ show p
+  putStrLn $ show val
+  time_finish_execute <- getCPUTime
+  putStrLn $ "execution time : " ++ showTime(time_finish_execute - time_start_execute)
+  return (val,env)
+
+showTime :: Integer -> String
+showTime a = show (div a 1000000000) ++ "ms"
+
+parseErrorHandler :: ParseError -> IO ()
+parseErrorHandler err = do
+  putStrLn "ParseError : "
+  putStrLn $ show err
+  exitFailure
+
+lexErrorHandler :: LexError -> IO ()
+lexErrorHandler err = do
+  putStrLn "LexError : "
+  putStrLn $ show err
+  exitFailure
+
+renameErrorHandler :: RenameError -> IO ()
+renameErrorHandler err = do 
+  putStrLn "RenamingError : "
+  putStrLn $ show err
+  exitFailure
diff --git a/src/CSPM/Interpreter/Types.hs b/src/CSPM/Interpreter/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/CSPM/Interpreter/Types.hs
@@ -0,0 +1,304 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.Types
+-- Copyright   :  (c) Fontaine 2008
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- Definitions of most of the types used in the interpreter.
+-- Also Instance declarations for the core language type families.
+-- 'INT' is the type (index) for the CSPM interpreter.
+--
+----------------------------------------------------------------------------
+{-# LANGUAGE TypeSynonymInstances,TypeFamilies #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE StandaloneDeriving #-}
+
+module CSPM.Interpreter.Types
+where
+
+import qualified Language.CSPM.AST as AST
+import Language.CSPM.SrcLoc (SrcLoc)
+import qualified CSPM.CoreLanguage as Core
+
+import CSPM.Interpreter.SSet (SSet)
+
+import Data.Digest.Pure.HashMD5 as HashMD5
+import Data.IntMap as IntMap (IntMap,empty)
+import qualified Control.Monad.Reader as Reader
+import Control.Monad.Reader
+import Control.Exception
+import qualified Data.List as List
+import Data.Typeable
+import Data.Set (Set)
+import Data.Map (Map)
+import Data.Ord
+import Data.Function
+
+data INT
+
+type Event = [Field]
+type instance Core.Event INT = Event
+type instance Core.EventSet INT = ClosureSet
+type instance Core.RenamingRelation INT = RenamingRelation
+type instance Core.ClosureState INT = ClosureState
+type Field = Value
+type instance Core.Field INT = Field
+type FieldSet = SSet Field
+type instance Core.FieldSet INT = FieldSet
+type Process = Core.Process INT
+type instance Core.ExtProcess INT = SwitchedOffProc
+type Digest = HashMD5.MD5Digest
+type instance Core.Prefix INT = PrefixState
+-- type instance CoreField.PrefixState INT = PrefixState
+type instance Core.PrefixState INT = GenericBufferPrefix
+
+deriving instance Eq Process
+deriving instance Ord Process
+deriving instance Show Process
+
+data ClosureSet
+  = ClosureSet {
+    closureSetTrie :: PrefixTrie
+   ,closureSetDigest :: Digest
+   } deriving (Show)
+
+instance Ord ClosureSet where
+  compare = comparing closureSetDigest
+instance Eq ClosureSet where
+  (==) = on (==) closureSetDigest
+
+
+data RenamingRelation
+  = RenamingRelation {
+    renamingPairs :: Set (Event,Event)
+   ,renamingDomain :: Set Event
+   ,renamingRange :: Set Event
+   ,renamingDigest :: Digest
+   } deriving (Show)
+
+instance Ord RenamingRelation where
+  compare = comparing renamingDigest
+instance Eq RenamingRelation where
+  (==) = on (==) renamingDigest
+
+data ClosureState
+  = ClosureStateNormal {
+     origClosureSet :: ClosureSet
+    ,currentPrefixTrie :: PrefixTrie
+  }
+  | ClosureStateFailed { origClosureSet :: ClosureSet }
+  | ClosureStateSucc {
+     origClosureSet :: ClosureSet
+    ,currentPrefixTrie :: PrefixTrie
+  }
+  deriving (Show,Eq,Ord)
+
+data SwitchedOffProc
+  = SwitchedOffProc {
+    switchedOffDigest :: Digest
+   ,switchedOffExpr :: AST.LExp
+   ,switchedOffProcess :: Process
+   }
+
+instance Ord SwitchedOffProc where
+  compare = comparing switchedOffDigest
+instance Eq SwitchedOffProc where
+  (==) = on (==) switchedOffDigest
+instance Show SwitchedOffProc where
+  show f = "(SwitchedOff " ++ (show $ switchedOffDigest f) ++ ")"
+
+data PrefixState = PrefixState {
+   prefixEnv :: Env
+  ,prefixFields :: [AST.LCommField]
+  ,prefixBody :: AST.LExp
+  ,prefixRHS :: Process
+  ,prefixDigest :: Digest
+  ,prefixPatternFailed :: Bool
+--  ,prefixLastInputBuffer :: [Value]
+--  ,prefixOutputBuffer :: [Value]
+  }
+
+instance Ord PrefixState where
+  compare = comparing prefixDigest
+instance Eq PrefixState where
+  a == b = prefixDigest a == prefixDigest b
+instance Show PrefixState where
+  show f = "(PrefixState " ++ (show $ prefixDigest f) ++ ")"
+
+data GenericBufferPrefix
+  = GBOut [Value] PrefixState
+  | GBInput PrefixState
+  | GBInputGuard FieldSet PrefixState
+  | GBInputGeneric [Value] PrefixState
+  | GBFinished PrefixState
+  deriving (Show,Eq,Ord)
+
+type Bindings = IntMap Value
+data Env = Env {
+   argBindings :: Bindings -- todo : merge argBindings and letBindings
+  ,letBindings :: Bindings 
+  ,letDigests :: IntMap Digest
+  }
+
+initialEnvirionment :: IO Env
+initialEnvirionment = return emptyEnvirionment
+
+emptyEnvirionment :: Env
+emptyEnvirionment = Env {
+   argBindings = IntMap.empty
+  ,letBindings = IntMap.empty
+  ,letDigests = IntMap.empty
+  }
+
+{- 
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+this is worng !
+we must not omit let bound identifier !!
+the fix is to statically compute, which parts of the envirionment are
+relevant and compare exactly those
+-}
+
+{-
+instance Ord Env where
+  compare a b = compare (argBindings a) (argBindings b)
+instance Eq Env where
+  (==) a b = argBindings a == argBindings b
+-}
+-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
+newtype EM x = EM { unEM ::Reader Env x }
+  deriving (Monad,MonadReader Env)
+
+getArgBindings :: Env -> Bindings
+getArgBindings = argBindings
+
+getLetBindings :: Env -> Bindings
+getLetBindings = letBindings
+
+setArgBindings :: Env -> Bindings -> Env
+setArgBindings env b = env {argBindings=b}
+
+setLetBindings :: Env -> Bindings -> Env
+setLetBindings env b = env {letBindings=b}
+
+getEnv :: EM Env
+getEnv = Reader.ask
+
+class Monad m => Eval m where
+  evalM :: AST.LExp -> m Value
+
+data Value =
+   VInt  Integer
+ | VBool Bool
+ | VList [Value]
+ | VTuple [Value]
+ | VDotTuple [Value]
+ | VSet (Set Value)
+ | VClosure ClosureSet
+ | VFun FunClosure
+ | VProcess Process
+ | VChannel Channel
+ | VUnit
+-- cspm-special features
+ | VAllInts
+ | VAllSequents (Set Value)
+--  | VAllEvents
+ | VConstructor Constructor
+ | VDataType [Constructor]
+ | VNameType [FieldSet]
+ | VPartialApplied FunClosure [Value]
+ deriving (Ord,Eq)
+
+data FunClosure = FunClosure {
+   getFunCases :: [AST.FunCase]
+  ,getFunEnv :: Env
+  ,getFunArgNum :: Int
+  ,getFunId  :: Digest
+  }
+
+instance Eq FunClosure where
+  a == b = getFunId a == getFunId b
+instance Ord FunClosure where
+  compare a b = compare (getFunId a) (getFunId b)
+instance Show FunClosure where
+  show f = "(FunClosure " ++ (show $ getFunId f) ++ ")"
+
+data Constructor = Constructor {
+   constrId ::Int
+  ,constrName :: String
+  ,constrFields :: [FieldSet]
+  } deriving (Show,Eq,Ord)
+
+data Channel = Channel
+  {
+    chanId :: Int
+   ,chanName :: String
+   ,chanLen :: Int
+   ,chanFields :: [FieldSet] -- these are the fields proper excluding the channel itself
+  } deriving (Show,Eq,Ord)
+
+isChannelField :: Field -> Bool
+isChannelField (VChannel {} ) = True
+isChannelField _ = False
+
+getChannel :: Field -> Channel
+getChannel (VChannel x) = x
+getChannel _ = error "Eval.hs : getChannel on non-Channel"
+
+instance Show Value where
+  show v = case v of
+    VInt  i -> "(VInt " ++ show i  ++ ")"
+    VBool b -> "(VBool " ++ show b  ++ ")"
+    VList l -> "(VList " ++ show l  ++ ")"
+    VTuple l -> "(VTuple " ++ show l  ++ ")"
+    VDotTuple l -> "(VDotTuple " ++ show l  ++ ")"
+    VSet s -> "(VSet " ++ show s ++ ")"
+    VClosure s -> "(VClosure " ++ show s ++ ")"
+    VProcess p -> "(VProcess " ++ show p ++ ")"
+    VChannel c -> "(VChannel " ++ show c ++ ")"
+    VFun _ -> "(VFun Functionclosure)"
+    VUnit -> "VUnit"
+    VAllInts -> "VAllInts"
+    VAllSequents _  -> "VAllSequents "
+--  VAllEvents -> "VAllEvents"
+    VConstructor c -> "(VConstructor " ++ (show $ constrName c) ++ ")"
+    VDataType l
+      -> "(VDataType " ++ (concat $ List.intersperse " " $ map (show . constrName) l ) ++")"
+    VNameType _ -> "VNameType"
+    VPartialApplied {} -> "(Partially applyed function)" 
+
+data PrefixTrie
+  = PTNil
+  | PTAny PrefixTrie
+  | PTMap (Map Value PrefixTrie)
+  | PTRec (Set Value) PrefixTrie  --rectangular closuresets (e.g. channels)
+--  | PTInt PrefixTrie -- any Int field : todo generarlise this
+  | PTSingle Value PrefixTrie
+  | PTClosure PrefixTrie
+  deriving (Show,Eq,Ord)
+
+data InterpreterError
+  = ScriptError {errMsg :: String, errLoc :: Maybe SrcLoc, errVal :: Maybe Value}
+  | FeatureNotImplemented {errMsg :: String, errLoc :: Maybe SrcLoc }
+  | TypingError {errMsg :: String, errLoc :: Maybe SrcLoc, errVal :: Maybe Value}
+  | InternalError {errMsg :: String, errLoc :: Maybe SrcLoc, errVal :: Maybe Value }
+  | PatternMatchError {errMsg :: String ,errLoc :: Maybe SrcLoc}
+  deriving (Show,Typeable)
+
+throwScriptError :: String -> Maybe SrcLoc -> Maybe Value -> a
+throwScriptError m l v = throw $ ScriptError m l v
+throwFeatureNotImplemented :: String -> Maybe SrcLoc -> a
+throwFeatureNotImplemented m l = throw $ FeatureNotImplemented m l
+throwTypingError :: String -> Maybe SrcLoc -> Maybe Value -> a
+throwTypingError m l v = throw $ TypingError m l v
+throwInternalError :: String -> Maybe SrcLoc -> Maybe Value -> a
+throwInternalError m l v = throw $ InternalError m l v
+throwPatternMatchError :: String -> Maybe SrcLoc -> a
+throwPatternMatchError m l = throw $ PatternMatchError m l
+
+instance Exception InterpreterError
diff --git a/src/Data/Digest/Pure/HashMD5.hs b/src/Data/Digest/Pure/HashMD5.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Digest/Pure/HashMD5.hs
@@ -0,0 +1,99 @@
+{-# LANGUAGE BangPatterns #-}
+-----------------------------------------------------------------------------
+--
+-- Module      : Data.Digest.Pure.HashMD5
+-- License     : BSD3
+-- Stability   : experimental
+-- Portability : portable, requires bang patterns and ByteString
+-- Tested with : GHC-6.12.2
+--
+-- Use the MD5-rounds to compute hash-values for data-structures.
+-----------------------------------------------------------------------------
+
+module Data.Digest.Pure.HashMD5
+	(
+          MD5Digest
+        , Hash(..)
+        , md5Init
+        , mixRaw
+        , mix
+        , mix3
+        , mix4
+        , mix5
+        , mixInt
+        , foldHash
+        ) where
+
+import Data.Digest.Pure.MD5
+import Data.Char
+
+{-# INLINE mix5 #-}
+mix5 a (MD5Digest w0 w1 w2 w3) (MD5Digest w4 w5 w6 w7)
+  (MD5Digest w8 w9 w10 w11) (MD5Digest w12 w13 w14 w15)
+  = mixRaw a w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 w13 w14 w15
+
+{-# INLINE mix4 #-}
+mix4 :: MD5Digest -> MD5Digest -> MD5Digest -> MD5Digest -> MD5Digest
+mix4 a b c d = mix5 md5Init a b c d
+
+{-# INLINE mix3 #-}
+mix3 :: MD5Digest -> MD5Digest -> MD5Digest -> MD5Digest
+mix3 a b c = mix5 md5Init md5Init a b c
+
+{-# INLINE mix #-}
+mix :: MD5Digest -> MD5Digest -> MD5Digest
+mix a b = mix5 md5Init md5Init md5Init a b
+
+class Hash a where
+  hash :: a -> MD5Digest
+
+-- instance Monoid HashMD5
+instance Hash MD5Digest where
+  hash = id
+ 
+instance Hash Char where
+  hash c = mixRaw md5Init (fromIntegral $ ord c) 234124 23415 3452 0 0 0 0
+              0 0 0 0 0 0 0 0
+
+instance (Hash a, Hash b) => Hash (a,b) where
+  hash (a, b) = mix (hash a) (hash b)
+
+instance (Hash a, Hash b, Hash c) => Hash (a, b, c) where
+  hash (a, b, c) = mix3 (hash a) (hash b) (hash c)
+
+instance (Hash a, Hash b, Hash c, Hash d) => Hash (a, b, c, d) where
+  hash (a, b, c, d) = mix4 (hash a) (hash b) (hash c) (hash d)
+
+
+hashString :: String -> MD5Digest
+hashString
+  = foldHash $ mixRaw md5Init 234 42 21 23 0 0 0 0 0 0 0 0 0 0 0 0
+
+instance Hash a => Hash [a] where
+  hash = foldHash (hashString "Prelude.List standart")
+
+foldHash :: Hash a => MD5Digest -> [a] -> MD5Digest
+foldHash !acc [] = acc
+foldHash !acc [a] = mix acc (hash a)
+foldHash !acc [a,b] = mix3 acc (hash a) (hash b)
+foldHash !acc [a,b,c] = mix4 acc (hash a) (hash b) (hash c)
+foldHash !acc (a:b:c:d:rest) = foldHash (mix5 acc (hash a) (hash b) (hash c) (hash d)) rest
+
+{-# inline mixInt #-}
+mixInt :: MD5Digest -> Int -> MD5Digest
+mixInt h i = mixRaw h (fromIntegral i) 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+{-
+foldInt :: Hash64 -> [Int] -> Hash64
+foldInt !acc [] = acc
+foldInt !acc [a] = mixRaw acc (fromIntegral a) 0 0 0
+foldInt !acc [a,b] = mixRaw acc (fromIntegral a) (fromIntegral b) 0 0
+foldInt !acc [a,b,c]
+  = mixRaw acc (fromIntegral a) (fromIntegral b) (fromIntegral c) 0
+foldInt !acc [a,b,c,d]
+  = mixRaw acc (fromIntegral a) (fromIntegral b) (fromIntegral c) (fromIntegral d)
+foldInt !acc (a:b:c:d:rest)
+  = foldInt
+      (mixRaw acc (fromIntegral a) (fromIntegral b) (fromIntegral c) (fromIntegral d))
+      rest
+-}
diff --git a/src/Data/Digest/Pure/MD5.hs b/src/Data/Digest/Pure/MD5.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Digest/Pure/MD5.hs
@@ -0,0 +1,178 @@
+{-# LANGUAGE BangPatterns #-}
+-----------------------------------------------------------------------------
+-- Module      : Data.Digest.Pure.MD5
+-- License     : BSD3
+--
+-- Stability   : experimental
+-- Portability : portable, requires bang patterns and ByteString
+-- Tested with : GHC-6.8.1
+--
+-- This is taken from the pureMD5 package but stripped down to remove some dependencies.
+-- Ideally one would extend pureMD5 or move this to a seperate package.
+-- Original Author is  : Thomas.DuBuisson@gmail.com
+--
+-----------------------------------------------------------------------------
+
+module Data.Digest.Pure.MD5
+	(
+          MD5Digest (..)
+        , mixRaw
+        , md5Init
+        ) where
+
+import Data.List
+import Data.Word
+import Data.Bits
+import Numeric
+
+data MD5Digest = MD5Digest !Word32 !Word32 !Word32 !Word32
+    deriving (Ord, Eq)
+
+md5Init :: MD5Digest
+md5Init = MD5Digest h0 h1 h2 h3
+  where
+    h0 = 0x67452301
+    h1 = 0xEFCDAB89
+    h2 = 0x98BADCFE
+    h3 = 0x10325476
+
+{-# INLINE applyMD5RoundsRaw #-}
+applyMD5RoundsRaw ::
+       MD5Digest
+    -> Word32 -> Word32 -> Word32 -> Word32
+    -> Word32 -> Word32 -> Word32 -> Word32
+    -> Word32 -> Word32 -> Word32 -> Word32
+    -> Word32 -> Word32 -> Word32 -> Word32
+    -> MD5Digest
+applyMD5RoundsRaw
+    (MD5Digest a b c d)
+    !w0 !w1 !w2 !w3 
+    !w4 !w5 !w6 !w7
+    !w8 !w9 !w10 !w11 
+    !w12 !w13 !w14 !w15
+    =  {-# SCC "applyMD5RoundsRaw" #-}
+        let -- Round 1
+            !r0  = ff  a  b  c  d   w0  7  3614090360
+            !r1  = ff  d r0  b  c   w1  12 3905402710
+            !r2  = ff  c r1 r0  b   w2  17 606105819
+            !r3  = ff  b r2 r1 r0   w3  22 3250441966
+            !r4  = ff r0 r3 r2 r1   w4  7  4118548399
+            !r5  = ff r1 r4 r3 r2   w5  12 1200080426
+            !r6  = ff r2 r5 r4 r3   w6  17 2821735955
+            !r7  = ff r3 r6 r5 r4   w7  22 4249261313
+            !r8  = ff r4 r7 r6 r5   w8  7  1770035416
+            !r9  = ff r5 r8 r7 r6   w9  12 2336552879
+            !r10 = ff r6 r9 r8 r7  w10 17 4294925233
+            !r11 = ff r7 r10 r9 r8 w11 22 2304563134
+            !r12 = ff r8 r11 r10 r9 w12 7  1804603682
+            !r13 = ff r9 r12 r11 r10 w13 12 4254626195
+            !r14 = ff r10 r13 r12 r11 w14 17 2792965006
+            !r15 = ff r11 r14 r13 r12 w15 22 1236535329
+            -- Round 2
+            !r16 = gg r12 r15 r14 r13 w1  5  4129170786
+            !r17 = gg r13 r16 r15 r14 w6  9  3225465664
+            !r18 = gg r14 r17 r16 r15 w11 14 643717713
+            !r19 = gg r15 r18 r17 r16 w0  20 3921069994
+            !r20 = gg r16 r19 r18 r17 w5  5  3593408605
+            !r21 = gg r17 r20 r19 r18 w10 9  38016083
+            !r22 = gg r18 r21 r20 r19 w15 14 3634488961
+            !r23 = gg r19 r22 r21 r20 w4  20 3889429448
+            !r24 = gg r20 r23 r22 r21 w9  5  568446438
+            !r25 = gg r21 r24 r23 r22 w14 9  3275163606
+            !r26 = gg r22 r25 r24 r23 w3  14 4107603335
+            !r27 = gg r23 r26 r25 r24 w8  20 1163531501
+            !r28 = gg r24 r27 r26 r25 w13 5  2850285829
+            !r29 = gg r25 r28 r27 r26 w2  9  4243563512
+            !r30 = gg r26 r29 r28 r27 w7  14 1735328473
+            !r31 = gg r27 r30 r29 r28 w12 20 2368359562
+            -- Round 3
+            !r32 = hh r28 r31 r30 r29 w5  4  4294588738
+            !r33 = hh r29 r32 r31 r30 w8  11 2272392833
+            !r34 = hh r30 r33 r32 r31 w11 16 1839030562
+            !r35 = hh r31 r34 r33 r32 w14 23 4259657740
+            !r36 = hh r32 r35 r34 r33 w1  4  2763975236
+            !r37 = hh r33 r36 r35 r34 w4  11 1272893353
+            !r38 = hh r34 r37 r36 r35 w7  16 4139469664
+            !r39 = hh r35 r38 r37 r36 w10 23 3200236656
+            !r40 = hh r36 r39 r38 r37 w13 4  681279174
+            !r41 = hh r37 r40 r39 r38 w0  11 3936430074
+            !r42 = hh r38 r41 r40 r39 w3  16 3572445317
+            !r43 = hh r39 r42 r41 r40 w6  23 76029189
+            !r44 = hh r40 r43 r42 r41 w9  4  3654602809
+            !r45 = hh r41 r44 r43 r42 w12 11 3873151461
+            !r46 = hh r42 r45 r44 r43 w15 16 530742520
+            !r47 = hh r43 r46 r45 r44 w2  23 3299628645
+            -- Round 4
+            !r48 = ii r44 r47 r46 r45 w0  6  4096336452
+            !r49 = ii r45 r48 r47 r46 w7  10 1126891415
+            !r50 = ii r46 r49 r48 r47 w14 15 2878612391
+            !r51 = ii r47 r50 r49 r48 w5  21 4237533241
+            !r52 = ii r48 r51 r50 r49 w12 6  1700485571
+            !r53 = ii r49 r52 r51 r50 w3  10 2399980690
+            !r54 = ii r50 r53 r52 r51 w10 15 4293915773
+            !r55 = ii r51 r54 r53 r52 w1  21 2240044497
+            !r56 = ii r52 r55 r54 r53 w8  6  1873313359
+            !r57 = ii r53 r56 r55 r54 w15 10 4264355552
+            !r58 = ii r54 r57 r56 r55 w6  15 2734768916
+            !r59 = ii r55 r58 r57 r56 w13 21 1309151649
+            !r60 = ii r56 r59 r58 r57 w4  6  4149444226
+            !r61 = ii r57 r60 r59 r58 w11 10 3174756917
+            !r62 = ii r58 r61 r60 r59 w2  15 718787259
+            !r63 = ii r59 r62 r61 r60 w9  21 3951481745
+        in MD5Digest r60 r63 r62 r61
+        where
+        f !x !y !z = (x .&. y) .|. ((complement x) .&. z)
+        {-# INLINE f #-}
+        g !x !y !z = (x .&. z) .|. (y .&. (complement z))
+        {-# INLINE g #-}
+        h !x !y !z = (x `xor` y `xor` z)
+        {-# INLINE h #-}
+        i !x !y !z = y `xor` (x .|. (complement z))
+        {-# INLINE i #-}
+        ff a b c d !x s ac = {-# SCC "ff" #-}
+                let !a' = f b c d + x + ac + a
+                    !a'' = rotateL a' s
+                in a'' + b
+        {-# INLINE ff #-}
+        gg a b c d !x s ac = {-# SCC "gg" #-}
+                let !a' = g b c d + x + ac + a
+                    !a'' = rotateL a' s
+                in a'' + b
+        {-# INLINE gg #-}
+        hh a b c d !x s ac = {-# SCC "hh" #-}
+                let !a' = h b c d + x + ac + a
+                    !a'' = rotateL a' s
+                    in a'' + b
+        {-# INLINE hh #-}
+        ii a b c d  !x s ac = {-# SCC "ii" #-}
+                let !a' = i b c d + x + ac + a
+                    !a'' = rotateL a' s
+                in a'' + b
+        {-# INLINE ii #-}
+
+
+infix 9 .<.
+(.<.) :: Word8 -> Int -> Word32
+(.<.) w i = (fromIntegral w) `shiftL` i
+
+-- | mix one Digest and 16 words by applying the md5-rounds
+mixRaw ::
+       MD5Digest
+    -> Word32 -> Word32 -> Word32 -> Word32
+    -> Word32 -> Word32 -> Word32 -> Word32
+    -> Word32 -> Word32 -> Word32 -> Word32
+    -> Word32 -> Word32 -> Word32 -> Word32
+    -> MD5Digest
+{- mix is the same as applyMD5RoundsRaw, except without INLINE pragma -}
+mixRaw = applyMD5RoundsRaw
+
+----- Some quick and dirty instances follow -----
+
+-- todo: this is not offical
+instance Show MD5Digest where
+  show (MD5Digest a b c d) = "HashMD5_"++ toHex a ++ toHex b ++ toHex c ++ toHex d
+    where
+      toHex :: Integral a => a -> String
+      toHex a = reverse $ take 8 $ hex a where
+      hex x = (digits !! (fromIntegral (x `mod` 16))) : hex ( x `div` 16)
+      digits = "0123456789ABCDEF"
diff --git a/src/Main.hs b/src/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/Main.hs
@@ -0,0 +1,26 @@
+----------------------------------------------------------------------------
+-- |
+-- Module      :  CSPM.Interpreter.Test.Main
+-- Copyright   :  (c) Fontaine 2010
+-- License     :  BSD
+-- 
+-- Maintainer  :  Fontaine@cs.uni-duesseldorf.de
+-- Stability   :  experimental
+-- Portability :  GHC-only
+--
+-- Very rudimentary comand line interface to the interpreter.
+----------------------------------------------------------------------------
+
+module Main
+where
+
+import CSPM.Interpreter.Test.CLI
+import System.Environment (getArgs)
+-- | main-funtion for the command line.
+-- (no help and no nothing)
+main :: IO ()
+main = do
+  l <- getArgs
+  case l of
+    [filePath, expression] -> runFile filePath expression
+    _ -> putStrLn "please start with two arguments: filename + expression"
