Commits

Xilexio committed dc90941

Refactorization OIdent -> String in map keys and added line numbers to errors

  • Participants
  • Parent commits 6d0b930

Comments (0)

Files changed (11)

+*.o
+*.hi
+Xilocaml
+Grammar/*
+doc/Xilocaml.aux
+doc/Xilocaml.log
+doc/Xilocaml.toc
+doc/Xilocaml.out
+doc/Xilocaml.pdf
 import qualified Data.Map as Map
 import AbsXilocaml
 
+type Ident = String
 
-localDeclIdent :: LocDecl -> OIdent
-localDeclIdent (LocalVarDecl ident _) = ident
-localDeclIdent (LocalVarDeclExplType ident _ _) = ident
-localDeclIdent (LocalFunDecl ident _ _) = ident
-localDeclIdent (LocalFunDeclExplType ident _ _ _) = ident
 
-
-identName :: OIdent -> String
-identName (OIdent name) = name
+localDeclIdent :: LocDecl -> Ident
+localDeclIdent (LocalVarDecl (OIdent (_, ident)) _) = ident
+localDeclIdent (LocalVarDeclExplType (OIdent (_, ident)) _ _) = ident
+localDeclIdent (LocalFunDecl (OIdent (_, ident)) _ _) = ident
+localDeclIdent (LocalFunDeclExplType (OIdent (_, ident)) _ _ _) = ident
 
 
 comparator :: (Eq a, Ord a) => OCmp -> a -> a -> Bool

File Interpreter.hs

 import RunEnvironment
 import PrettyShow
 import Common
+import Position
 
 
 -- Interprets program and returns result of computation.
 returnValue :: Value -> EnvRun Value
 returnValue = lift . Ok
 
-runtimeError :: PrettyShowable a => String -> a -> EnvRun Value
-runtimeError s x = lift $ Bad $ "Runtime error: " ++ s ++ " in " ++ (prettyShow x) ++ "."
+runtimeError :: String -> Exp -> EnvRun Value
+runtimeError s x = lift $ Bad $ "Runtime error: " ++ s ++ " in " ++ (prettyShow $ position x) ++ " in "  ++ (prettyShow x) ++ "."
 
 
 transProgram :: Program -> EnvRun Value
 		argVal <- transExp arg
 		apply expVal argVal
 
-	EInt n -> returnValue $ VInt n
+	EInt str -> returnValue $ VInt $ transOInteger str
 
 	EFloat str -> returnValue $ VFloat $ transOFloat str
 
-	ETrue -> returnValue $ VBool True
-
-	EFalse -> returnValue $ VBool False
+	EBool str -> returnValue $ VBool $ transOBool str
 
 	EList elems -> do
 		let content (ListElement x) = x
 		values <- transExps $ map content elems
 		returnValue $ VList values
 
-	EVar ident -> lookupEnv ident
+	EVar (OIdent (_, ident)) -> lookupEnv ident
 
 	EExplType exp _ -> transExp exp
 
 	return $ v:vs
 
 
+transOInteger :: OInteger -> Integer
+transOInteger (OInteger (_, str)) = (read str)::Integer
+
+
+transOBool :: OBool -> Bool
+transOBool (OBool (_, str)) = case str of
+	"true" -> True
+	"false" -> False
+	_ -> error "Internal error: string should be equal to true or false."
+
+
 transOFloat :: OFloat -> Double
-transOFloat (OFloat str) = let
+transOFloat (OFloat (_, str)) = let
 	exponentDelimiter = findIndex (\x -> x == 'e' || x == 'E') str
 	(fractionStr, exponentStr) = case exponentDelimiter of
 		Nothing -> (str, "")
 	returnValue $ VFun env argIdents exp
 
 
-argIdent :: Argument -> OIdent
-argIdent (FunArg ident) = ident
-argIdent (FunArgExplType ident _) = ident
+argIdent :: Argument -> Ident
+argIdent (FunArg (OIdent (_, ident))) = ident
+argIdent (FunArgExplType (OIdent (_, ident)) _) = ident
 
 
 apply :: Value -> Value -> EnvRun Value
+module Position where
+import AbsXilocaml
+
+
+data Position = At Int Int | Somewhere deriving (Eq, Ord, Show)
+
+
+class Positionable t where
+	position :: t -> Position
+
+instance Positionable Exp where
+	position exp = case exp of
+		ELetIn loc exp1 -> min (position loc) (position exp1)
+		ELetRecIn loc exp1 -> min (position loc) (position exp1)
+		ELambda args exp1 -> min (position args) (position exp1)
+		EIfThenElse exp1 exp2 exp3 -> min (position exp1) $ min (position exp2) (position exp3)
+		EOr exp1 exp2 -> min (position exp1) (position exp2)
+		EAnd exp1 exp2 -> min (position exp1) (position exp2)
+		ECmp exp1 _ exp2 -> min (position exp1) (position exp2)
+		EPrepend exp1 exp2 -> min (position exp1) (position exp2)
+		EInfixWeak exp1 _ exp2 -> min (position exp1) (position exp2)
+		EInfixStrong exp1 _ exp2 -> min (position exp1) (position exp2)
+		EUnary _ exp1 -> position exp1
+		ENot exp1 -> position exp1
+		EHead exp1 -> position exp1
+		ETail exp1 -> position exp1
+		EAppl exp1 exp2 -> min (position exp1) (position exp2)
+		EInt (OInteger ((l,c), _)) -> At l c
+		EFloat (OFloat ((l,c), _)) -> At l c
+		EBool (OBool ((l,c), _)) -> At l c
+		EList elems -> position elems
+		EVar (OIdent ((l,c), _)) -> At l c
+		EExplType exp1 _ -> position exp1
+
+instance Positionable t => Positionable [t] where
+	position [] = Somewhere
+	position (x:xs) = foldl (\acc e -> min acc $ position e) (position x) xs
+
+instance Positionable LocDecl where
+	position loc = case loc of
+		LocalVarDecl (OIdent ((l,c), _)) _ -> At l c
+		LocalVarDeclExplType (OIdent ((l,c), _)) _ _ -> At l c
+
+instance Positionable Argument where
+	position arg = case arg of
+		FunArg (OIdent ((l,c), _)) -> At l c
+		FunArgExplType (OIdent ((l,c), _)) _ -> At l c
+
+instance Positionable ListElem where
+	position (ListElement exp) = position exp

File PrettyShow.hs

 import AbsXilocaml
 import PrintXilocaml
 import Common
+import Position
 
 
 class PrettyShowable t where
 	prettyShow :: t -> String
 
 
+instance PrettyShowable Position where
+	prettyShow Somewhere = "somewhere"
+	prettyShow (At line column) = "line " ++ (show line) ++ " around column " ++ (show column)
+
+
 instance PrettyShowable Type where
 	prettyShow = prettyShowNormalized . normalize where
 		prettyShowNormalized x = case x of

File RunEnvironment.hs

 import Control.Monad.State
 import ErrM
 import AbsXilocaml
+import Common
 
 
 -- Look out for comparisons of recursive functions with infinite environments.
 -- Difference with OCaml: int is of infinite precision instead of 31 bit.
 data Value =
-	VFun { fenv :: RunEnvironment, fargs :: [OIdent], fexp :: Exp }
+	VFun { fenv :: RunEnvironment, fargs :: [Ident], fexp :: Exp }
 	| VList { lelems :: [Value] }
 	| VFloat { fval :: Double }
 	| VInt { ival :: Integer }
 
 
 type Result = Err Value
-type RunEnvironment = Map.Map OIdent Value
+type RunEnvironment = Map.Map Ident Value
 type EnvRun = StateT RunEnvironment Err
 
 
 startREnv = Map.empty
 
 
-assignEnv :: OIdent -> t -> StateT (Map.Map OIdent t) Err ()
+assignEnv :: Ident -> t -> StateT (Map.Map Ident t) Err ()
 assignEnv ident val = modify $ Map.insert ident val
 
-lookupEnv :: OIdent -> StateT (Map.Map OIdent t) Err t
+lookupEnv :: Ident -> StateT (Map.Map Ident t) Err t
 lookupEnv ident = do
 	s <- get
 	return $ (Map.!) s ident
 
-tryLookupEnv :: OIdent -> StateT (Map.Map OIdent t) Err (Maybe t)
+tryLookupEnv :: Ident -> StateT (Map.Map Ident t) Err (Maybe t)
 tryLookupEnv ident = do
 	s <- get
 	return $ Map.lookup ident s
 
 -- Construction of infinite structure with all recursive functions and their environments is placed here
 -- Idea is like
--- let f = VFun (Map.insert (OIdent "f") f Map.empty) [OIdent "x"] (EVar $ OIdent "x")
+-- let f = VFun (Map.insert (Ident "f") f Map.empty) [Ident "x"] (EVar $ Ident "x")
 -- but it's few times more evil because of "and"
-loopEnvironment :: [OIdent] -> EnvRun ()
+loopEnvironment :: [Ident] -> EnvRun ()
 loopEnvironment idents = do
 	let loop s = let
 			env = loop s

File Semantics.hs

 import Unification
 import PrettyShow
 import Common
+import Position
 
 
 -- Checks semantics and returns expression type.
 returnType :: UType -> EnvType UType
 returnType = lift . Ok
 
-failurePrefix :: PrettyShowable a => String -> a -> String
-failurePrefix s x = "Semantic error: " ++ s ++ " in " ++ (prettyShow x) ++ "."
+failurePrefix :: String -> Exp -> String
+failurePrefix s x = "Semantic error: " ++ s ++ " in " ++ (prettyShow $ position x) ++ " in " ++ (prettyShow x) ++ "."
 
-failure :: PrettyShowable a => String -> a -> EnvType UType
+failure :: String -> Exp -> EnvType UType
 failure s x = lift $ Bad $ failurePrefix s x
 
 
 
 	EFloat _ -> returnType UFloat
 
-	ETrue -> returnType UBool
-
-	EFalse -> returnType UBool
+	EBool _ -> returnType UBool
 
 	EList elems ->
 		if elems == [] then
 			term <- nextTerm
 			liftM UList $ foldM (unify $ failurePrefix "expected consistent types in list" x) term types
 
-	EVar ident -> do
+	EVar (OIdent (_, ident)) -> do
 		val <- lookupId ident
 		case val of
-			Nothing -> failure ("undefined identifier " ++ identName ident) x
+			Nothing -> failure ("undefined identifier " ++ ident) x
 			Just t -> convertPolyToTerm t
 
 	EExplType exp explicitType -> do
 
 		addArgs (arg:args) = do
 			case arg of
-				FunArg ident -> assignNewId ident
-				FunArgExplType ident explicitType -> do
+				FunArg (OIdent (_, ident)) -> assignNewId ident
+				FunArgExplType (OIdent (_, ident)) explicitType -> do
 					explicitType' <- convertTypeToUType explicitType
 					assignId ident explicitType'
 			addArgs args
 
 addRecFunDecls (decl:decls) = do
 		case decl of
-			LocalFunDecl ident args exp ->
+			LocalFunDecl (OIdent (_, ident)) args exp ->
 				addRecFun ident args exp
-			LocalFunDeclExplType ident args _ exp ->
+			LocalFunDeclExplType (OIdent (_, ident)) args _ exp ->
 				addRecFun ident args exp
 			_ -> return ()
 		addRecFunDecls decls
 	where
-		addRecFun :: OIdent -> [Argument] -> Exp -> EnvType ()
+		addRecFun :: Ident -> [Argument] -> Exp -> EnvType ()
 		addRecFun ident args exp = do
 			declType <- liftM fromJust $ lookupId ident
 			identifiers <- getIdentifiers
 
 addRecPolymorphism (decl:decls) = do
 		case decl of
-			LocalFunDecl ident args _ -> addPolyToFun ident args
-			LocalFunDeclExplType ident args _ _ -> addPolyToFun ident args
+			LocalFunDecl (OIdent (_, ident)) args _ -> addPolyToFun ident args
+			LocalFunDeclExplType (OIdent (_, ident)) args _ _ -> addPolyToFun ident args
 			_ -> return ()
 		addRecPolymorphism decls
 	where
-		addPolyToFun :: OIdent -> [Argument] -> EnvType ()
+		addPolyToFun :: Ident -> [Argument] -> EnvType ()
 		addPolyToFun ident args = do
 			declType <- liftM fromJust $ lookupId ident
 			identifiers <- getIdentifiers
 
 addRecFunArgs (arg:args) (UFun t1 t2) = do
 	case arg of
-		FunArg ident -> assignId ident t1
-		FunArgExplType ident _ -> assignId ident t1
+		FunArg (OIdent (_, ident)) -> assignId ident t1
+		FunArgExplType (OIdent (_, ident)) _ -> assignId ident t1
 	addRecFunArgs args t2
 
 addRecFunArgs _ _ = error "Internal error: wrong usage of addRecFunArgs"
 
 convertArgsToPolymorphic (arg:args) = do
 	t <- case arg of
-		FunArg ident ->
+		FunArg (OIdent (_, ident)) ->
 			convertIdTypeToPoly ident
-		FunArgExplType ident _ ->
+		FunArgExplType (OIdent (_, ident)) _ ->
 			convertIdTypeToPoly ident
 	ts <- convertArgsToPolymorphic args
 	return (t:ts)

File TypeEnvironment.hs

 --   It might contain other UTypes only in internals of some functions,
 --   for example to remember which UTerm is created from which UPoly.
 -- * number for next fresh UTerm
-data TypeEnvironment = TypeEnvironment { idEnv :: Map.Map OIdent UType, tEnv :: Map.Map UType UType, nextN :: Int }
+data TypeEnvironment = TypeEnvironment { idEnv :: Map.Map Ident UType, tEnv :: Map.Map UType UType, nextN :: Int }
 	deriving (Eq,Ord,Show)
 type EnvType = StateT TypeEnvironment Err
 
 startTEnv = TypeEnvironment Map.empty Map.empty 0
 
 
-assignId :: OIdent -> UType -> EnvType UType
+assignId :: Ident -> UType -> EnvType UType
 assignId k v = do
 	modify $ \s -> TypeEnvironment (Map.insert k v $ idEnv s) (tEnv s) (nextN s)
 	return v
 simpleLookupType :: UType -> EnvType (Maybe UType)
 simpleLookupType k = gets $ Map.lookup k . tEnv
 
-lookupId :: OIdent -> EnvType (Maybe UType)
+lookupId :: Ident -> EnvType (Maybe UType)
 lookupId k = do
 	t <- gets $ Map.lookup k . idEnv
 	case t of
 	return (UTerm n)
 
 
-getIdentifiers :: EnvType (Map.Map OIdent UType)
+getIdentifiers :: EnvType (Map.Map Ident UType)
 getIdentifiers = gets idEnv
 
-putIdentifiers :: Map.Map OIdent UType -> EnvType ()
+putIdentifiers :: Map.Map Ident UType -> EnvType ()
 putIdentifiers i = modify $ \s -> TypeEnvironment i (tEnv s) (nextN s)
 
-assignNewId :: OIdent -> EnvType UType
+assignNewId :: Ident -> EnvType UType
 assignNewId ident = nextTerm >>= assignId ident
 
 
 
 
 -- Converts terms in type of identifier into UPoly's.
-convertIdTypeToPoly :: OIdent -> EnvType UType
+convertIdTypeToPoly :: Ident -> EnvType UType
 convertIdTypeToPoly ident = do
 	t <- liftM fromJust $ lookupId ident
 	t' <- convertTermToPoly t

File UnitTests.hs

 import Unification
 import Common
 import PrettyShow
+import Position
 import Main hiding (main)
 
-
 tests =
 	TestList [
 		TestLabel "Semantics" $ TestList [
 			],
 			TestLabel "Let rec helper functions" $ TestList [
 				execStateT (prepareRecDecls
-					[LocalVarDecl (OIdent "a") (EInt 1), LocalVarDeclExplType (OIdent "b") TInt $ EInt 2])
+					[LocalVarDecl (buildOIdent "a") (buildEInt 1), LocalVarDeclExplType (buildOIdent "b") TInt $ buildEInt 2])
 					(TypeEnvironment Map.empty Map.empty 0) ~?=
-					(Ok $ TypeEnvironment (Map.fromList [(OIdent "a", UInt), (OIdent "b", UInt)]) Map.empty 0),
+					(Ok $ TypeEnvironment (Map.fromList [("a", UInt), ("b", UInt)]) Map.empty 0),
 				execStateT (prepareRecDecls
-					[LocalFunDecl (OIdent "f") [FunArg $ OIdent "x"] $ EVar $ OIdent "x"])
+					[LocalFunDecl (buildOIdent "f") [FunArg $ buildOIdent "x"] $ buildEVar "x"])
 					(TypeEnvironment Map.empty Map.empty 0) ~?=
-					(Ok $ TypeEnvironment (Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0))]) Map.empty 2),
+					(Ok $ TypeEnvironment (Map.fromList [("f", UFun (UTerm 1) (UTerm 0))]) Map.empty 2),
 				execStateT (prepareRecDecls
-					[LocalFunDecl (OIdent "f") [FunArgExplType (OIdent "x") basicPolyType] $ EVar $ OIdent "x"])
+					[LocalFunDecl (buildOIdent "f") [FunArgExplType (buildOIdent "x") basicPolyType] $ buildEVar "x"])
 					(TypeEnvironment Map.empty Map.empty 0) ~?=
-					(Ok $ TypeEnvironment (Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0))]) Map.empty 2),
+					(Ok $ TypeEnvironment (Map.fromList [("f", UFun (UTerm 1) (UTerm 0))]) Map.empty 2),
 				execStateT (prepareRecDecls
-					[LocalFunDecl (OIdent "f") [FunArgExplType (OIdent "x") TInt, FunArg $ OIdent "y"] $ EVar $ OIdent "x"])
+					[LocalFunDecl (buildOIdent "f") [FunArgExplType (buildOIdent "x") TInt, FunArg $ buildOIdent "y"] $ buildEVar "x"])
 					(TypeEnvironment Map.empty Map.empty 0) ~?=
-					(Ok $ TypeEnvironment (Map.fromList [(OIdent "f", UFun UInt (UFun (UTerm 1) (UTerm 0)))]) Map.empty 2),
+					(Ok $ TypeEnvironment (Map.fromList [("f", UFun UInt (UFun (UTerm 1) (UTerm 0)))]) Map.empty 2),
 				execStateT (addRecFunDecls
-					[LocalFunDecl (OIdent "f") [FunArg $ OIdent "x"] $ EInt 1])
-					(TypeEnvironment (Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0)), (OIdent "x", UTerm 1)]) Map.empty 2) ~?=
+					[LocalFunDecl (buildOIdent "f") [FunArg $ buildOIdent "x"] $ buildEInt 1])
+					(TypeEnvironment (Map.fromList [("f", UFun (UTerm 1) (UTerm 0)), ("x", UTerm 1)]) Map.empty 2) ~?=
 					(Ok $ TypeEnvironment
-						(Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0)), (OIdent "x", UTerm 1)])
+						(Map.fromList [("f", UFun (UTerm 1) (UTerm 0)), ("x", UTerm 1)])
 						(Map.fromList [(UTerm 0, UInt)]) 2),
 				execStateT (addRecFunDecls
-					[LocalFunDecl (OIdent "f") [FunArg $ OIdent "x"] $ EVar $ OIdent "x"])
-					(TypeEnvironment (Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0)), (OIdent "x", UTerm 1)]) Map.empty 2) ~?=
+					[LocalFunDecl (buildOIdent "f") [FunArg $ buildOIdent "x"] $ buildEVar "x"])
+					(TypeEnvironment (Map.fromList [("f", UFun (UTerm 1) (UTerm 0)), ("x", UTerm 1)]) Map.empty 2) ~?=
 					(Ok $ TypeEnvironment
-						(Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0)), (OIdent "x", UTerm 1)])
+						(Map.fromList [("f", UFun (UTerm 1) (UTerm 0)), ("x", UTerm 1)])
 						(Map.fromList [(UTerm 0, UTerm 1)]) 2),
 				execStateT (addRecFunDecls
-					[LocalFunDecl (OIdent "f") [FunArg $ OIdent "x"] $
+					[LocalFunDecl (buildOIdent "f") [FunArg $ buildOIdent "x"] $
 						EIfThenElse
-							(ECmp (EVar $ OIdent "x") OLeq (EInt 42))
-							(EVar $ OIdent "x")
-							(EAppl (EVar $ OIdent "f") (EVar $ OIdent "x"))])
-					(TypeEnvironment (Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0)), (OIdent "x", UTerm 1)]) Map.empty 2) ~?=
+							(ECmp (buildEVar "x") OLeq (buildEInt 42))
+							(buildEVar "x")
+							(EAppl (buildEVar "f") (buildEVar "x"))])
+					(TypeEnvironment (Map.fromList [("f", UFun (UTerm 1) (UTerm 0)), ("x", UTerm 1)]) Map.empty 2) ~?=
 					(Ok $ TypeEnvironment
-						(Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0)), (OIdent "x", UTerm 1)])
+						(Map.fromList [("f", UFun (UTerm 1) (UTerm 0)), ("x", UTerm 1)])
 						(Map.fromList [(UTerm 0, UInt), (UTerm 1, UInt), (UTerm 2, UInt)]) 3),
 				execStateT (addRecPolymorphism
-					[LocalFunDecl (OIdent "f") [FunArg $ OIdent "x"] $ EVar $ OIdent "x"])
+					[LocalFunDecl (buildOIdent "f") [FunArg $ buildOIdent "x"] $ buildEVar "x"])
 					(TypeEnvironment
-						(Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0)), (OIdent "x", UTerm 1)])
+						(Map.fromList [("f", UFun (UTerm 1) (UTerm 0)), ("x", UTerm 1)])
 						(Map.fromList [(UTerm 0, UTerm 1)]) 2) ~?=
 					(Ok $ TypeEnvironment
-						(Map.fromList [(OIdent "f", UFun (UTerm 1) (UTerm 0)), (OIdent "x", UTerm 1)])
+						(Map.fromList [("f", UFun (UTerm 1) (UTerm 0)), ("x", UTerm 1)])
 						(Map.fromList [(UTerm 0, UTerm 1),(UTerm 1, UPoly 1)]) 2)
 			],
 			TestLabel "Function type checker" $ TestList [
-				assertTypeEquals (checkFun [] (EInt 3)) startTEnv UInt,
-				assertBadSemantics (checkFun [] (EVar $ OIdent "x")) startTEnv,
-				assertTypeEquals (checkFun [FunArgExplType (OIdent "x") TInt] (EInt 2)) startTEnv $ UFun UInt UInt,
-				assertTypeEquals (checkFun [FunArgExplType (OIdent "x") TInt] (EVar $ OIdent "x")) startTEnv $ UFun UInt UInt,
-				assertTypeEquals (checkFun [] (EVar $ OIdent "x"))
-					(TypeEnvironment (Map.fromList[(OIdent "x", UInt)]) Map.empty 0) UInt,
-				assertTypeEquals (checkFun [FunArgExplType (OIdent "x") TBool] (EVar $ OIdent "x"))
-					(TypeEnvironment (Map.fromList [(OIdent "x", UInt)]) Map.empty 0) $ UFun UBool UBool
+				assertTypeEquals (checkFun [] (buildEInt 3)) startTEnv UInt,
+				assertBadSemantics (checkFun [] (buildEVar "x")) startTEnv,
+				assertTypeEquals (checkFun [FunArgExplType (buildOIdent "x") TInt] (buildEInt 2)) startTEnv $ UFun UInt UInt,
+				assertTypeEquals (checkFun [FunArgExplType (buildOIdent "x") TInt] (buildEVar "x")) startTEnv $ UFun UInt UInt,
+				assertTypeEquals (checkFun [] (buildEVar "x"))
+					(TypeEnvironment (Map.fromList[("x", UInt)]) Map.empty 0) UInt,
+				assertTypeEquals (checkFun [FunArgExplType (buildOIdent "x") TBool] (buildEVar "x"))
+					(TypeEnvironment (Map.fromList [("x", UInt)]) Map.empty 0) $ UFun UBool UBool
 			],
 			TestLabel "Type inference" $ TestList [
 				assertParsedTypeEquals "1" TInt,
 					TFun TInt (TFun (basicPolyType) (TList $ TFun (basicPolyType') (basicPolyType)))
 			],
 			TestLabel "UTerm -> UPoly conversion for identifiers" $ TestList [
-				runStateT (convertIdTypeToPoly $ OIdent "x")
-					(TypeEnvironment (Map.fromList [(OIdent "x", UFun UInt UBool)]) Map.empty 0) ~?=
-					Ok (UFun UInt UBool, TypeEnvironment (Map.fromList [(OIdent "x", UFun UInt UBool)]) Map.empty 0),
-				runStateT (convertIdTypeToPoly $ OIdent "x")
-					(TypeEnvironment (Map.fromList [(OIdent "x", UTerm 1)]) Map.empty 2) ~?=
-					Ok (UPoly 1, TypeEnvironment (Map.fromList [(OIdent "x", UPoly 1)]) (Map.fromList [(UTerm 1, UPoly 1)]) 2),
-				evalStateT (convertIdTypeToPoly $ OIdent "x")
+				runStateT (convertIdTypeToPoly "x")
+					(TypeEnvironment (Map.fromList [("x", UFun UInt UBool)]) Map.empty 0) ~?=
+					Ok (UFun UInt UBool, TypeEnvironment (Map.fromList [("x", UFun UInt UBool)]) Map.empty 0),
+				runStateT (convertIdTypeToPoly "x")
+					(TypeEnvironment (Map.fromList [("x", UTerm 1)]) Map.empty 2) ~?=
+					Ok (UPoly 1, TypeEnvironment (Map.fromList [("x", UPoly 1)]) (Map.fromList [(UTerm 1, UPoly 1)]) 2),
+				evalStateT (convertIdTypeToPoly "x")
 					(TypeEnvironment
-						(Map.fromList [(OIdent "x", UTerm 2)])
+						(Map.fromList [("x", UTerm 2)])
 						(Map.fromList [(UTerm 2, UTerm 1)]) 3) ~?=
 					(Ok $ UPoly 1),
-				evalStateT (convertIdTypeToPoly $ OIdent "x")
+				evalStateT (convertIdTypeToPoly "x")
 					(TypeEnvironment
-						(Map.fromList [(OIdent "x", UTerm 3)])
+						(Map.fromList [("x", UTerm 3)])
 						(Map.fromList [(UTerm 3, UTerm 1), (UTerm 1, UFun UBool (UTerm 0))]) 4) ~?=
 					(Ok $ UFun UBool (UPoly 0)),
-				evalStateT (convertIdTypeToPoly $ OIdent "x")
+				evalStateT (convertIdTypeToPoly "x")
 					(TypeEnvironment
-						(Map.fromList [(OIdent "x", UTerm 1), (OIdent "y", UTerm 2)])
+						(Map.fromList [("x", UTerm 1), ("y", UTerm 2)])
 						(Map.fromList [(UTerm 2, UTerm 1)]) 4) ~?=
 					(Ok $ UPoly 1)
 			],
 				assertParsedRuntimeError "2::[1+1;1/0]"
 			],
 			TestLabel "Lambda" $ TestList [
-				assertParsedValueEquals "fun (x : int) -> x" $ VFun startREnv [OIdent "x"] $ EVar (OIdent "x"),
-				assertParsedValueEquals "fun (x : int) (y : int) -> x + y" $ VFun startREnv [OIdent "x", OIdent "y"] $ EInfixWeak (EVar $ OIdent "x") OAdd (EVar $ OIdent "y"),
-				assertParsedValueEquals "fun (x : int) -> fun (y : int) -> x * y" $ VFun startREnv [OIdent "x"] $ ELambda [FunArgExplType (OIdent "y") TInt] $ EInfixStrong (EVar $ OIdent "x") OMul (EVar $ OIdent "y"),
-				assertParsedValueEquals "fun (f : int -> int) -> f" $ VFun startREnv [OIdent "f"] $ EVar (OIdent "f"),
-				assertParsedValueEquals "fun (x : int) -> x / 0" $ VFun startREnv [OIdent "x"] $ EInfixStrong (EVar $ OIdent "x") ODiv (EInt 0)
+				assertParsedValueEquals "fun (x : int) -> x" $ VFun startREnv ["x"] $ buildEVar "x",
+				assertParsedValueEquals "fun (x : int) (y : int) -> x + y" $ VFun startREnv ["x", "y"] $ EInfixWeak (buildEVar "x") OAdd (buildEVar "y"),
+				assertParsedValueEquals "fun (x : int) -> fun (y : int) -> x * y" $ VFun startREnv ["x"] $ ELambda [FunArgExplType (buildOIdent "y") TInt] $ EInfixStrong (buildEVar "x") OMul (buildEVar "y"),
+				assertParsedValueEquals "fun (f : int -> int) -> f" $ VFun startREnv ["f"] $ buildEVar "f",
+				assertParsedValueEquals "fun (x : int) -> x / 0" $ VFun startREnv ["x"] $ EInfixStrong (buildEVar "x") ODiv (buildEInt 0)
 			],
 			TestLabel "Function application" $ TestList [
 				assertParsedValueEquals "(fun (x : int) -> 2 * x) 3" $ VInt 6,
 				assertParsedValueEquals "(fun (x : int) (y : bool) -> if y then 2 * x else 3 * x) 2 false" $ VInt 6,
-				assertParsedValueEquals "(fun (x : int) (y : int) -> x * y) 2" $ VFun (createEnv [("x", VInt 2)]) [OIdent "y"] $ EInfixStrong (EVar $ OIdent "x") OMul (EVar $ OIdent "y"),
-				assertParsedValueEquals "(fun (x : int) (y : bool) -> fun (x : int) -> 2 * x) 2 true" $ VFun (createEnv [("y", VBool True), ("x", VInt 2)]) [OIdent "x"] $ EInfixStrong (EInt 2) OMul (EVar $ OIdent "x")
+				assertParsedValueEquals "(fun (x : int) (y : int) -> x * y) 2" $ VFun (createEnv [("x", VInt 2)]) ["y"] $ EInfixStrong (buildEVar "x") OMul (buildEVar "y"),
+				assertParsedValueEquals "(fun (x : int) (y : bool) -> fun (x : int) -> 2 * x) 2 true" $ VFun (createEnv [("y", VBool True), ("x", VInt 2)]) ["x"] $ EInfixStrong (buildEInt 2) OMul (buildEVar "x")
 			],
 			TestLabel "Comparison of functions" $ assertParsedRuntimeError "(fun x -> x = x) (fun x -> x)",
 			TestLabel "Let in" $ TestList [
 				assertParsedValueEquals "let a = 2 in a" $ VInt 2,
 				assertParsedValueEquals "let a : int = 2 in a" $ VInt 2,
-				assertParsedValueEquals "let a (x : int) = x in a" $ VFun startREnv [OIdent "x"] $ EVar (OIdent "x"),
-				assertParsedValueEquals "let a (x : int) : int = 2 in a" $ VFun startREnv [OIdent "x"] $ EInt 2,
-				assertParsedValueEquals "let a (x : int) : int = x in a" $ VFun startREnv [OIdent "x"] $ EVar (OIdent "x"),
+				assertParsedValueEquals "let a (x : int) = x in a" $ VFun startREnv ["x"] $ buildEVar "x",
+				assertParsedValueEquals "let a (x : int) : int = 2 in a" $ VFun startREnv ["x"] $ buildEInt 2,
+				assertParsedValueEquals "let a (x : int) : int = x in a" $ VFun startREnv ["x"] $ buildEVar "x",
 				assertParsedValueEquals "1 + (let a = 2 in a + a)" $ VInt 5
 			],
 			TestLabel "Let rec" $ TestList [
 			],
 			TestLabel "Looping environment" $ TestList [
 				assertVariableFound ["x"] $ Ok $ createEnv [("x", VInt 1)],
-				assertVariableFound ["f", "y"] $ Ok $ createEnv [("f", VFun (createEnv [("y", VInt 1)]) [] ETrue)],
+				assertVariableFound ["f", "y"] $ Ok $ createEnv [("f", VFun (createEnv [("y", VInt 1)]) [] someExpression)],
 				assertVariableFound ["f"] $
-					execStateT (loopEnvironment [OIdent "f"]) $ createEnv
-						[("f", VFun startREnv [] ETrue)],
+					execStateT (loopEnvironment ["f"]) $ createEnv
+						[("f", VFun startREnv [] someExpression)],
 				assertVariableFound ["f", "f", "f", "f", "f"] $
-					execStateT (loopEnvironment [OIdent "f"]) $
-					createEnv [("f", VFun startREnv [] ETrue)],
+					execStateT (loopEnvironment ["f"]) $
+					createEnv [("f", VFun startREnv [] someExpression)],
 				assertVariableFound ["f", "f", "f", "f", "a"] $
-					execStateT (loopEnvironment [OIdent "f"]) $ createEnv
-						[("f", VFun startREnv [] ETrue),
+					execStateT (loopEnvironment ["f"]) $ createEnv
+						[("f", VFun startREnv [] someExpression),
 						("a", VInt 1)],
 				assertVariableFound ["f", "f", "g", "f", "g"] $
-					execStateT (loopEnvironment [OIdent "f", OIdent "g"]) $ createEnv
-						[("f", VFun startREnv [] ETrue),
-						("g", VFun startREnv [] ETrue),
+					execStateT (loopEnvironment ["f", "g"]) $ createEnv
+						[("f", VFun startREnv [] someExpression),
+						("g", VFun startREnv [] someExpression),
 						("a", VInt 1)],
 				assertVariableFound ["g", "f", "g", "f", "f", "h", "h", "f", "a"] $
-					execStateT (loopEnvironment [OIdent "f", OIdent "g", OIdent "h"]) $ createEnv
-						[("f", VFun startREnv [] ETrue),
-						("g", VFun startREnv [] ETrue),
-						("h", VFun startREnv [] ETrue),
+					execStateT (loopEnvironment ["f", "g", "h"]) $ createEnv
+						[("f", VFun startREnv [] someExpression),
+						("g", VFun startREnv [] someExpression),
+						("h", VFun startREnv [] someExpression),
 						("a", VInt 1),
 						("b", VBool True)]
 			]
 		],
+		TestLabel "Position detection" $ TestList [
+			position (EInt $ OInteger ((0,0), "42")) ~?= At 0 0,
+			position (EList []) ~?= Somewhere,
+			position (ELambda [FunArg $ OIdent ((1,12), "x")] (EVar $ OIdent ((1, 20), "x"))) ~?= At 1 12,
+			position (EIfThenElse (ECmp (EList []) OEq (EList [])) (EList []) (EList [ListElement $ EList []])) ~?= Somewhere,
+			position (EIfThenElse (ECmp (EList []) OEq (EList [])) (EList [ListElement $ EInt $ OInteger ((2,15), "42")]) (EList [ListElement $ EInt $ OInteger ((3,1), "44")])) ~?= At 2 15
+		],
 		TestLabel "Pretty printer" $ TestList [
+			TestLabel "Position" $ TestList [
+				prettyShow Somewhere ~?= "somewhere",
+				prettyShow (At 3 2) ~?= "line 3 around column 2"
+			],
 			TestLabel "Types" $ TestList [
 				prettyShow (TInt) ~?= "int",
 				prettyShow (TFun TInt (TFun TBool TFloat)) ~?= "int -> bool -> float",
 			],
 			TestLabel "Values" $ TestList [
 				prettyShow (VInt 42) ~?= "42",
-				prettyShow (VFun startREnv [] ETrue) ~?= "<fun>",
+				prettyShow (VFun startREnv [] someExpression) ~?= "<fun>",
 				prettyShow (VList [VBool True, VBool False]) ~?= "[true;false]",
 				prettyShow (VList [VBool True]) ~?= "[true]",
 				prettyShow (VList []) ~?= "[]",
-				prettyShow (VList [VFun startREnv [] ETrue, VFun startREnv [] ETrue]) ~?= "[<fun>;<fun>]"
+				prettyShow (VList [VFun startREnv [] someExpression, VFun startREnv [] someExpression]) ~?= "[<fun>;<fun>]"
 			],
 			TestLabel "UTypes" $ TestList [
 				prettyShow (UFun UInt (UList UBool)) ~?= "int -> bool list",
 
 main = runTestTT tests
 
+someExpression = EBool $ OBool ((0,0),"true")
+
+buildEInt n = EInt $ OInteger ((0,0), show n)
+buildEVar = EVar . buildOIdent
+buildOIdent ident = OIdent ((0,0), ident)
+
 basicPolyType = TPoly $ OPolyIdent "'a"
 basicPolyType' = TPoly $ OPolyIdent "'b"
 
 assertParsedValueEquals :: String -> Value -> Test
 assertParsedValueEquals input expectedValue =
 	case interpreted input of
-		Ok (Ok t) -> t ~?= expectedValue
+		Ok (Ok t) -> (removePosition t) ~?= expectedValue
 		Ok (Bad s) -> TestCase $ assertFailure $ "Runtime error, but expected " ++ (show expectedValue) ++ " in " ++ input ++ ". Error message: " ++ s ++ "."
 		Bad s -> TestCase $ assertFailure s
 
 -- Input is sequence of identifiers of which every but last must be a function type.
 assertVariableFound :: [String] -> Err RunEnvironment -> Test
 assertVariableFound _ (Bad s) = TestCase $ assertFailure s
-assertVariableFound identStrs (Ok env) = let
-		lookupVariable :: [OIdent] -> EnvRun ()
+assertVariableFound idents (Ok env) = let
+		lookupVariable :: [Ident] -> EnvRun ()
 		lookupVariable [] = return ()
 		lookupVariable [ident] = do
 			v <- tryLookupEnv ident
 			case v of
-				Nothing -> lift $ Bad $ "Looked up variable " ++ (identName ident) ++ " doesn't exist."
+				Nothing -> lift $ Bad $ "Looked up variable " ++ ident ++ " doesn't exist."
 				Just _ -> return ()
 		lookupVariable (ident:idents) = do
 			v <- tryLookupEnv ident
 			case v of
-				Nothing -> lift $ Bad $ "Looked up variable " ++ (identName ident) ++ " doesn't exist."
+				Nothing -> lift $ Bad $ "Looked up variable " ++ ident ++ " doesn't exist."
 				Just (VFun env _ _) -> do
 					put env
 					lookupVariable idents
-				Just _ -> lift $ Bad $ "Looked up variable " ++ (identName ident) ++ " is not a function."
-		found = evalStateT (lookupVariable $ map OIdent identStrs) env
+				Just _ -> lift $ Bad $ "Looked up variable " ++ ident ++ " is not a function."
+		found = evalStateT (lookupVariable idents) env
 	in case found of
 		Ok _ -> TestCase $ assertBool "" True
 		Bad s -> TestCase $ assertFailure s
 
 
-createEnv :: [(String, t)] -> Map.Map OIdent t
-createEnv mapping = Map.fromList $ map (\(s,v) -> (OIdent s, v)) mapping
+createEnv :: [(String, t)] -> Map.Map Ident t
+createEnv = Map.fromList
 
 assertUnifiedTypesEqual :: UType -> UType -> UType -> Test
 assertUnifiedTypesEqual t1 t2 expected =
 assertUnificationFails :: UType -> UType -> Test
 assertUnificationFails t1 t2 =
 	assertBad $ evalStateT (unify "" t1 t2) startTEnv
+
+
+class RemoveablePosition t where
+	removePosition :: t -> t
+
+instance RemoveablePosition Exp where
+	removePosition exp = case exp of
+		ELetIn loc exp1 -> ELetIn (removePosition loc) (removePosition exp1)
+		ELetRecIn loc exp1 -> ELetRecIn (removePosition loc) (removePosition exp1)
+		ELambda args exp1 -> ELambda (removePosition args) (removePosition exp1)
+		EIfThenElse exp1 exp2 exp3 -> EIfThenElse (removePosition exp1) (removePosition exp2) (removePosition exp3)
+		EOr exp1 exp2 -> EOr (removePosition exp1) (removePosition exp2)
+		EAnd exp1 exp2 -> EAnd (removePosition exp1) (removePosition exp2)
+		ECmp exp1 cmp exp2 -> ECmp (removePosition exp1) cmp (removePosition exp2)
+		EPrepend exp1 exp2 -> EPrepend (removePosition exp1) (removePosition exp2)
+		EInfixWeak exp1 op exp2 -> EInfixWeak (removePosition exp1) op (removePosition exp2)
+		EInfixStrong exp1 op exp2 -> EInfixStrong (removePosition exp1) op (removePosition exp2)
+		EUnary op exp1 -> EUnary op (removePosition exp1)
+		ENot exp1 -> ENot (removePosition exp1)
+		EHead exp1 -> EHead (removePosition exp1)
+		ETail exp1 -> ETail (removePosition exp1)
+		EAppl exp1 exp2 -> EAppl (removePosition exp1) (removePosition exp2)
+		EInt (OInteger ((_,_), str)) -> EInt $ OInteger ((0,0), str)
+		EFloat (OFloat ((_,_), str)) -> EFloat $ OFloat ((0,0), str)
+		EBool (OBool ((_,_), str)) -> EBool $ OBool ((0,0), str)
+		EList elems -> EList (removePosition elems)
+		EVar (OIdent ((_,_), str)) -> EVar $ OIdent ((0,0), str)
+		EExplType exp1 explType -> EExplType (removePosition exp1) explType
+
+instance RemoveablePosition t => RemoveablePosition [t] where
+	removePosition = map removePosition
+
+instance RemoveablePosition LocDecl where
+	removePosition loc = case loc of
+		LocalVarDecl (OIdent ((_,_), str)) exp ->
+			LocalVarDecl (OIdent ((0,0), str)) (removePosition exp)
+		LocalVarDeclExplType (OIdent ((_,_), str)) explType exp ->
+			LocalVarDeclExplType (OIdent ((0,0), str)) explType (removePosition exp)
+
+instance RemoveablePosition Argument where
+	removePosition arg = case arg of
+		FunArg (OIdent ((_,_), str)) ->
+			FunArg (OIdent ((0,0), str))
+		FunArgExplType (OIdent ((_,_), str)) explType ->
+			FunArgExplType (OIdent ((0,0), str)) explType
+
+instance RemoveablePosition ListElem where
+	removePosition (ListElement exp) = ListElement $ removePosition exp
+
+instance RemoveablePosition Value where
+	removePosition val = case val of
+		VFun fenv fargs fexp -> VFun (Map.map removePosition fenv) fargs (removePosition fexp)
+		VList lelems -> VList $ removePosition lelems
+		_ -> val
 -- Unlike in OCaml, nested comments aren't allowed
 comment "(*" "*)" ;
 
+position token OInteger digit+ ;
+position token OBool 't' 'r' 'u' 'e' | 'f' 'a' 'l' 's' 'e' ;
 -- More Options than for Double (mainly 1.)
-token OFloat (((digit+ '.' digit*)|('.' digit+))(('e'|'E') ('+'|'-')? digit+)?)|
+position token OFloat (((digit+ '.' digit*)|('.' digit+))(('e'|'E') ('+'|'-')? digit+)?)|
              (digit+ ('e'|'E') ('-')? digit+) ;
 -- Identifier for function and argument names
-token OIdent lower (letter | digit | '_' | '\'')* ;
+position token OIdent lower (letter | digit | '_' | '\'')* ;
 -- Identifier for polymorphic types
 token OPolyIdent '\'' (letter | digit | '_' | '\'')* ;
 
 CompatibColon. ComEnd ::= ";;" ;
 CompatibEnd.   ComEnd ::= ;
 
--- In Ocaml let has every priority and greedy second Exp (possible "1+let a=2 in a + a")
+-- In Ocaml let has every priority and greedy last Exp (possible "1+let a=2 in a + a")
 ELetIn.       Exp  ::= "let" [LocDecl] "in" Exp ;
 ELetRecIn.    Exp  ::= "let" "rec" [LocDecl] "in" Exp ;
 ELambda.      Exp  ::= "fun" [Argument] "->" Exp ;
 EHead.        Exp8 ::= "hd"  Exp10 ;
 ETail.        Exp8 ::= "tl"  Exp10 ;
 EAppl.        Exp9 ::= Exp9 Exp10 ;
-EInt.         Exp10 ::= Integer ;
+EInt.         Exp10 ::= OInteger ;
 EFloat.       Exp10 ::= OFloat ;
-ETrue.        Exp10 ::= "true" ;
-EFalse.       Exp10 ::= "false" ;
+EBool.        Exp10 ::= OBool ;
 EList.        Exp10 ::= "[" [ListElem] "]" ;
 EVar.         Exp11 ::= OIdent ;
 EExplType.    Exp12 ::= "(" Exp ":" Type ")" ;

File doc/Xilocaml.tex

 	\item parametric polymorphism.
 \end{itemize}
 
+
+%%%% BNFC %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
 \section{The lexical structure of Xilocaml}
 
 \subsection{Literals}
-Integer literals \nonterminal{Int}\ are nonempty sequences of digits.
+OInteger literals are recognized by the regular expression
+\({\nonterminal{digit}}+\)
+
+OBool literals are recognized by the regular expression
+\(\mbox{`t'} \mbox{`r'} \mbox{`u'} \mbox{`e'} \mid \mbox{`f'} \mbox{`a'} \mbox{`l'} \mbox{`s'} \mbox{`e'}\)
 
 OFloat literals are recognized by the regular expression
 \(({\nonterminal{digit}}+ \mbox{`.'} {\nonterminal{digit}}* \mid \mbox{`.'} {\nonterminal{digit}}+) ((\mbox{`e'} \mid \mbox{`E'}) (\mbox{`{$+$}'} \mid \mbox{`{$-$}'})? {\nonterminal{digit}}+)? \mid {\nonterminal{digit}}+ (\mbox{`e'} \mid \mbox{`E'}) \mbox{`{$-$}'}? {\nonterminal{digit}}+\)
 OIdent literals are recognized by the regular expression
 \({\nonterminal{lower}} ({\nonterminal{letter}} \mid {\nonterminal{digit}} \mid \mbox{`\_'} \mid \mbox{`''})*\)
 
-OPoliIdent literals are recognized by the regular expression
+OPolyIdent literals are recognized by the regular expression
 \(\mbox{`''} ({\nonterminal{letter}} \mid {\nonterminal{digit}} \mid \mbox{`\_'} \mid \mbox{`''})*\)
 
+
 \subsection{Reserved words and symbols}
 The set of reserved words is the set of terminals appearing in the grammar. Those reserved words that consist of non-letter characters are called symbols, and they are treated in a different way from those that are similar to identifiers. The lexer follows rules familiar from languages like Haskell, C, and Java, including longest match and spacing conventions.
 
 
 \begin{tabular}{lll}
 {\reserved{List}} &{\reserved{and}} &{\reserved{bool}} \\
-{\reserved{else}} &{\reserved{false}} &{\reserved{float}} \\
-{\reserved{fun}} &{\reserved{hd}} &{\reserved{if}} \\
-{\reserved{in}} &{\reserved{int}} &{\reserved{let}} \\
-{\reserved{list}} &{\reserved{mod}} &{\reserved{not}} \\
-{\reserved{open}} &{\reserved{rec}} &{\reserved{then}} \\
-{\reserved{tl}} &{\reserved{true}} & \\
+{\reserved{else}} &{\reserved{float}} &{\reserved{fun}} \\
+{\reserved{hd}} &{\reserved{if}} &{\reserved{in}} \\
+{\reserved{int}} &{\reserved{let}} &{\reserved{list}} \\
+{\reserved{mod}} &{\reserved{not}} &{\reserved{open}} \\
+{\reserved{rec}} &{\reserved{then}} &{\reserved{tl}} \\
 \end{tabular}\\
 
 The symbols used in Xilocaml are the following: \\
 {\symb{/.}} & & \\
 \end{tabular}\\
 
+
 \subsection{Comments}
 There are no single-line comments in the grammar. \\Multiple-line comments are  enclosed with {\symb{(*}} and {\symb{*)}}. Unlike in OCaml, nested comments are not allowed.
 
+
 \section{The syntactic structure of Xilocaml}
 Non-terminals are enclosed between $\langle$ and $\rangle$. 
 The symbols  {\arrow}  (production),  {\delimit}  (union) 
 \end{tabular}\\
 
 \begin{tabular}{lll}
-{\nonterminal{Exp10}} & {\arrow}  &{\nonterminal{Integer}}  \\
+{\nonterminal{Exp10}} & {\arrow}  &{\nonterminal{OInteger}}  \\
  & {\delimit}  &{\nonterminal{OFloat}}  \\
- & {\delimit}  &{\terminal{true}}  \\
- & {\delimit}  &{\terminal{false}}  \\
+ & {\delimit}  &{\nonterminal{OBool}}  \\
  & {\delimit}  &{\terminal{[}} {\nonterminal{ListListElem}} {\terminal{]}}  \\
  & {\delimit}  &{\nonterminal{Exp11}}  \\
 \end{tabular}\\
 \end{tabular}\\
 
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
 \section{Semantics of Xilocaml}
 
 Xilocaml is a subset of OCaml 3.12. with very little changes. All syntactically valid constructions not described below have the same meaning as in language OCaml 3.12. For description of OCaml semantics, see \cite{ocaml}.
 
 Floating-point operations have the same meaning as in OCaml and integer operations are performed on arbitrary precision integers. For compatibility to OCaml 3.12 implementation, sequence of unary prefix operators {\symb{+}}, {\symb{-}}, {\symb{+.}}, {\symb{-.}} applied to a floating-point constant is allowed and has the standard meaning.
 
+\subsection{Explicit types}
+It is possible to explicitly define types in Xilocaml similarly to OCaml. The only difference is that in Xilocaml, explicitly defined polymorphic types are local for each declaration. That is, a polymorphic type (like {\code{'a}}) actual type is independent of it's usage outside of {\code{pattern}} in declaration:
+\begin{verbatim}
+pattern = expr
+\end{verbatim}
+
 \subsection{Type inference}
 Type inference in Xilocaml behave the same way as in OCaml (without enabled recursive types). If Xilocaml will be unable to detect the type of a value, a semantics error will occur. Xilocaml should be able to deduct types of all its constructions that implementation of OCaml 3.12. is able to.
 
 	\item comparing functional values (it might not be detected as a semantic error when functional values are passed to a polymorphic function).
 \end{itemize}
 
+If any bound name or constant is used in expression that generated semantic or runtime error, its approximate line and column will be printed out together with code and error description. In case of syntactic error, printed out data is library-dependent, though usually position of error along with additional information is printed out too.
+
+\subsection{Tail recursion}
+In Xilocaml interpreter, tail recursion isn't implemented, so programs depending on it may quickly run out of memory.
+
 
 \begin{thebibliography}{99}
 \addcontentsline{toc}{section}{Bibliography}
 
 \end{thebibliography}
 
-\end{document}
+\end{document}