Fixed subtyping

This commit is contained in:
Macocian Adrian Radu
2022-03-25 01:42:56 +01:00
parent a07fe3e67b
commit f18066e5da
11 changed files with 144 additions and 76 deletions

View File

@@ -114,7 +114,7 @@ addNewTypes defined (TypeObject o: os) =
case addNewTypes defined os of case addNewTypes defined os of
Left errors -> Left errors Left errors -> Left errors
Right types -> addDefinedTypes types [o] Right types -> addDefinedTypes types [o]
addNewTypes defined (EnumObject (MakeEnum name _ _): os) = addNewTypes defined (TypeObject (MakeType name (BasicType "Object") Nothing []) : os) addNewTypes defined (EnumObject (MakeEnum name _ _): os) = addNewTypes defined (TypeObject (MakeType name (BasicType "Object") Nothing [] []) : os)
addNewTypes defined (_ :os) = addNewTypes defined os addNewTypes defined (_ :os) = addNewTypes defined os
-- |Parses any supported Rosetta types into a list of RosettaObject -- |Parses any supported Rosetta types into a list of RosettaObject

View File

@@ -14,6 +14,8 @@ type TestZeroOneType extends Period:
type ObservationPrimitive: type ObservationPrimitive:
observationPrimitive int (1..1) observationPrimitive int (1..1)
condition important: <"This is an important condition">
observationPrimitive < 0
func EquityPriceObservation: <"Function specification for the observation of an equity price, based on the attributes of the 'EquityValuation' class."> func EquityPriceObservation: <"Function specification for the observation of an equity price, based on the attributes of the 'EquityValuation' class.">
inputs: inputs:
@@ -21,7 +23,6 @@ func EquityPriceObservation: <"Function specification for the observation of an
valuationDate ObservationPrimitive (0..1) valuationDate ObservationPrimitive (0..1)
valuationTime int (0..1) valuationTime int (0..1)
timeType TestType (0..1) timeType TestType (0..1)
determinationMethod ObservationPrimitive (1..1)
output: output:
observation ObservationPrimitive (0..1) observation ObservationPrimitive (0..1)
@@ -38,6 +39,8 @@ func Something: <"asd">
func SomethingElse: <"dsa"> func SomethingElse: <"dsa">
inputs: inputs:
num1 int (1..1)
num2 int (0..1)
valuationTime ObservationPrimitive (1..1) valuationTime ObservationPrimitive (1..1)
output: output:
valuation ObservationPrimitive (0..1) valuation ObservationPrimitive (0..1)

View File

@@ -0,0 +1,36 @@
namespace test.all : <"Something">
version "${version.ok}"
type ObservationPrimitive:
observationPrimitive int (1..1)
condition important: <"This is an important condition">
observationPrimitive < 0
func UsingFunctions: <"This function will use the other functions">
inputs:
val ObservationPrimitive (1..1)
bol boolean (1..1)
output:
valuation ObservationPrimitive(0..*)
assign-output: if bol then Something (bol, val) else SomethingElse (1, 2, val)
func Something: <"asd">
inputs:
equity1 boolean (1..1)
valuationTime ObservationPrimitive (1..1)
output:
valuation ObservationPrimitive (0..*)
assign-output: if True and False then valuationTime
func SomethingElse: <"dsa">
inputs:
num1 int (1..1)
num2 int (0..1)
valuationTime ObservationPrimitive (1..1)
output:
valuation ObservationPrimitive (0..1)
assign-output: if True and False then valuationTime

View File

@@ -1,6 +1,6 @@
module Model.Function where module Model.Function where
import Model.Type (TypeAttribute) import Model.Type (TypeAttribute, Expression)
-- |The representation of a Rosetta function type -- |The representation of a Rosetta function type
data Function = data Function =
@@ -11,20 +11,4 @@ data Function =
outputParameter :: TypeAttribute, outputParameter :: TypeAttribute,
assignment :: Expression assignment :: Expression
} }
deriving (Show) deriving (Show)
-- |The representation of an expression
data Expression = Variable String
| Int String
| Real String
| Boolean String
| Empty
| Parens Expression
| List [Expression]
| Function String [Expression]
| PrefixExp String Expression
| PostfixExp String Expression
| InfixExp String Expression Expression
| IfSimple Expression Expression
| IfElse Expression Expression Expression
deriving (Eq, Show)

View File

