diff --git a/A.csv b/A.csv
new file mode 100644
index 0000000000000000000000000000000000000000..3c461496a6088e571d22c5a089870231f3af5346
--- /dev/null
+++ b/A.csv
@@ -0,0 +1,3 @@
+patryk,malinowski
+maram, jones
+jeffrey,sylvester
diff --git a/B.csv b/B.csv
new file mode 100644
index 0000000000000000000000000000000000000000..bf47bb37fc5f31f96d9ef7be71cafe1ea4efb211
--- /dev/null
+++ b/B.csv
@@ -0,0 +1,3 @@
+jian,shi
+andrew,sogokon
+julian,rathke
\ No newline at end of file
diff --git a/Eval.hs b/Eval.hs
index 7f9a370a0949bc451c42545d646b43d407119c1d..7d41beca39e1e589d65c4a4d7c770d3a0d855733 100644
--- a/Eval.hs
+++ b/Eval.hs
@@ -17,13 +17,16 @@ eval env expr = let (eval', evalFull') = (eval env, evalFull env) in case expr o
     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).(\r -> eval' $ FuncCall predicate [] [r])) $ map eval' inputRecords
+                Set $ filter ((==Boolean True).(\r -> eval' $ FuncCall predicate [] [r])) $ map eval' inputRecords
               
             IsEqual -> let (e1:e2:_) = args in -- TODO not sufficent.
-              Boolean (eval' e1 == eval' e2)
+                Boolean (eval' e1 == eval' e2)
 
             RecordIndex -> let (Record recordData:Int index:_) = (map eval' args) in
-              recordData !! index
+                recordData !! index
+
+            XProduct -> debug (show env) $ let ((Set l1): (Set l2):_) = map eval' inputSets in
+                Set $ [ x `concatRecord` y | x <- l1, y <- l2]
 
             --implement later
             --(Map) -> Set $ (map (\r -> FuncCall predicate [] [r]) inputRecords)
@@ -48,4 +51,5 @@ evalControl1 env (Control last (currentExpr:exprs)) = let output = eval env curr
 evalFull = eval
 --evalFull env (Set xs) = Set (map (eval env) xs) -- evaluates expression fully (not just weak head normal form)
 --evalFull _ e = e
---TODO implement properly
\ No newline at end of file
+--TODO implement properly
+concatRecord (Record r1) (Record r2) = Record (r1 ++ r2)
\ No newline at end of file
diff --git a/Interpreter.hs b/Interpreter.hs
index 8eafcddfd0c91ca276492d04636f80acf7c88e5b..97a5a6bb650dfbc8dd0fd1cbf7d652d0a85e5236 100644
--- a/Interpreter.hs
+++ b/Interpreter.hs
@@ -2,6 +2,7 @@ import Types
 import Debug
 import Eval
 import System.IO
+import System.Environment
 import CSV
 import Lexer
 import Parser
@@ -11,7 +12,12 @@ parse :: String -> Program
 parse = parseSource.alexScanTokens
 --outline
 
-main = interpret "sampleprogram.txt"
+main = do
+    args <- getArgs
+    case args of
+        (srcname:_) -> interpret srcname
+        _ -> interpret "q1.txt"
+    
 
 interpret :: FilePath -> IO () -- the main function, takes in file name, prints out result
 interpret sourceFName = do
diff --git a/Lexer.x b/Lexer.x
index 8f37a6a8f5c0202cba4d7cdd140b964920805d73..407bb44f6806a349c91aee2b3737cb0d3e938492 100644
--- a/Lexer.x
+++ b/Lexer.x
@@ -26,8 +26,9 @@ false                           {\s -> TokenFalse }
 \)                             {\s -> TokenRightBracket }
 \;                             {\s -> TokenSemiCol }
 \\                            {\s -> TokenLambda }
---\,                             {\s -> TokenComma }
+\,                             {\s -> TokenComma }
 \.                             {\s -> TokenFullStop }
+x                                {\s -> TokenXProduct }
 $lower [$lower $digit \_ \']*   {\s -> TokenVarName s }
 $upper[$alpha]*                 {\s -> TokenSetName s }
 $digit+                         {\s -> TokenNat (read s) }
@@ -56,6 +57,7 @@ data Token =
     TokenComma          |
     TokenFullStop       |
     TokenInSet          |
+    TokenXProduct       |
     TokenOutSet
     deriving  (Eq, Show)
 }
diff --git a/Parser.y b/Parser.y
index 8be3046a4cf79c55f8acf8a3bd313b7f1ca9e2b2..8875f8058af2b8aca899c58bc71f664724f83d61 100644
--- a/Parser.y
+++ b/Parser.y
@@ -29,6 +29,7 @@ import Types
 	'\\'            { TokenLambda }
 	','             { TokenComma  }
 	'.'             { TokenFullStop }
+	x				{ TokenXProduct }
 
 %right "->"
 %left "/=" "==" ';'
@@ -49,6 +50,8 @@ SetFuncCalls : SetFuncCall    {[$1]}
 SetFuncCall : filter '['SetName']' '('Func')' {FuncCall (PredefFunc Filter) [Var $3] [$6]}
 	| filter '('Func')' {FuncCall (PredefFunc Filter) [] [$3]}
 
+	| SetName x SetName	{FuncCall (PredefFunc XProduct) (map Var [$1, $3]) []}
+
 Func : '\\' '(' VarNames ')' "->" Expr {FuncDef [] $3 $6}