diff --git a/Debug.hs b/Debug.hs
new file mode 100644
index 0000000000000000000000000000000000000000..6c66e0c069b2ce8c7fae62ccb78ef2ff8dc1ef94
--- /dev/null
+++ b/Debug.hs
@@ -0,0 +1,2 @@
+module Debug where
+notImplemented = error "Not implemented yet"
diff --git a/Eval.hs b/Eval.hs
new file mode 100644
index 0000000000000000000000000000000000000000..712aeffed0d73b9972a08678c1be2b06dd4e8293
--- /dev/null
+++ b/Eval.hs
@@ -0,0 +1,27 @@
+eval :: ResultEnvironment -> Expr -> Expr --only focus on one expression
+type Environment = ResultEnvironment
+findVar :: Environment -> SymbolName -> Expr
+findVar = notImplemented
+addVar :: Environment -> SymbolName -> Expr -> Environment
+
+eval env expr = let eval' = eval env in case expr of -- evaluates expression to weak-head normal form (i.e. top level data structure is not a FuncCall)
+    FuncCall func inputSets args -> case func of
+        (PredefFunc f) -> case f of
+            (Filter) -> let (Set inputRecords,predicate) = (eval' $ head inputSets, eval' $ head args) in
+                Set $ filter ((==Boolean True).eval')(map (\r -> FuncCall predicate [] [r]) inputRecords) -- result is weak-head normal form
+                --Set $ map (eval env) (map (\r -> FuncCall predicate [] [r]) inputRecords) # don't evaluate last step
+
+            (IsEqual) -> let (e1:e2:_) = args in
+                Boolean (eval' e1 == eval' e2)
+
+            (RecordIndex) -> let (Record recordData, Int index) = (eval' $ args !! 0, eval' $ args !! 1) in
+                recordData !! index
+
+            --implement later
+            --(Map) -> Set $ (map (\r -> FuncCall predicate [] [r]) inputRecords)
+        (FuncDef setParams argParams body) -> eval new_env body
+            where
+                newEnv = foldl (\env entry@(name, expr) -> addVar env name expr) env --adds entries to environment
+                -- TODO FIx
+    (Var name) -> findVar env name
+    _ -> expr
diff --git a/Interpreter.hs b/Interpreter.hs
new file mode 100644
index 0000000000000000000000000000000000000000..2fe210e256f73daac1fd68b70bd35e4c8351a44c
--- /dev/null
+++ b/Interpreter.hs
@@ -0,0 +1,31 @@
+import Types
+import Debug
+
+type Control = (ResultEnvironment, [Expr])
+type ResultEnvironment = [(SymbolName, Expr)] -- (result of last calculation, other bindings e.g. let statements)
+
+prepare :: Program -> IO Control -- takes in the AST for the program, reads the csv files and prepares the environment based on the CSV files
+prepare (inputSets,instructions) = zipM (environment, return instructions)
+    where environment = fmap (zip inputSets) $ loadInputFiles inputSets
+
+---eval :: Control -> Expr -- fully evaluates the program, returning a set
+zipM (a,b) = do
+    a' <- a
+    b' <- b
+    return (a',b')
+
+--pairmap f s = (s, fs)
+
+--------------------------------------------
+
+programStep :: Control -> Control -- updates environment and list
+programStep = notImplemented
+
+
+--------------------------------------------
+
+loadInputFiles :: [String] -> IO [[String]]
+loadInputFiles = mapM readCSV
+
+readCSV :: FilePath -> IO [[String]]
+readCSV _ = error ""
\ No newline at end of file
diff --git a/ReadCSV.hs b/ReadCSV.hs
new file mode 100644
index 0000000000000000000000000000000000000000..53231accd75e40cdad1b0ad94a0ca3b9b46485c4
--- /dev/null
+++ b/ReadCSV.hs
@@ -0,0 +1,20 @@
+module ReadCSV where
+
+import System.IO
+
+readCSV :: FilePath -> IO [[String]]
+readCSV fname = do
+    str <- readFile fname
+    return $ readCSVString str
+
+readCSVString :: String -> [[String]]
+readCSVString whole = [splitElem ',' line | line <- splitElem '\n' whole]
+    
+splitElem :: Eq a => a -> [a] -> [[a]]
+splitElem elem = split (/=elem)
+
+split :: (a -> Bool) -> [a] -> [[a]]
+split p l = case span p l of
+        ([], _) -> []
+        (match, []) -> [match]
+        (match, _:rem') -> match:split p rem'
\ No newline at end of file
diff --git a/Types.hs b/Types.hs
index 85b17489ae3e6625ca2001a024c70e464fff58c6..54db017b2fc199284f2878a17a07c3e6d2885930 100644
--- a/Types.hs
+++ b/Types.hs
@@ -3,22 +3,26 @@ type Program = (InputSymbols,Output)
 
 type SymbolName = String
 type InputSymbols = [String] -- .in section
-type Output = [OutputLine] -- .out section
-
-data OutputLine = Let SymbolName Expr | Expr -- Expr always a function call for a set function, but not enforced by AST.
+--type Output = [OutputLine] -- .out section
 
+--data OutputLine = Let SymbolName Expr | Expr -- Expr always a function call for a set function, but not enforced by AST.
+type Output = [Expr]
 data PredefFunc = XProduct | XXProduct | IsEqual | IsNotEqual | Add --operators
     | Map | Filter
     | RecordIndex -- [] operator
     | IsEmpty | NotEmpty -- string functions
+    deriving (Show, Eq)
 
 
 --n.b. these definitions do not enforce type checking! The use of any function or operator will be associated with a FuncCall.
 --Therefore, it is possible to have ASTs with ridiculous things where e.g. a XX product is applied to and int and a String, or a function call has an Int as a function!
 --These issues will be checked via the type checker after the AST has been built.
 
+-- filter [A] (\(r) -> r[1] == "hello")
+-- FuncCall (PredefFunc Filter) [Var "A"] [FuncDef [] ["r"] [(FuncCall (PredefFunc IsEqual) [] (r[1]) ("hello"))]]
 data Expr = FuncCall {func::Expr, inputSets::[Expr], args::[Expr]} -- args: function to call, input sets, extra argument. Applicable for all kinds of functions: the set functions e.g. filter, map or simple functions or even the operators e.g. ==, /= ! We don't define separate expr for each operator
-    | FuncDef {name::SymbolName, inputSetNames::[SymbolName], argsNames::[SymbolName], body::Expr} -- function definition
+    -- | FuncDef {name::SymbolName, inputSetNames::[SymbolName], argsNames::[SymbolName], body::Expr} -- function definition
+    | FuncDef {inputSetNames::[SymbolName], argsNames::[SymbolName], body::Expr} -- function definition
     | If Expr Expr Expr
     | Set [Expr]
     | Tuple [Expr]
@@ -28,5 +32,6 @@ data Expr = FuncCall {func::Expr, inputSets::[Expr], args::[Expr]} -- args: func
     | Int Int
     | String String
     | Boolean Bool
-
+    deriving (Show, Eq)
+    
 data Parameter = NamedParam SymbolName | TupleMatch [SymbolName]
\ No newline at end of file