@@ -5,7 +5,8 @@ data Type = MakeType {
typeName :: String, typeName :: String,
superType :: Type, superType :: Type,
typeDescription :: Maybe String, typeDescription :: Maybe String,
typeAttributes :: [TypeAttribute] typeAttributes :: [TypeAttribute],
conditions :: [Condition]
} }
| BasicType { | BasicType {
typeName :: String typeName :: String
@@ -13,7 +14,7 @@ data Type = MakeType {
deriving (Show) deriving (Show)
instance Eq Type where instance Eq Type where
(==) (MakeType name _ _ _) (MakeType name2 _ _ _) (==) (MakeType name _ _ _ _) (MakeType name2 _ _ _ _)
| name == name2 = True | name == name2 = True
| otherwise = False | otherwise = False
(==) (BasicType name) (BasicType name2) (==) (BasicType name) (BasicType name2)
@@ -21,6 +22,27 @@ instance Eq Type where
| otherwise = False | otherwise = False
(==) _ _ = False (==) _ _ = False
data Condition = MakeCondition {
conditionName :: String,
conditionDescription :: Maybe String,
expressionExpression :: Expression
} deriving (Show)
-- |The representation of an expression
data Expression = Variable String
| Int String
| Real String
| Boolean String
| Empty
| Parens Expression
| List [Expression]
| Function String [Expression]
| PrefixExp String Expression
| PostfixExp String Expression
| InfixExp String Expression Expression
| IfSimple Expression Expression
| IfElse Expression Expression Expression
deriving (Eq, Show)
-- |The representation of an attribute of a data type -- |The representation of an attribute of a data type
data TypeAttribute = MakeTypeAttribute { data TypeAttribute = MakeTypeAttribute {
@@ -81,10 +103,13 @@ typeAndCardinality (MakeTypeAttribute _ typ crd _) = (typ, crd)
-- |Checks whether the first argument is a subtype of the second argument -- |Checks whether the first argument is a subtype of the second argument
isSubType :: Type -> Type -> Bool isSubType :: Type -> Type -> Bool
isSubType (BasicType "Integer") (BasicType "Double") = True isSubType (BasicType "Integer") (BasicType "Double") = True
isSubType _ (BasicType "Any") = True isSubType _ (BasicType "Object") = True
isSubType _ (BasicType "Object") = False isSubType _ (BasicType "Any") = False
isSubType (BasicType x) y
| x == typeName y = True
| otherwise = False
isSubType x y isSubType x y
| x == y = True | typeName x == typeName y = True
| otherwise = isSubType (superType x) y | otherwise = isSubType (superType x) y
-- |Checks whether the first cardinality is included into the second one -- |Checks whether the first cardinality is included into the second one
@@ -100,4 +125,11 @@ cardinalityIncluded (Bounds (x1, _)) (OneBound y)
cardinalityIncluded (OneBound _) (Bounds (_, _)) = False cardinalityIncluded (OneBound _) (Bounds (_, _)) = False
cardinalityIncluded (Bounds (x1, x2)) (Bounds (y1, y2)) cardinalityIncluded (Bounds (x1, x2)) (Bounds (y1, y2))
| x1 >= y1 && x2 <= y2 = True | x1 >= y1 && x2 <= y2 = True
| otherwise = False | otherwise = False
toHaskell :: Type -> Type
toHaskell a
| typeName a == "int" = BasicType "Integer"
| typeName a == "boolean" = BasicType "Boolean"
| typeName a == "real" = BasicType "Double"
| otherwise = a

View File

@@ -4,6 +4,7 @@ module Parser.Expression where
import Parser.General import Parser.General
import Model.Function import Model.Function
import Model.Type (Expression (..))
import qualified Data.Text as Text import qualified Data.Text as Text
import Text.Megaparsec import Text.Megaparsec
import Text.Megaparsec.Char import Text.Megaparsec.Char

View File

@@ -52,5 +52,5 @@ attributeParser =
typ <- try (pascalNameParser <|> camelNameParser) typ <- try (pascalNameParser <|> camelNameParser)
crd <- cardinalityParser crd <- cardinalityParser
desc <- optional descriptionParser desc <- optional descriptionParser
return $ MakeTypeAttribute nam (MakeType typ (BasicType "Object") Nothing []) crd desc return $ MakeTypeAttribute nam (MakeType typ (BasicType "Object") Nothing [] []) crd desc

View File

@@ -7,25 +7,30 @@ import Text.Megaparsec.Char
import Text.Megaparsec import Text.Megaparsec
import Data.Maybe import Data.Maybe
import Parser.General import Parser.General
import Parser.Expression (expressionParser)
-- |Parses a type declaration statement in Rosetta into an Type -- |Parses a type declaration statement in Rosetta into an Type
typeParser :: Parser Type typeParser :: Parser Type
typeParser = typeParser =
do do
tName <- try typeNameParser tName <- try typeNameParser
tSuper <- optional superTypeParser tSuper <- superTypeParser
_ <- lexeme $ char ':' _ <- lexeme $ char ':'
tDescription <- optional descriptionParser tDescription <- optional descriptionParser
tAttributes <- many $ try typeAttributeParser tAttributes <- many $ try typeAttributeParser
if isJust tSuper then return (MakeType tName (fromJust tSuper) tDescription tAttributes) else return (MakeType tName (BasicType "Object") tDescription tAttributes) tConditions <- many $ try conditionParser
return (MakeType tName tSuper tDescription tAttributes tConditions)
-- |Parses the super class declaration statement in Rosetta into an Type -- |Parses the super class declaration statement in Rosetta into an Type
superTypeParser :: Parser Type superTypeParser :: Parser Type
superTypeParser = superTypeParser =
do do
_ <- lexeme $ string "extends" exists <- lexeme $ optional $ string "extends"
name <- pascalNameParser case exists of
return $ MakeType name (BasicType "Object") Nothing [] Nothing -> return $ BasicType "Object"
Just _ -> do
name <- pascalNameParser
return $ MakeType name (BasicType "Object") Nothing [] []
-- |Parses a declared type attribute in Rosetta into a TypeAttribute -- |Parses a declared type attribute in Rosetta into a TypeAttribute
typeAttributeParser :: Parser TypeAttribute typeAttributeParser :: Parser TypeAttribute
@@ -35,13 +40,20 @@ typeAttributeParser =
aType <- try nameParser aType <- try nameParser
card <- cardinalityParser card <- cardinalityParser
desc <- optional descriptionParser desc <- optional descriptionParser
return (MakeTypeAttribute aName (MakeType aType (BasicType "Object") Nothing []) card desc) return (MakeTypeAttribute aName (MakeType aType (BasicType "Object") Nothing [] []) card desc)
-- |Parses the cardinality of a type attribute in Rosetta into a Cardinality -- |Parses the cardinality of a type attribute in Rosetta into a Cardinality
cardinalityParser :: Parser Cardinality cardinalityParser :: Parser Cardinality
cardinalityParser = cardinalityParser = try parseBounded <|> try parseSemiBounded <|> try parseUnbounded
do
try parseBounded <|> try parseSemiBounded <|> try parseUnbounded -- |Parser the condition of a type attribute in Rosetta into a Condition
conditionParser :: Parser Condition
conditionParser = do
_ <- lexeme $ string "condition"
name <- lexeme camelNameParser
_ <- lexeme $ char ':'
description <- optional descriptionParser
MakeCondition name description <$> expressionParser
-- |Parses a bounded cardinality statement in Rosetta into a Cardinality -- |Parses a bounded cardinality statement in Rosetta into a Cardinality
parseBounded :: Parser Cardinality parseBounded :: Parser Cardinality

View File

@@ -9,15 +9,15 @@ import Utils.Utils
-- |Converts an EnumType into a haskell valid String -- |Converts an EnumType into a haskell valid String
printType :: Type -> String printType :: Type -> String
printType (MakeType name (MakeType super _ _ _) description attributes) = printType (MakeType name (BasicType "Object") description (superToAttribute name super:attributes)) printType (MakeType name (MakeType super _ _ _ _) description attributes conditions) = printType (MakeType name (BasicType "Object") description (superToAttribute super:attributes) conditions)
printType (MakeType name (BasicType "Object") description attributes) = printType (MakeType name (BasicType "Object") description attributes conditions) =
show $ printDescription description (vcat [nest 4 $ vcat ("data" <+> pretty name <+> "=" <+> "Make" <> pretty name <+> "{": printAttributes name attributes), "}", "", emptyDoc]) show $ printDescription description (vcat [nest 4 $ vcat ("data" <+> pretty name <+> "=" <+> "Make" <> pretty name <+> "{": printAttributes name attributes ++ map printCondition conditions), "}", emptyDoc, emptyDoc])
printType (MakeType _ (BasicType _) _ _) = error "Can't extend basic types" printType (MakeType _ (BasicType _) _ _ _) = error "Can't extend basic types"
printType (BasicType name) = show $ pretty name printType (BasicType name) = show $ pretty name
-- |Creates an attribute that accesses the super type -- |Creates an attribute that accesses the super type
superToAttribute :: String -> String -> TypeAttribute superToAttribute :: String -> TypeAttribute
superToAttribute name typ = MakeTypeAttribute ("super" ++ name) (MakeType typ (BasicType "Object") Nothing []) (Bounds (1, 1)) (Just "Pointer to super class") superToAttribute typ = MakeTypeAttribute "super" (MakeType typ (BasicType "Object") Nothing [] []) (Bounds (1, 1)) (Just "Pointer to super class")
-- |Converts a list of TypeAttributes into a list of haskell valid Docs -- |Converts a list of TypeAttributes into a list of haskell valid Docs
printAttributes :: String -> [TypeAttribute] -> [Doc a] printAttributes :: String -> [TypeAttribute] -> [Doc a]
@@ -38,4 +38,7 @@ printCardinality (MakeTypeAttribute _ typ (Bounds (x, y)) _)
| x == 1 && y == 1 = pretty (typeName typ) | x == 1 && y == 1 = pretty (typeName typ)
| otherwise = "[" <> pretty (typeName typ) <> "]" | otherwise = "[" <> pretty (typeName typ) <> "]"
printCardinality (MakeTypeAttribute _ typ NoBounds _) = "[" <> pretty (typeName typ) <> "]" printCardinality (MakeTypeAttribute _ typ NoBounds _) = "[" <> pretty (typeName typ) <> "]"
printCardinality (MakeTypeAttribute _ typ (OneBound _) _) = "[" <> pretty (typeName typ) <> "]" printCardinality (MakeTypeAttribute _ typ (OneBound _) _) = "[" <> pretty (typeName typ) <> "]"
printCondition :: Condition -> Doc a
printCondition (MakeCondition name desc e) = printDescription desc ("--" <+> pretty name <+> pretty (show e))

View File

@@ -81,7 +81,7 @@ addFunction (definedTypes, definedSymbols) (MakeFunction name _ inps out _)
-- |Adds a newly defined variable to the symbol table -- |Adds a newly defined variable to the symbol table
addVariables :: [Symbol] -> [TypeAttribute] -> [Symbol] addVariables :: [Symbol] -> [TypeAttribute] -> [Symbol]
addVariables s [] = s addVariables s [] = s
addVariables s ((MakeTypeAttribute name typ crd _) : vars) = Var name typ crd : addVariables s vars addVariables s ((MakeTypeAttribute name typ crd _) : vars) = Var name (toHaskell typ) crd : addVariables s vars
-- |Checks the type of a given expression -- |Checks the type of a given expression
checkExpression :: [Symbol] -> Expression -> Either TypeCheckError (Type, Cardinality) checkExpression :: [Symbol] -> Expression -> Either TypeCheckError (Type, Cardinality)
@@ -109,14 +109,13 @@ checkExpression symbolMap (IfSimple cond ex)
checkedExp = checkExpression symbolMap ex checkedExp = checkExpression symbolMap ex
-- |Checks if the condition of the if statement is of type boolean, and then checks that both the then and else statements have the same type -- |Checks if the condition of the if statement is of type boolean, and then checks that both the then and else statements have the same type
checkExpression symbolMap (IfElse cond ex1 ex2) checkExpression symbolMap (IfElse cond ex1 ex2)
| isLeft condType || isSubType (fst $ fromRightUnsafe condType) (BasicType "Boolean") && snd (fromRightUnsafe condType) == Bounds (1, 1) = Left $ IfConditionNotBoolean $ show cond | isLeft condType || not (isSubType (fst $ fromRightUnsafe condType) (BasicType "Boolean") && snd (fromRightUnsafe condType) == Bounds (1, 1)) = Left $ IfConditionNotBoolean $ show cond ++ " :: " ++ show condType
| isLeft ex1Type || isLeft ex2Type || | otherwise = case checkExpression symbolMap ex1 of
isLeft (typeMatch (fst $ fromRightUnsafe ex1Type) (fst $ fromRightUnsafe ex2Type)) || Left err -> Left $ ErrorInsideFunction $ show err
snd (fromRightUnsafe ex1Type) /= snd (fromRightUnsafe ex2Type) = Left $ IfExpressionsDifferentTypes (show ex1) (show ex2) Right ex1Type -> case checkExpression symbolMap ex2 of
| otherwise = ex1Type Left err -> Left $ ErrorInsideFunction $ show err
Right ex2Type -> Right (typeMatch (fst ex1Type) (fst ex2Type), smallestBound (snd ex1Type) (snd ex2Type))
where condType = checkExpression symbolMap cond where condType = checkExpression symbolMap cond
ex1Type = checkExpression symbolMap ex1
ex2Type = checkExpression symbolMap ex2
-- |Checks that all the expressions in a list have compatible types -- |Checks that all the expressions in a list have compatible types
checkList :: [Symbol] -> [Expression] -> Either TypeCheckError (Type, Cardinality) checkList :: [Symbol] -> [Expression] -> Either TypeCheckError (Type, Cardinality)
@@ -144,7 +143,7 @@ checkFunctionCall :: [Symbol] -> String -> [Either TypeCheckError (Type, Cardina
checkFunctionCall [] fun args = Left $ UndefinedFunction $ "Undefined function: \"" ++ fun ++ "\" [" ++ show (rights args) ++ "]" checkFunctionCall [] fun args = Left $ UndefinedFunction $ "Undefined function: \"" ++ fun ++ "\" [" ++ show (rights args) ++ "]"
checkFunctionCall ((Func n a r):symbolMap) name args checkFunctionCall ((Func n a r):symbolMap) name args
| length right /= length args = Left $ ErrorInsideFunction (name ++ ": " ++ show args ++ show (lefts args)) | length right /= length args = Left $ ErrorInsideFunction (name ++ ": " ++ show args ++ show (lefts args))
| name == n && all isRight (zipWith typeIncluded a right) = Right r | name == n && all isRight (zipWith typeIncluded right a) = Right r
| otherwise = checkFunctionCall symbolMap name args | otherwise = checkFunctionCall symbolMap name args
where where
right = rights args right = rights args
@@ -156,23 +155,21 @@ typeIncluded (t1, c1) (t2, c2)
| t1 `isSubType` t2 = Left $ CardinalityMismatch c1 c2 | t1 `isSubType` t2 = Left $ CardinalityMismatch c1 c2
| otherwise = Left $ TypeMismatch (typeName t1) (typeName t2) | otherwise = Left $ TypeMismatch (typeName t1) (typeName t2)
-- |Checks whether two types are compatible (i.e. they have a common super type) -- |Finds the most specific super type of the two types
typeMatch :: Type -> Type -> Either TypeCheckError Type typeMatch :: Type -> Type -> Type
-- |An object matches only with object
typeMatch (BasicType "Object") _ = Right $ BasicType "Object"
typeMatch _ (BasicType "Object") = Right $ BasicType "Object"
-- |Any matches with any type -- |Any matches with any type
typeMatch (BasicType "Any") x = Right x typeMatch (BasicType "Any") x = x
typeMatch x (BasicType "Any") = Right x typeMatch x (BasicType "Any") = x
-- |Integer can be a double -- |Integer can be a double
typeMatch (BasicType "Integer") (BasicType "Double") = Right (BasicType "Double") -- typeMatch (BasicType "Integer") (BasicType "Double") = BasicType "Double"
typeMatch (BasicType "Double") (BasicType "Integer") = Right (BasicType "Double") -- typeMatch (BasicType "Double") (BasicType "Integer") = BasicType "Double"
typeMatch x (BasicType y)
| x `isSubType` BasicType y = x
| otherwise = BasicType "Object"
-- |First check x with all the supertypes of y, then go higher on the supertypes of x and repeat -- |First check x with all the supertypes of y, then go higher on the supertypes of x and repeat
typeMatch x y typeMatch x y
| x == y = Right x | x `isSubType` y = x
| isRight match = Right $ fromRightUnsafe match | otherwise = typeMatch x (superType y)
| otherwise = typeMatch (superType x) y
where match = typeMatch x (superType y)
-- |Looks in the symbol map for the type of a variable -- |Looks in the symbol map for the type of a variable
findVarType :: String -> [Symbol] -> Either TypeCheckError (Type, Cardinality) findVarType :: String -> [Symbol] -> Either TypeCheckError (Type, Cardinality)

View File

@@ -20,9 +20,9 @@ data TypeCheckError =
-- |Checks whether a data type is valid -- |Checks whether a data type is valid
checkType :: [Type] -> Type -> Either [TypeCheckError] Type checkType :: [Type] -> Type -> Either [TypeCheckError] Type
checkType definedTypes (MakeType name super desc attr) checkType definedTypes (MakeType name super desc attr cond)
| null (lefts checkedAttr) = case populateSuper definedTypes definedTypes super of | null (lefts checkedAttr) = case populateSuper definedTypes definedTypes super of
Right superPopulated -> Right $ MakeType name superPopulated desc (rights checkedAttr) Right superPopulated -> Right $ MakeType name superPopulated desc (rights checkedAttr) cond
Left err -> Left [err] Left err -> Left [err]
| otherwise = Left $ lefts checkedAttr | otherwise = Left $ lefts checkedAttr
where checkedAttr = checkAttributes definedTypes attr where checkedAttr = checkAttributes definedTypes attr
@@ -32,11 +32,11 @@ populateSuper :: [Type] -> [Type] -> Type -> Either TypeCheckError Type
populateSuper _ _ (BasicType "Object") = Right (BasicType "Object") populateSuper _ _ (BasicType "Object") = Right (BasicType "Object")
populateSuper _ _ (BasicType _) = Left $ UndefinedType "Can't extend basic types" populateSuper _ _ (BasicType _) = Left $ UndefinedType "Can't extend basic types"
populateSuper _ [] t = Left $ UndefinedType (typeName t) populateSuper _ [] t = Left $ UndefinedType (typeName t)
populateSuper allTypes (currType : types) (MakeType t super d a) populateSuper allTypes (currType : types) (MakeType t super d a c)
| typeName currType == t = case populateSuper allTypes allTypes super of | typeName currType == t = case populateSuper allTypes allTypes super of
Right superChecked -> Right $ MakeType t superChecked (typeDescription currType) (typeAttributes currType) Right superChecked -> Right $ MakeType t superChecked (typeDescription currType) (typeAttributes currType) c
Left err -> Left err Left err -> Left err
| otherwise = populateSuper allTypes types (MakeType t super d a) | otherwise = populateSuper allTypes types (MakeType t super d a c)
-- |Checks whether all the types of the attributes of a data type are already defined -- |Checks whether all the types of the attributes of a data type are already defined
checkAttributes :: [Type] -> [TypeAttribute] -> [Either TypeCheckError TypeAttribute] checkAttributes :: [Type] -> [TypeAttribute] -> [Either TypeCheckError TypeAttribute]
@@ -48,11 +48,11 @@ checkAttributes definedTypes ((MakeTypeAttribute name typ crd desc):as)
-- |Checks whether a type is predefined or in the symbol table -- |Checks whether a type is predefined or in the symbol table
checkAttributeType :: [Type] -> Type -> Either TypeCheckError Type checkAttributeType :: [Type] -> Type -> Either TypeCheckError Type
checkAttributeType _ (MakeType "int" _ _ _) = Right $ BasicType "Integer" checkAttributeType _ (MakeType "int" _ _ _ _) = Right $ BasicType "Integer"
checkAttributeType _ (MakeType "string" _ _ _) = Right $ BasicType "String" checkAttributeType _ (MakeType "string" _ _ _ _) = Right $ BasicType "String"
checkAttributeType _ (MakeType "number" _ _ _) = Right $ BasicType "Double" checkAttributeType _ (MakeType "number" _ _ _ _) = Right $ BasicType "Double"
checkAttributeType _ (MakeType "boolean" _ _ _) = Right $ BasicType "Bool" checkAttributeType _ (MakeType "boolean" _ _ _ _) = Right $ BasicType "Bool"
checkAttributeType _ (MakeType "time" _ _ _) = Right $ BasicType "Time" checkAttributeType _ (MakeType "time" _ _ _ _) = Right $ BasicType "Time"
checkAttributeType definedTypes name checkAttributeType definedTypes name
| name `elem` definedTypes = Right name | name `elem` definedTypes = Right name
| otherwise = Left $ UndefinedType (typeName name) | otherwise = Left $ UndefinedType (typeName name)