on master help sign in
move common stringy elements to Data.Text to save more space

add command-line parsing to bigrel all tests pass

commitf7681f6c00feeb4249e5c7247261ec50ff9dff9a authorAgentM <agentm@themactionfaction.com> dateMon 4 May 2015, 14:19 (11 years ago) parent84b3b93
17 files changed+187−143
ProjectM36/Atom.hs+1 ProjectM36/Base.hs+19−13 ProjectM36/Error.hs+7−6 ProjectM36/Relation.hs+4−3 ProjectM36/Relation/Show/HTML.hs+18−15 ProjectM36/Relation/Show/Term.hs+43−41 ProjectM36/RelationalExpression.hs+3−2 ProjectM36/Transaction.hs+3−2 ProjectM36/Transaction/Show.hs+4−2 ProjectM36/TupleSet.hs+2−1 TutorialD/Interpreter.hs+50−45 TutorialD/tutd.hs+1 benchmark/bigrel.hs+26−10 project-m36.cabal+2−2 test/Relation/Basic.hs+2−1 test/Relation/StaticOptimizer.hs+1 test/TutorialD/Interpreter.hs+1
ProjectM36/Atom.hs+1
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12module ProjectM36.Atom where
23import ProjectM36.Base
34import ProjectM36.Error
ProjectM36/Base.hs+19−13
@@ -11,8 +11,11 @@ import Control.DeepSeq.Generics (genericRnf)
1111import GHC.Generics (Generic)
1212import qualified Data.Vector as V
1313import qualified Data.List as L
14+import qualified Data.Text as T
1415
15−data Atom = StringAtom String |
16+type StringType = T.Text
17+
18+data Atom = StringAtom StringType |
1619 IntAtom Int |
1720 RelationAtom Relation deriving (Show, Eq, Generic)
1821
@@ -26,8 +29,7 @@ data AtomType = StringAtomType |
2629
2730instance NFData AtomType where rnf = genericRnf
2831
29−type AttributeName = String
30−type AtomName = String
32+type AttributeName = T.Text
3133
3234data Attribute = Attribute AttributeName AtomType deriving (Eq, Show, Generic)
3335
@@ -88,12 +90,14 @@ instance Hash.Hashable Relation where
8890data RelationCardinality = Uncountable | Countable Int deriving (Eq, Show, Generic)
8991data RelationSizeInfinite = RelationSizeInfinite
9092
93+type RelVarName = StringType
94+
9195data RelationalExpr where
9296 MakeStaticRelation :: Attributes -> RelationTupleSet -> RelationalExpr
9397 --MakeFunctionalRelation (creates a relation from a tuple-generating function, potentially infinite)
9498 --in Tutorial D, relational variables pick up the type of the first relation assigned to them
9599 --relational variables should also be able to be explicitly-typed like in Haskell
96− RelationVariable :: String -> RelationalExpr
100+ RelationVariable :: RelVarName -> RelationalExpr
97101 Project :: S.Set AttributeName -> RelationalExpr -> RelationalExpr
98102 Union :: RelationalExpr -> RelationalExpr -> RelationalExpr
99103 Join :: RelationalExpr -> RelationalExpr -> RelationalExpr
@@ -111,10 +115,12 @@ data RelationalExpr where
111115
112116data DatabaseContext = DatabaseContext {
113117 inclusionDependencies :: HS.HashSet InclusionDependency,
114− relationVariables :: M.Map String Relation
118+ relationVariables :: M.Map RelVarName Relation
115119 } deriving (Show)
116120
117−data InclusionDependency = InclusionDependency String RelationalExpr RelationalExpr deriving (Show)
121+type IncDepName = StringType
122+
123+data InclusionDependency = InclusionDependency IncDepName RelationalExpr RelationalExpr deriving (Show)
118124
119125instance Hash.Hashable InclusionDependency where
120126 hashWithSalt salt dep = Hash.hashWithSalt salt (show dep)
@@ -124,12 +130,12 @@ instance Eq InclusionDependency where
124130
125131--Database context expressions modify the database context while relational expressions do not
126132data DatabaseExpr where
127− Define :: String -> Attributes -> DatabaseExpr
128− Undefine :: String -> DatabaseExpr --forget existence of relvar X
129− Assign :: String -> RelationalExpr -> DatabaseExpr
130− Insert :: String -> RelationalExpr -> DatabaseExpr
131− Delete :: String -> RestrictionPredicateExpr -> DatabaseExpr
132− Update :: String -> M.Map String Atom -> RestrictionPredicateExpr -> DatabaseExpr -- needs restriction support
133+ Define :: RelVarName -> Attributes -> DatabaseExpr
134+ Undefine :: RelVarName -> DatabaseExpr --forget existence of relvar X
135+ Assign :: RelVarName -> RelationalExpr -> DatabaseExpr
136+ Insert :: RelVarName -> RelationalExpr -> DatabaseExpr
137+ Delete :: RelVarName -> RestrictionPredicateExpr -> DatabaseExpr
138+ Update :: RelVarName -> M.Map AttributeName Atom -> RestrictionPredicateExpr -> DatabaseExpr -- needs restriction support
133139 AddInclusionDependency :: InclusionDependency -> DatabaseExpr
134140 MultipleExpr :: [DatabaseExpr] -> DatabaseExpr
135141 deriving (Show,Eq)
@@ -147,7 +153,7 @@ data RestrictionPredicateExpr where
147153
148154-- child + parent links
149155-- the string represents the branch name and can be used to find the named HEADs
150−type HeadName = String
156+type HeadName = StringType
151157
152158type TransactionHeads = M.Map HeadName Transaction
153159
ProjectM36/Error.hs+7−6
@@ -5,21 +5,22 @@ import qualified Data.UUID as U
55import Control.DeepSeq (NFData, rnf)
66import Control.DeepSeq.Generics (genericRnf)
77import GHC.Generics (Generic)
8+import qualified Data.Text as T
89
910
1011data RelationalError = NoSuchAttributeNameError AttributeName
1112 | TupleAttributeCountMismatchError Int --attribute name
1213 | TupleAttributeTypeMismatchError Attributes
1314 | AttributeCountMismatchError Int
14− | AttributeNameMismatchError String
15+ | AttributeNameMismatchError AttributeName
1516 | AttributeNameInUseError AttributeName
1617 | AttributeIsNotRelationValuedError AttributeName
17− | RelVarNotDefinedError String
18− | RelVarAlreadyDefinedError String
18+ | RelVarNotDefinedError RelVarName
19+ | RelVarAlreadyDefinedError RelVarName
1920 | RelVarAssignmentTypeMismatchError
20− | InclusionDependencyCheckError String
21− | ParseError String
22− | PredicateExpressionError String
21+ | InclusionDependencyCheckError IncDepName
22+ | ParseError T.Text
23+ | PredicateExpressionError T.Text
2324 | NoSuchTransactionError U.UUID
2425 | NoSuchHeadNameError HeadName
2526 | TransactionIsNotAHeadError U.UUID
ProjectM36/Relation.hs+4−3
@@ -1,5 +1,5 @@
11-- this is an implementation of the Relation typeclass which creates a GADT DSL
2−{-# LANGUAGE GADTs,ExistentialQuantification,NoImplicitPrelude #-}
2+{-# LANGUAGE GADTs,ExistentialQuantification,NoImplicitPrelude,OverloadedStrings #-}
33module ProjectM36.Relation where
44import qualified Data.Set as S
55import qualified Data.HashSet as HS
@@ -12,6 +12,7 @@ import qualified ProjectM36.Attribute as A
1212import ProjectM36.TupleSet
1313import ProjectM36.Error
1414import Prelude hiding (join)
15+import qualified Data.Text as T
1516
1617attributes :: Relation -> Attributes
1718attributes (Relation attrs _ ) = attrs
@@ -76,7 +77,7 @@ singletonValueFromRelation rel@(Relation _ tupSet) = if cardinality rel /= Count
7677union :: Relation -> Relation -> Either RelationalError Relation
7778union (Relation attrs1 tupSet1) (Relation attrs2 tupSet2) =
7879 if not (attrs1 == attrs2)
79− then Left $ AttributeNameMismatchError (show attrs1 ++ show attrs2)
80+ then Left $ AttributeNameMismatchError (T.pack (show attrs1 ++ show attrs2))
8081 else
8182 Right $ Relation attrs1 newtuples
8283 where
@@ -259,7 +260,7 @@ imageRelationJoin rel1@(Relation attrNameSet1 tupSet1) rel2@(Relation attrNameSe
259260-- this is useful for performance and resource usage testing
260261matrixRelation :: Int -> Int -> Either RelationalError Relation
261262matrixRelation attributeCount tupleCount = do
262− let attrs = A.attributesFromList $ map (\c-> Attribute (show c) IntAtomType) [0 .. attributeCount-1]
263+ let attrs = A.attributesFromList $ map (\c-> Attribute (T.pack $ show c) IntAtomType) [0 .. attributeCount-1]
263264 tuple tupleX = RelationTuple attrs (V.generate attributeCount (\_ -> IntAtom tupleX))
264265 tupleSet = HS.fromList $ map (\c -> tuple c) [0 .. tupleCount]
265266 mkRelation attrs tupleSet
ProjectM36/Relation/Show/HTML.hs+18−15
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12module ProjectM36.Relation.Show.HTML where
23import ProjectM36.Base
34import ProjectM36.Relation
@@ -5,35 +6,37 @@ import ProjectM36.Tuple
56import qualified Data.HashSet as HS
67import qualified Data.List as L
78import ProjectM36.Attribute
9+import Data.Text (append, Text, pack)
10+import qualified Data.Text.IO as TIO
811
9−attributesAsHTML :: Attributes -> String
10−attributesAsHTML attrs = "<tr>" ++ (foldr folder "" attrNameList) ++ "</tr>"
12+attributesAsHTML :: Attributes -> Text
13+attributesAsHTML attrs = "<tr>" `append` (foldr folder "" attrNameList) `append` "</tr>"
1114 where
12− folder attrName acc = acc ++ "<th>" ++ attrName ++ "</th>"
15+ folder attrName acc = acc `append` "<th>" `append` attrName `append` "</th>"
1316 attrNameList = sortedAttributeNameList (attributeNameSet attrs)
1417
15−relationAsHTML :: Relation -> String
16−relationAsHTML rel@(Relation attrNameSet tupleSet) = "<table border=\"1\">" ++ (attributesAsHTML attrNameSet) ++ (tupleSetAsHTML tupleSet) ++ "<tfoot>" ++ tablefooter ++ "</tfoot></table>"
18+relationAsHTML :: Relation -> Text
19+relationAsHTML rel@(Relation attrNameSet tupleSet) = "<table border=\"1\">" `append` (attributesAsHTML attrNameSet) `append` (tupleSetAsHTML tupleSet) `append` "<tfoot>" `append` tablefooter `append` "</tfoot></table>"
1720 where
18− tablefooter = "<tr><td colspan=\"100%\">" ++ show (cardinality rel) ++ " tuples</td></tr>"
21+ tablefooter = "<tr><td colspan=\"100%\">" `append` (pack $ show (cardinality rel)) `append` " tuples</td></tr>"
1922
20−writeHTML :: String -> IO ()
21−writeHTML = writeFile "/home/agentm/rel.html"
23+writeHTML :: Text -> IO ()
24+writeHTML = TIO.writeFile "/home/agentm/rel.html"
2225
2326writeRel :: Relation -> IO ()
2427writeRel = writeHTML . relationAsHTML
2528
26−atomAsHTML :: Atom -> String
29+atomAsHTML :: Atom -> Text
2730atomAsHTML (StringAtom atom) = atom
28−atomAsHTML (IntAtom int) = show int
31+atomAsHTML (IntAtom int) = pack (show int)
2932atomAsHTML (RelationAtom rel) = relationAsHTML rel
3033
31−tupleAsHTML :: RelationTuple -> String
32−tupleAsHTML tuple = "<tr>" ++ L.foldr folder "" (tupleSortedAssocs tuple) ++ "</tr>"
34+tupleAsHTML :: RelationTuple -> Text
35+tupleAsHTML tuple = "<tr>" `append` L.foldr folder "" (tupleSortedAssocs tuple) `append` "</tr>"
3336 where
34− folder tup acc = acc ++ "<td>" ++ (atomAsHTML (snd tup)) ++ "</td>"
37+ folder tup acc = acc `append` "<td>" `append` (atomAsHTML (snd tup)) `append` "</td>"
3538
36−tupleSetAsHTML :: RelationTupleSet -> String
39+tupleSetAsHTML :: RelationTupleSet -> Text
3740tupleSetAsHTML tupSet = HS.foldr folder "" tupSet
3841 where
39− folder tuple acc = acc ++ tupleAsHTML tuple
42+ folder tuple acc = acc `append` tupleAsHTML tuple
ProjectM36/Relation/Show/Term.hs+43−41
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12--writes Relation to a String suitable for terminal output
23module ProjectM36.Relation.Show.Term where
34import ProjectM36.Base
@@ -6,45 +7,46 @@ import ProjectM36.Relation
67import qualified Data.Set as S
78import qualified Data.HashSet as HS
89import qualified Data.List as L
10+import qualified Data.Text as T
911
10−boxV :: String
12+boxV :: StringType
1113boxV = "│"
12−boxH :: String
14+boxH :: StringType
1315boxH = "─"
1416
15−boxTL :: String
17+boxTL :: StringType
1618boxTL = "┌"
17−boxTR :: String
19+boxTR :: StringType
1820boxTR = "┐"
19−boxBL :: String
21+boxBL :: StringType
2022boxBL = "└"
21−boxBR :: String
23+boxBR :: StringType
2224boxBR = "┘"
2325
24−boxLB :: String
26+boxLB :: StringType
2527boxLB = "├"
26−boxRB :: String
28+boxRB :: StringType
2729boxRB = "┤"
28−boxTB :: String
30+boxTB :: StringType
2931boxTB = "┬"
30−boxBB :: String
32+boxBB :: StringType
3133boxBB = "┴"
3234
33−boxC :: String
35+boxC :: StringType
3436boxC = "┼"
3537
36−dboxH :: String
38+dboxH :: StringType
3739dboxH = "═"
38−dboxL :: String
40+dboxL :: StringType
3941dboxL = "╞"
40−dboxR :: String
42+dboxR :: StringType
4143dboxR = "╡"
4244
4345class TermSize a where
4446 termLength :: a -> Int
4547
4648--represent a relation as a table similar to those drawn by Date
47−type Cell = String
49+type Cell = StringType
4850type Table = ([Cell], [[Cell]]) --header, body
4951
5052addRow :: [Cell] -> Table -> Table
@@ -63,14 +65,14 @@ cellLocations tab@(header, _) = (maxWidths, maxHeights)
6365 mergeMax a b = map (\(c,d) -> max c d) (zip a b)
6466
6567--the normal "lines" function returns an empty list for an empty string which is not what we want
66−breakLines :: String -> [String]
68+breakLines :: StringType -> [StringType]
6769breakLines "" = [""]
68−breakLines x = lines x
70+breakLines x = T.lines x
6971
7072cellSizes :: Table -> [([Int], [Int])]
7173cellSizes (header, body) = map (\row -> (map maxRowWidth row, map (length . breakLines) row)) allRows
7274 where
73− maxRowWidth row = L.maximumBy compare (map length (breakLines row))
75+ maxRowWidth row = L.maximumBy compare (map T.length (breakLines row))
7476 allRows = [header] ++ body
7577
7678relationAsTable :: Relation -> Table
@@ -85,53 +87,53 @@ relationAsTable rel@(Relation _ tupleSet) = (header, body)
8587 Right atom -> showAtom atom
8688 ) oAttrs]
8789
88−showAtom :: Atom -> String
90+showAtom :: Atom -> StringType
8991showAtom (StringAtom atom) = atom
90−showAtom (IntAtom atom) = show atom
92+showAtom (IntAtom atom) = T.pack $ show atom
9193showAtom (RelationAtom rel) = renderTable $ relationAsTable rel
9294
93−renderTable :: Table -> String
94−renderTable table = renderHeader table (fst cellLocs) ++ renderBody (snd table) cellLocs
95+renderTable :: Table -> StringType
96+renderTable table = renderHeader table (fst cellLocs) `T.append` renderBody (snd table) cellLocs
9597 where
9698 cellLocs = cellLocations table
9799
98−renderHeader :: Table -> [Int] -> String
99−renderHeader (header, body) columnLocations = renderTopBar ++ renderHeaderNames ++ renderBottomBar
100+renderHeader :: Table -> [Int] -> StringType
101+renderHeader (header, body) columnLocations = renderTopBar `T.append` renderHeaderNames `T.append` renderBottomBar
100102 where
101− renderTopBar = boxTL ++ concat (L.intersperse boxTB (map (\x -> repeatString x boxH) columnLocations)) ++ boxTR ++ "\n"
103+ renderTopBar = boxTL `T.append` T.concat (L.intersperse boxTB (map (\x -> repeatString x boxH) columnLocations)) `T.append` boxTR `T.append` "\n"
102104 renderHeaderNames = renderRow header columnLocations 1 boxV
103105 renderBottomBar = if length body == 0 then ""
104− else renderHBar boxLB boxC boxRB columnLocations ++ "\n"
106+ else renderHBar boxLB boxC boxRB columnLocations `T.append` "\n"
105107
106−renderHBar :: String -> String -> String -> [Int] -> String
107−renderHBar left middle end columnLocations = left ++ concat (L.intersperse middle (map (\x -> repeatString x boxH) columnLocations)) ++ end
108+renderHBar :: StringType -> StringType -> StringType -> [Int] -> StringType
109+renderHBar left middle end columnLocations = left `T.append` T.concat (L.intersperse middle (map (\x -> repeatString x boxH) columnLocations)) `T.append` end
108110
109−leftPaddedString :: Int -> Int -> String -> String
111+leftPaddedString :: Int -> Int -> StringType -> StringType
110112leftPaddedString lineNum size str = paddedLines !! lineNum
111113 where
112− paddedLines = map (\line -> line ++ repeatString (size - length line) " ") (breakLines str ++ repeat "")
114+ paddedLines = map (\line -> line `T.append` repeatString (size - T.length line) " ") (breakLines str)
113115
114−renderRow :: [Cell] -> [Int] -> Int -> String -> String
115−renderRow cells columnLocations rowHeight interspersed = unlines $ map renderOneLine [0..rowHeight-1]
116+renderRow :: [Cell] -> [Int] -> Int -> StringType -> StringType
117+renderRow cells columnLocations rowHeight interspersed = T.unlines $ map renderOneLine [0..rowHeight-1]
116118 where
117− renderOneLine lineNum = boxV ++ concat (L.intersperse interspersed (map (\(size, value) -> leftPaddedString lineNum size value) (zip columnLocations cells))) ++ boxV
119+ renderOneLine lineNum = boxV `T.append` T.concat (L.intersperse interspersed (map (\(size, value) -> leftPaddedString lineNum size value) (zip columnLocations cells))) `T.append` boxV
118120
119−renderBody :: [[Cell]] -> ([Int],[Int]) -> String
120−renderBody cellMatrix cellLocations = renderRows ++ renderBottomBar
121+renderBody :: [[Cell]] -> ([Int],[Int]) -> StringType
122+renderBody cellMatrix cellLocs = renderRows `T.append` renderBottomBar
121123 where
122− columnLocations = fst cellLocations
123− rowLocations = snd cellLocations
124− renderRows = concat (map (\(row, rowHeight)-> renderRow row columnLocations rowHeight boxV) rowHeightMatrix)
124+ columnLocations = fst cellLocs
125+ rowLocations = snd cellLocs
126+ renderRows = T.concat (map (\(row, rowHeight)-> renderRow row columnLocations rowHeight boxV) rowHeightMatrix)
125127 rowHeightMatrix = zip cellMatrix (tail rowLocations)
126128 renderBottomBar = renderHBar boxBL boxBB boxBR columnLocations
127129
128130orderedAttributeNames :: Relation -> [AttributeName]
129131orderedAttributeNames = S.toAscList . attributeNames
130132
131−repeatString :: Int -> String -> String
132−repeatString c s = concat (take c (repeat s))
133+repeatString :: Int -> StringType -> StringType
134+repeatString c s = T.concat (take c (repeat s))
133135
134−showRelation :: Relation -> String
136+showRelation :: Relation -> StringType
135137showRelation rel
136138 | rel == relationTrue = "true"
137139 | rel == relationFalse = "false"
ProjectM36/RelationalExpression.hs+3−2
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12module ProjectM36.RelationalExpression where
23import ProjectM36.Relation
34import ProjectM36.Tuple
@@ -162,7 +163,7 @@ productsRel = case mkRelationFromList attrs matrix of
162163 ]
163164
164165--helper function to process relation variable creation/assignment
165−setRelVar :: String -> Relation -> DatabaseState (Maybe RelationalError)
166+setRelVar :: RelVarName -> Relation -> DatabaseState (Maybe RelationalError)
166167setRelVar relVarName rel = do
167168 currstate <- get
168169 let newRelVars = M.insert relVarName rel $ relationVariables currstate
@@ -173,7 +174,7 @@ setRelVar relVarName rel = do
173174 return Nothing
174175
175176-- it is not an error to delete a relvar which does not exist, just like it is not an error to insert a pre-existing tuple into a relation
176−deleteRelVar :: String -> DatabaseState (Maybe RelationalError)
177+deleteRelVar :: RelVarName -> DatabaseState (Maybe RelationalError)
177178deleteRelVar relVarName = do
178179 currstate <- get
179180 let newRelVars = M.delete relVarName (relationVariables currstate)
ProjectM36/Transaction.hs+3−2
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12module ProjectM36.Transaction where
23import qualified Data.UUID as U
34import ProjectM36.Base
@@ -14,10 +15,10 @@ bootstrapTransactionGraph freshUUID context = TransactionGraph bootstrapHeads bo
1415 freshTransaction = Transaction freshUUID (TransactionInfo U.nil S.empty) context
1516 bootstrapTransactions = S.singleton freshTransaction
1617
17−transactionForHead :: String -> TransactionGraph -> Maybe Transaction
18+transactionForHead :: HeadName -> TransactionGraph -> Maybe Transaction
1819transactionForHead headName (TransactionGraph heads _) = M.lookup headName heads
1920
20−headNameForTransaction :: Transaction -> TransactionGraph -> Maybe String
21+headNameForTransaction :: Transaction -> TransactionGraph -> Maybe HeadName
2122headNameForTransaction transaction (TransactionGraph heads _) = if M.null matchingTrans then
2223 Nothing
2324 else
ProjectM36/Transaction/Show.hs+4−2
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12module ProjectM36.Transaction.Show where
23import ProjectM36.Base
34import ProjectM36.Relation
@@ -9,6 +10,7 @@ import qualified ProjectM36.Attribute as A
910import qualified Data.HashSet as HS
1011import qualified Data.Set as S
1112import qualified Data.Vector as V
13+import qualified Data.Text as T
1214
1315showTransactionStructure :: Transaction -> TransactionGraph -> String
1416showTransactionStructure trans graph = headInfo ++ " " ++ show (transactionUUID trans) ++ " " ++ parentTransactionsInfo
@@ -37,7 +39,7 @@ graphAsRelation (DisconnectedTransaction parentUUID _) graph@(TransactionGraph _
3739 parentAttributes = A.attributesFromList [Attribute "id" StringAtomType]
3840 tupleGenerator transaction = case transactionParentsRelation transaction graph of
3941 Left err -> Left err
40− Right parentTransRel -> Right [StringAtom $ show (transactionUUID transaction),
42+ Right parentTransRel -> Right [StringAtom $ T.pack $ show (transactionUUID transaction),
4143 RelationAtom parentTransRel,
4244 IntAtom $ if parentUUID == transactionUUID transaction then 1 else 0,
4345 StringAtom $ case headNameForTransaction transaction graph of
@@ -55,7 +57,7 @@ transactionParentsRelation trans graph = do
5557 mkRelation attrs tupleSet
5658 where
5759 attrs = A.attributesFromList [Attribute "id" StringAtomType]
58− trans2tuple trans2 = mkRelationTuple attrs $ V.singleton (StringAtom (show $ transactionUUID trans2))
60+ trans2tuple trans2 = mkRelationTuple attrs $ V.singleton (StringAtom (T.pack (show $ transactionUUID trans2)))
5961
6062
6163
ProjectM36/TupleSet.hs+2−1
@@ -19,7 +19,8 @@ singletonTupleSet = HS.singleton emptyTuple
1919verifyTupleSet :: Attributes -> RelationTupleSet -> Either RelationalError RelationTupleSet
2020verifyTupleSet attrs tupleSet = do
2121 --check that all tuples have the same attributes and that the atom types match
22− let tupleList = (map (verifyTuple attrs) (HS.toList tupleSet)) `P.using` P.parListChunk (100000 `div` 24) P.rdeepseq
22+ let tupleList = (map (verifyTuple attrs) (HS.toList tupleSet)) `P.using` P.parListChunk chunkSize P.rdeepseq
23+ chunkSize = HS.size tupleSet `div` 24
2324 --let tupleList = P.parMap P.rdeepseq (verifyTuple attrs) (HS.toList tupleSet)
2425 if length (lefts tupleList) > 0 then
2526 Left $ head (lefts tupleList)
TutorialD/Interpreter.hs+50−45
@@ -1,4 +1,4 @@
1−{-# LANGUAGE GADTs #-}
1+{-# LANGUAGE GADTs,OverloadedStrings #-}
22module TutorialD.Interpreter where
33import ProjectM36.Base
44import ProjectM36.Relation
@@ -29,6 +29,8 @@ import System.Directory (getHomeDirectory)
2929import qualified Data.UUID as U
3030import Data.UUID.V4 (nextRandom)
3131import qualified Data.Vector as V
32+import qualified Data.Text as T
33+import qualified Data.Text.IO as TIO
3234
3335{-
3436List of Tutorial D operators:
@@ -70,7 +72,9 @@ uuidP = do
7072
7173--used in projection
7274attributeList :: Parser [AttributeName]
73−attributeList = sepBy identifier comma
75+attributeList = do
76+ attrs <- sepBy identifier comma
77+ return $ map T.pack attrs
7478
7579makeRelation :: Parser RelationalExpr
7680makeRelation = do
@@ -94,7 +98,7 @@ attributeAndType = do
9498 attrTypeName <- identifier
9599 --convert type name into type
96100 case tutDTypeToAtomType attrTypeName of
97− Just t -> return $ Attribute attrName t
101+ Just t -> return $ Attribute (T.pack attrName) t
98102 Nothing -> fail (attrTypeName ++ " is not a valid type name.")
99103
100104tupleP :: Parser RelationTuple
@@ -113,7 +117,7 @@ tupleAtomP = do
113117 case tutDTypeToAtomType attrType of
114118 Nothing -> fail (attrType ++ " is not a valid type name.")
115119 Just typeA -> if typeA == atomTypeForAtom atom then
116− return $ (attributeName, atom)
120+ return $ (T.pack attributeName, atom)
117121 else
118122 fail "type mismatch in tuple generation"
119123
@@ -132,7 +136,7 @@ atomTypeToTutDType atomType = case atomType of
132136 _ -> Nothing
133137
134138relVarP :: Parser RelationalExpr
135−relVarP = liftA RelationVariable identifier
139+relVarP = liftA (RelationVariable . T.pack) identifier
136140
137141relTerm = parens relExpr
138142 <|> makeRelation
@@ -149,7 +153,7 @@ assignP = do
149153 reservedOp ":="
150154 return relVarName
151155 expr <- relExpr
152− return $ Assign relVarName expr
156+ return $ Assign (T.pack relVarName) expr
153157
154158renameClause = do
155159 oldAttr <- identifier
@@ -161,7 +165,7 @@ renameP :: Parser (RelationalExpr -> RelationalExpr)
161165renameP = do
162166 reservedOp "rename"
163167 (oldAttr, newAttr) <- braces renameClause
164− return $ Rename oldAttr newAttr
168+ return $ Rename (T.pack oldAttr) (T.pack newAttr)
165169
166170whereClauseP = do
167171 reservedOp "where"
@@ -178,14 +182,14 @@ groupP :: Parser (RelationalExpr -> RelationalExpr)
178182groupP = do
179183 reservedOp "group"
180184 (groupAttrList, groupAttrName) <- parens groupClause
181− return $ Group (S.fromList groupAttrList) groupAttrName
185+ return $ Group (S.fromList groupAttrList) (T.pack groupAttrName)
182186
183187--in "Time and Relational Theory" (2014), Date's Tutorial D grammar for ungroup takes one attribute, while in previous books, it take multiple arguments. Let us assume that nested ungroups are the same as multiple attributes.
184188ungroupP :: Parser (RelationalExpr -> RelationalExpr)
185189ungroupP = do
186190 reservedOp "ungroup"
187191 rvaAttrName <- identifier
188− return $ Ungroup rvaAttrName
192+ return $ Ungroup (T.pack rvaAttrName)
189193
190194relOperators = [
191195 [Postfix projectOp],
@@ -220,7 +224,7 @@ insertP = do
220224 reservedOp "insert"
221225 relvar <- identifier
222226 expr <- relExpr
223− return $ Insert relvar expr
227+ return $ Insert (T.pack relvar) expr
224228
225229defineP :: Parser DatabaseExpr
226230defineP = do
@@ -229,20 +233,20 @@ defineP = do
229233 reservedOp "::"
230234 return relVarName
231235 attributeSet <- makeAttributes
232− return $ Define relVarName attributeSet
236+ return $ Define (T.pack relVarName) attributeSet
233237
234238undefineP :: Parser DatabaseExpr
235239undefineP = do
236240 reservedOp "undefine"
237241 relVarName <- identifier
238− return $ Undefine relVarName
242+ return $ Undefine (T.pack relVarName)
239243
240244deleteP :: Parser DatabaseExpr
241245deleteP = do
242246 reservedOp "delete"
243247 relVarName <- identifier
244248 predicate <- option TruePredicate (reservedOp "where" *> restrictionPredicateP)
245− return $ Delete relVarName predicate
249+ return $ Delete (T.pack relVarName) predicate
246250
247251updateP :: Parser DatabaseExpr
248252updateP = do
@@ -250,7 +254,7 @@ updateP = do
250254 relVarName <- identifier
251255 predicate <- option TruePredicate (reservedOp "where" *> restrictionPredicateP <* spaces)
252256 attributeAssignments <- liftM M.fromList $ parens (sepBy attributeAssignment comma)
253− return $ Update relVarName attributeAssignments predicate
257+ return $ Update (T.pack relVarName) (M.mapKeys T.pack $ attributeAssignments) predicate
254258
255259constraintP :: Parser DatabaseExpr
256260constraintP = do
@@ -259,7 +263,7 @@ constraintP = do
259263 subset <- relExpr
260264 reservedOp "in"
261265 superset <- relExpr
262− return $ AddInclusionDependency (InclusionDependency constraintName subset superset)
266+ return $ AddInclusionDependency (InclusionDependency (T.pack constraintName) subset superset)
263267
264268attributeAssignment :: Parser (String, Atom)
265269attributeAssignment = do
@@ -270,21 +274,21 @@ attributeAssignment = do
270274
271275parseString :: String -> Either RelationalError DatabaseExpr
272276parseString str = case parse (multipleDatabaseExpr <* eof) "" str of
273− Left err -> Left $ ParseError (show err)
277+ Left err -> Left $ ParseError (T.pack (show err))
274278 Right r -> Right r
275279
276280--operators which only rely on database context reading
277281data ContextOperator where
278282 ShowRelation :: RelationalExpr -> ContextOperator
279283 ShowRelationType :: RelationalExpr -> ContextOperator
280− ShowConstraint :: String -> ContextOperator
284+ ShowConstraint :: StringType -> ContextOperator
281285 ShowPlan :: DatabaseExpr -> ContextOperator
282286 Quit :: ContextOperator
283287 deriving (Show)
284288
285289--operators which manipulate a transaction graph
286290data GraphOperator where
287− JumpToHead :: String -> GraphOperator
291+ JumpToHead :: HeadName -> GraphOperator
288292 JumpToTransaction :: U.UUID -> GraphOperator
289293 Branch :: HeadName -> GraphOperator
290294 Commit :: GraphOperator
@@ -318,13 +322,13 @@ showConstraintsP :: Parser ContextOperator
318322showConstraintsP = do
319323 reservedOp ":constraints"
320324 constraintName <- option "" identifier
321− return $ ShowConstraint constraintName
325+ return $ ShowConstraint (T.pack constraintName)
322326
323327jumpToHeadP :: Parser GraphOperator
324328jumpToHeadP = do
325329 reservedOp ":jumphead"
326330 headid <- identifier
327− return $ JumpToHead headid
331+ return $ JumpToHead (T.pack headid)
328332
329333jumpToTransactionP :: Parser GraphOperator
330334jumpToTransactionP = do
@@ -336,7 +340,7 @@ branchTransactionP :: Parser GraphOperator
336340branchTransactionP = do
337341 reservedOp ":branch"
338342 branchName <- identifier
339− return $ Branch branchName
343+ return $ Branch (T.pack branchName)
340344
341345commitTransactionP :: Parser GraphOperator
342346commitTransactionP = do
@@ -372,32 +376,32 @@ contextOps = typeP
372376interpreterOps :: Parser (Either ContextOperator GraphOperator)
373377interpreterOps = liftM Left contextOps <|> liftM Right transactionGraphOps
374378
375−showRelationAttributes :: Relation -> String
376−showRelationAttributes rel = "{" ++ concat (L.intersperse ", " $ map showAttribute attrs) ++ "}"
379+showRelationAttributes :: Relation -> T.Text
380+showRelationAttributes rel = "{" `T.append` T.concat (L.intersperse ", " $ map showAttribute attrs) `T.append` "}"
377381 where
378− showAttribute (Attribute name atomType) = name ++ " " ++ case atomTypeToTutDType atomType of
379− Just t -> show t
380− Nothing -> "unknown"
382+ showAttribute (Attribute name atomType) = name `T.append` " " `T.append` case atomTypeToTutDType atomType of
383+ Just t -> T.pack (show t)
384+ Nothing -> T.pack "unknown"
381385 attrs = V.toList $ attributes rel
382386
383387data TutorialDOperatorResult = QuitResult |
384− DisplayResult String |
385− DisplayErrorResult String |
388+ DisplayResult StringType |
389+ DisplayErrorResult StringType |
386390 QuietSuccessResult |
387391 NoActionResult --refactor to make this dead- there should be only one parser
388392
389393evalContextOp :: DatabaseContext -> ContextOperator -> TutorialDOperatorResult
390394evalContextOp context (ShowRelationType expr) = case runState (typeForRelationalExpr expr) context of
391395 (Right rel, _) -> DisplayResult $ showRelationAttributes rel
392− (Left err, _) -> DisplayErrorResult $ show err
396+ (Left err, _) -> DisplayErrorResult $ T.pack (show err)
393397
394398evalContextOp context (ShowRelation expr) = do
395399 case runState (evalRelationalExpr expr) context of
396− (Left err, _) -> DisplayErrorResult $ show err
400+ (Left err, _) -> DisplayErrorResult $ T.pack (show err)
397401 (Right rel, _) -> DisplayResult $ showRelation rel
398402
399403evalContextOp context (ShowConstraint name) = do
400− DisplayResult $ show filteredDeps
404+ DisplayResult $ T.pack (show filteredDeps)
401405 where
402406 deps = inclusionDependencies context
403407 filteredDeps = case name of
@@ -405,7 +409,7 @@ evalContextOp context (ShowConstraint name) = do
405409 name2 -> HS.filter (\(InclusionDependency n _ _) -> n == name2) deps
406410
407411evalContextOp context (ShowPlan dbExpr) = do
408− DisplayResult $ show plan
412+ DisplayResult $ T.pack (show plan)
409413 where
410414 plan = evalState (applyStaticDatabaseOptimization dbExpr) context
411415
@@ -500,20 +504,20 @@ interpretNO context tutdstring = case parseString tutdstring of
500504-- for interpreter-specific operations
501505interpretOps :: U.UUID -> DisconnectedTransaction -> TransactionGraph -> String -> (DisconnectedTransaction, TransactionGraph, TutorialDOperatorResult)
502506interpretOps newUUID trans@(DisconnectedTransaction _ context) transGraph instring = case parse interpreterOps "" instring of
503− Left err -> (trans, transGraph, NoActionResult)
507+ Left _ -> (trans, transGraph, NoActionResult)
504508 Right ops -> case ops of
505509 Left contextOp -> (trans, transGraph, (evalContextOp context contextOp))
506510 Right graphOp -> case evalGraphOp newUUID trans transGraph graphOp of
507− Left err -> (trans, transGraph, DisplayErrorResult $ show err)
511+ Left err -> (trans, transGraph, DisplayErrorResult $ T.pack (show err))
508512 Right (newDiscon, newGraph, result) -> (newDiscon, newGraph, result)
509513
510−promptText :: DisconnectedTransaction -> TransactionGraph -> String
511−promptText (DisconnectedTransaction parentUUID _) graph = "TutorialD (" ++ transInfo ++ "): "
514+promptText :: DisconnectedTransaction -> TransactionGraph -> StringType
515+promptText (DisconnectedTransaction parentUUID _) graph = "TutorialD (" `T.append` transInfo `T.append` "): "
512516 where
513517 transInfo = case transactionForUUID parentUUID graph of
514518 Left _ -> "unknown"
515519 Right parentTrans -> case headNameForTransaction parentTrans graph of
516− Nothing -> show $ transactionUUID parentTrans
520+ Nothing -> T.pack (show $ transactionUUID parentTrans)
517521 Just headName -> headName
518522
519523reprLoop :: DisconnectedTransaction -> TransactionGraph -> IO ()
@@ -521,7 +525,7 @@ reprLoop currentTransaction@(DisconnectedTransaction currentParentUUID currentCo
521525 homeDirectory <- getHomeDirectory
522526 let settings = defaultSettings {historyFile = Just (homeDirectory ++ "/.tutd_history")}
523527
524− maybeLine <- runInputT settings $ getInputLine (promptText currentTransaction graph)
528+ maybeLine <- runInputT settings $ getInputLine (T.unpack (promptText currentTransaction graph))
525529
526530 let roloop = reprLoop currentTransaction graph
527531 case maybeLine of
@@ -530,12 +534,12 @@ reprLoop currentTransaction@(DisconnectedTransaction currentParentUUID currentCo
530534 newUUID <- nextRandom
531535 case interpretOps newUUID currentTransaction graph line of
532536 (_, _, QuitResult) -> return ()
533− (_, _, DisplayErrorResult err) -> hPutStrLn stderr ("ERR: " ++ err) >> roloop
537+ (_, _, DisplayErrorResult err) -> TIO.hPutStrLn stderr ("ERR: " `T.append` err) >> roloop
534538 (updatedTrans, updatedGraph, DisplayResult out) -> do
535− putStrLn out
539+ TIO.putStrLn out
536540 reprLoop updatedTrans updatedGraph
537541 (updatedTrans, updatedGraph, QuietSuccessResult) -> do
538− putStrLn "Done."
542+ TIO.putStrLn "Done."
539543 reprLoop updatedTrans updatedGraph
540544 (_, _, NoActionResult) -> do
541545 let (value, contextup) = interpret currentContext line
@@ -543,7 +547,7 @@ reprLoop currentTransaction@(DisconnectedTransaction currentParentUUID currentCo
543547 case value of
544548 Nothing -> reprLoop updatedTransaction graph
545549 Just err -> do
546− hPutStrLn stderr ("ERR:" ++ show err)
550+ TIO.hPutStrLn stderr ("ERR:" `T.append` T.pack (show err))
547551 reprLoop currentTransaction graph
548552
549553restrictionPredicateP :: Parser RestrictionPredicateExpr
@@ -569,18 +573,19 @@ restrictionAttributeEqualityP = do
569573 attributeName <- identifier
570574 reservedOp "="
571575 atom <- stringAtomP <|> intAtomP
572− return $ AttributeEqualityPredicate attributeName atom
576+ return $ AttributeEqualityPredicate (T.pack attributeName) atom
573577
574578quotedChar = noneOf "\""
575579 <|> try (string "\"\"" >> return '"')
576580
577−stringAtomP = liftA StringAtom (string "\"" *> many quotedChar <* string "\"")
581+stringAtomP = liftA (StringAtom . T.pack) (string "\"" *> many quotedChar <* string "\"")
578582
579583intAtomP = do
580584 intstr <- many digit
581585 return $ IntAtom (read intstr)
582586
583587--used by :dumpGraph
588+{-
584589displayTransactionGraph :: TransactionGraph -> String
585590displayTransactionGraph (TransactionGraph _ transSet) = L.intercalate "\n" $ S.foldr (\(Transaction tUUID pUUID _ ) acc -> acc ++ [show tUUID ++ " " ++ show pUUID]) [] transSet
586−
591+-}
TutorialD/tutd.hs+1
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12import TutorialD.Interpreter
23import ProjectM36.RelationalExpression
34import ProjectM36.Transaction
benchmark/bigrel.hs+26−10
@@ -1,37 +1,52 @@
1−{-# LANGUAGE FlexibleInstances #-}
1+{-# LANGUAGE FlexibleInstances,OverloadedStrings #-}
22import ProjectM36.Base
33import ProjectM36.Relation
44import ProjectM36.Tuple
5−import ProjectM36.Error
65import ProjectM36.Relation.Show.CSV
7−import qualified Data.Map as M
86import qualified Data.HashSet as HS
97import qualified Data.ByteString.Lazy.Char8 as BS
108import qualified Data.IntMap as IM
119import qualified Data.Hashable as Hash
1210import qualified Data.Vector as V
13−import Control.DeepSeq
11+import Options.Applicative
1412
1513dumpcsv :: Relation -> IO ()
1614dumpcsv = BS.putStrLn . relationAsCSV
1715
18−main = matrixRun
19− --vectorMatrixRun
20− --intmapMatrixRun
16+parseAttributeCount :: Parser Int
17+parseAttributeCount = option auto (short 'a' <> long "attribute-count")
18+
19+parseTupleCount :: Parser Int
20+parseTupleCount = option auto (short 't' <> long "tuple-count")
21+
22+parseArgs :: Parser (Int, Int)
23+parseArgs = (,) <$> parseAttributeCount <*> parseTupleCount
24+
25+
26+main :: IO ()
27+main = do
28+ (attributeCount, tupleCount) <- execParser $ info (helper <*> parseArgs) fullDesc
29+ --matrixRestrictRun
30+ matrixRun attributeCount tupleCount
31+ --vectorMatrixRun
32+ --intmapMatrixRun
2133
2234-- takes 30 minutes to run and 1.1 GB
35+matrixRestrictRun :: IO ()
2336matrixRestrictRun = do
24− case matrixRelation 100 100000 of
37+ case matrixRelation 100 1000000 of
2538 Left err -> putStrLn (show err)
2639 Right rel -> case restrict (\tuple -> atomForAttributeName "0" tuple == Right (IntAtom 5)) rel of
2740 Left err -> putStrLn (show err)
2841 Right rel -> dumpcsv rel
2942
30−matrixRun = do
31− case matrixRelation 100 100000 of
43+matrixRun :: Int -> Int -> IO ()
44+matrixRun attributeCount tupleCount= do
45+ case matrixRelation attributeCount tupleCount of
3246 Left err -> putStrLn (show err)
3347 Right rel -> putStrLn "Done"
3448
49+intmapMatrixRun :: IO ()
3550intmapMatrixRun = do
3651 let matrix = intmapMatrixRelation 100 100000
3752 putStrLn (show matrix)
@@ -46,6 +61,7 @@ intmapMatrixRelation attributeCount tupleCount = HS.fromList $ map mapper [0..tu
4661instance Hash.Hashable (IM.IntMap Atom) where
4762 hashWithSalt salt tupMap = Hash.hashWithSalt salt (show tupMap)
4863
64+vectorMatrixRun :: IO ()
4965vectorMatrixRun = do
5066 let matrix = vectorMatrixRelation 100 100000
5167 putStrLn (show matrix)
project-m36.cabal+2−2
@@ -33,7 +33,7 @@ Executable tutd
3333 GHC-Options: -Wall
3434
3535Executable bigrel
36− Build-Depends: base,deepseq
36+ Build-Depends: base,deepseq,optparse-applicative
3737 Other-Modules: ProjectM36.Base,
3838 ProjectM36.Relation
3939 ProjectM36.Tuple,
@@ -41,7 +41,7 @@ Executable bigrel
4141 ProjectM36.Relation.Show.CSV
4242 main-is: benchmark/bigrel.hs
4343 GHC-Options: -Wall -threaded -rtsopts
44− GHC-Prof-Options: -fprof-auto "-with-rtsopts -p -s -h -i0.1"
44+ GHC-Prof-Options: -fprof-auto -rtsopts -threaded -Wall
4545
4646Test-Suite test-tutoriald
4747 type: exitcode-stdio-1.0
test/Relation/Basic.hs+2−1
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12import Test.HUnit
23import ProjectM36.Base
34import ProjectM36.Relation
@@ -70,7 +71,7 @@ testRename2 = TestCase $ assertEqual "attribute in use" (rename "b" "a" simpleRe
7071--mkRelation tests
7172--test tupleset key mismatch failure
7273testMkRelation1 :: Test
73−testMkRelation1 = TestCase $ assertEqual "key mismatch" (Left $ TupleAttributeTypeMismatchError (A.attributesFromList [Attribute "a" StringAtomType])) (mkRelation testAttrs testTupSet)
74+testMkRelation1 = TestCase $ assertEqual "key mismatch" (Left $ TupleAttributeTypeMismatchError A.emptyAttributes) (mkRelation testAttrs testTupSet) -- the error attribute set is empty due to an optimization- the tuple attrs do not match the atoms' types
7475 where
7576 testAttrs = A.attributesFromList [Attribute "a" StringAtomType]
7677 testTupSet = HS.fromList [mkRelationTuple testAttrs $ V.fromList [StringAtom "v"],
test/Relation/StaticOptimizer.hs+1
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12import ProjectM36.Base
23import ProjectM36.Relation
34import ProjectM36.RelationalExpression
test/TutorialD/Interpreter.hs+1
@@ -1,3 +1,4 @@
1+{-# LANGUAGE OverloadedStrings #-}
12import TutorialD.Interpreter
23import Test.HUnit
34import ProjectM36.RelationalExpression