mirror of
https://github.com/macocianradu/RosettaHaskellCompiler.git
synced 2026-03-18 13:00:08 +00:00
finished generator for basic types, enums and functions.
Functions still need to print a body
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,3 +22,4 @@ cabal.project.local~
|
|||||||
.HTF/
|
.HTF/
|
||||||
.ghc.environment.*
|
.ghc.environment.*
|
||||||
.idea/
|
.idea/
|
||||||
|
/resources/Generated/
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ library
|
|||||||
exposed-modules:
|
exposed-modules:
|
||||||
Model.Enum
|
Model.Enum
|
||||||
Model.Function
|
Model.Function
|
||||||
|
Model.RosettaObject
|
||||||
Model.Type
|
Model.Type
|
||||||
Parser.Enum
|
Parser.Enum
|
||||||
Parser.Expression
|
Parser.Expression
|
||||||
@@ -36,6 +37,7 @@ library
|
|||||||
PrettyPrinter.Enum
|
PrettyPrinter.Enum
|
||||||
PrettyPrinter.Function
|
PrettyPrinter.Function
|
||||||
PrettyPrinter.General
|
PrettyPrinter.General
|
||||||
|
PrettyPrinter.RosettaObject
|
||||||
PrettyPrinter.Type
|
PrettyPrinter.Type
|
||||||
Semantic.ExpressionChecker
|
Semantic.ExpressionChecker
|
||||||
Semantic.TypeChecker
|
Semantic.TypeChecker
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.stack-work" />
|
<excludeFolder url="file://$MODULE_DIR$/.stack-work" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/resources/Generated" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|||||||
72
app/Main.hs
72
app/Main.hs
@@ -3,28 +3,84 @@ module Main where
|
|||||||
import Parser.Enum
|
import Parser.Enum
|
||||||
import Parser.Type
|
import Parser.Type
|
||||||
import Parser.Function
|
import Parser.Function
|
||||||
|
import Parser.General
|
||||||
|
import Model.RosettaObject
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
import Text.Megaparsec
|
import Text.Megaparsec
|
||||||
import PrettyPrinter.Enum
|
import PrettyPrinter.Enum
|
||||||
import PrettyPrinter.Type
|
import PrettyPrinter.Type
|
||||||
import PrettyPrinter.Function
|
import PrettyPrinter.Function
|
||||||
import Semantic.TypeChecker
|
import Semantic.TypeChecker
|
||||||
|
import Semantic.ExpressionChecker
|
||||||
import Model.Function
|
import Model.Function
|
||||||
import Model.Type
|
import Model.Type
|
||||||
|
import System.Environment.Blank (getArgs)
|
||||||
|
import Model.Enum
|
||||||
|
import Data.Either
|
||||||
|
|
||||||
|
-- :set args resources/testAll.rosetta resources/Generated/testAll.hs
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
rosettaString <- readFile "app/testFile.rosetta"
|
args <- getArgs
|
||||||
putStrLn "rosetta String: "
|
rosettaString <- readFile $ head args
|
||||||
putStrLn rosettaString
|
case parse rosettaParser "" (Text.pack rosettaString) of
|
||||||
putStrLn "\nFinal enum: \n"
|
|
||||||
case parse enumParser "" (Text.pack rosettaString) of
|
|
||||||
Left errorBundle -> print (errorBundlePretty errorBundle)
|
Left errorBundle -> print (errorBundlePretty errorBundle)
|
||||||
Right enum -> putStrLn $ printEnum enum
|
Right objs -> do
|
||||||
|
putStrLn $ printObjects (definedTypes, definedFunctions) objs
|
||||||
|
where
|
||||||
|
definedFunctions = addNewFunctions (definedTypes, defaultMap) objs
|
||||||
|
definedTypes = addNewTypes [] objs
|
||||||
|
|
||||||
|
printObjects :: ([Type], [Symbol]) -> [RosettaObject] -> String
|
||||||
|
printObjects (t, s) objs
|
||||||
|
| null (lefts finalString) = concat $ rights finalString
|
||||||
|
| otherwise = error $ show $ lefts finalString
|
||||||
|
where finalString = map (printObject (t, s)) objs
|
||||||
|
|
||||||
|
printObject :: ([Type], [Symbol]) -> RosettaObject -> Either [TypeCheckError] String
|
||||||
|
printObject (definedTypes, _) (TypeObject t)
|
||||||
|
| isRight checked = Right $ printType t
|
||||||
|
| otherwise = Left $ fromLeftUnsafe checked
|
||||||
|
where checked = checkType definedTypes t
|
||||||
|
printObject _ (EnumObject e) = Right $ printEnum e
|
||||||
|
printObject (_, definedFunctions) (FunctionObject (MakeFunction name desc inp out ex))
|
||||||
|
| isRight checked = Right $ printFunction (MakeFunction name desc inp out ex)
|
||||||
|
| otherwise = Left [fromLeftUnsafe checked]
|
||||||
|
where
|
||||||
|
checked = checkExpression definedFunctions ex
|
||||||
|
|
||||||
|
addNewFunctions :: ([Type], [Symbol]) -> [RosettaObject] -> [Symbol]
|
||||||
|
addNewFunctions (_, s) [] = s
|
||||||
|
addNewFunctions (t, s) ((FunctionObject f):os)
|
||||||
|
| isRight definedFunctions = fromRightUnsafe definedFunctions
|
||||||
|
| otherwise = error $ show $ fromLeftUnsafe definedFunctions
|
||||||
|
where definedFunctions = addFunction (t, addNewFunctions (t, s) os) f
|
||||||
|
addNewFunctions (t, s) (_:os) = addNewFunctions (t, s) os
|
||||||
|
|
||||||
|
addNewTypes :: [Type] -> [RosettaObject] -> [Type]
|
||||||
|
addNewTypes l [] = l
|
||||||
|
addNewTypes defined (TypeObject o: os) = addDefinedTypes (addNewTypes defined os) [o]
|
||||||
|
addNewTypes defined (EnumObject (MakeEnum name _ _): os) = addDefinedTypes (addNewTypes defined os) [MakeType name Nothing Nothing []]
|
||||||
|
addNewTypes defined (_ :os) = addNewTypes defined os
|
||||||
|
|
||||||
|
rosettaParser :: Parser [RosettaObject]
|
||||||
|
rosettaParser = many (try parseEnum <|> try parseType <|> try parseFunction) <* eof
|
||||||
|
|
||||||
|
parseEnum :: Parser RosettaObject
|
||||||
|
parseEnum = do
|
||||||
|
EnumObject <$> enumParser
|
||||||
|
|
||||||
|
parseType :: Parser RosettaObject
|
||||||
|
parseType = do
|
||||||
|
TypeObject <$> typeParser
|
||||||
|
|
||||||
|
parseFunction :: Parser RosettaObject
|
||||||
|
parseFunction = do
|
||||||
|
FunctionObject <$> functionParser
|
||||||
|
|
||||||
testEnum :: IO()
|
testEnum :: IO()
|
||||||
testEnum = do
|
testEnum = do
|
||||||
rosettaString <- readFile "resources/Enums/testEnum5.rosetta"
|
rosettaString <- readFile "resources/Enums/testEnum1.rosetta"
|
||||||
case parse enumParser "" (Text.pack rosettaString) of
|
case parse enumParser "" (Text.pack rosettaString) of
|
||||||
Left errorBundle -> print errorBundle
|
Left errorBundle -> print errorBundle
|
||||||
Right enum ->
|
Right enum ->
|
||||||
@@ -61,5 +117,5 @@ testFunc = do
|
|||||||
Right fun ->
|
Right fun ->
|
||||||
do
|
do
|
||||||
print $ printFunctionSignature fun
|
print $ printFunctionSignature fun
|
||||||
print (assignments fun)
|
print (assignment fun)
|
||||||
writeFile "resources/Generated/generatedFunction.hs" (show $ printFunctionSignature fun)
|
writeFile "resources/Generated/generatedFunction.hs" (show $ printFunctionSignature fun)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
type Period: <"description">
|
type Period extends Something: <"description">
|
||||||
periodMultiplier int (1..1) <"A time period multiplier, e.g. 1, 2 or 3 etc. A negative value can be used when specifying an offset relative to another date, e.g. -2 days.">
|
periodMultiplier int (1..1) <"A time period multiplier, e.g. 1, 2 or 3 etc. A negative value can be used when specifying an offset relative to another date, e.g. -2 days.">
|
||||||
testMany TestType (0..*) <"Test many">
|
testMany TestType (0..*) <"Test many">
|
||||||
testSome TestSomeType (1..*) <"Test some">
|
testSome TestSomeType (1..*) <"Test some">
|
||||||
|
|||||||
34
resources/testAll.rosetta
Normal file
34
resources/testAll.rosetta
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
enum PeriodEnum: <"The enumerated values to specified the period, e.g. day, week.">
|
||||||
|
D displayName "day" <"Day">
|
||||||
|
M displayName "month" <"Month">
|
||||||
|
Y displayName "year" <"Year">
|
||||||
|
|
||||||
|
type Period extends Something: <"description">
|
||||||
|
periodMultiplier int (1..1) <"A time period multiplier, e.g. 1, 2 or 3 etc. A negative value can be used when specifying an offset relative to another date, e.g. -2 days.">
|
||||||
|
testMany TestType (0..*) <"Test many">
|
||||||
|
testSome TestSomeType (1..*) <"Test some">
|
||||||
|
testMaybeOne TestZeroOneType (0..1) <"Test zero or one">
|
||||||
|
|
||||||
|
type TestType:
|
||||||
|
periodMultiplier int (1..1)
|
||||||
|
|
||||||
|
type TestSomeType: <"description">
|
||||||
|
periodMultiplier int (1..1) <"A time period multiplier, e.g. 1, 2 or 3 etc. A negative value can be used when specifying an offset relative to another date, e.g. -2 days.">
|
||||||
|
|
||||||
|
type TestZeroOneType extends Period:
|
||||||
|
periodMultiplier int (1..1)
|
||||||
|
|
||||||
|
type ObservationPrimitive:
|
||||||
|
periodMultiplier int (1..1)
|
||||||
|
|
||||||
|
func EquityPriceObservation: <"Function specification for the observation of an equity price, based on the attributes of the 'EquityValuation' class.">
|
||||||
|
inputs:
|
||||||
|
equity int (1..1)
|
||||||
|
valuationDate int (1..1)
|
||||||
|
valuationTime int (0..1)
|
||||||
|
timeType TestType (0..1)
|
||||||
|
determinationMethod ObservationPrimitive (1..*)
|
||||||
|
output:
|
||||||
|
observation ObservationPrimitive (1..1)
|
||||||
|
|
||||||
|
assign-output: if equity exists then valuationDate
|
||||||
@@ -8,5 +8,4 @@ func EquityPriceObservation: <"Function specification for the observation of an
|
|||||||
output:
|
output:
|
||||||
observation ObservationPrimitive (1..1)
|
observation ObservationPrimitive (1..1)
|
||||||
|
|
||||||
assign-output
|
assign-output: if asd exists then var2
|
||||||
observation: if asd exists then var2
|
|
||||||
@@ -8,7 +8,7 @@ data Function =
|
|||||||
functionDescription :: Maybe String,
|
functionDescription :: Maybe String,
|
||||||
inputParameters :: [TypeAttribute],
|
inputParameters :: [TypeAttribute],
|
||||||
outputParameter :: TypeAttribute,
|
outputParameter :: TypeAttribute,
|
||||||
assignments :: [(Expression, Expression)]
|
assignment :: Expression
|
||||||
}
|
}
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
|||||||
10
src/Model/RosettaObject.hs
Normal file
10
src/Model/RosettaObject.hs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
module Model.RosettaObject where
|
||||||
|
|
||||||
|
import Model.Enum
|
||||||
|
import Model.Function
|
||||||
|
import Model.Type
|
||||||
|
|
||||||
|
data RosettaObject =
|
||||||
|
EnumObject EnumType
|
||||||
|
| TypeObject Type
|
||||||
|
| FunctionObject Function
|
||||||
@@ -29,7 +29,6 @@ data TypeAttribute = MakeTypeAttribute {
|
|||||||
attributeDescription :: Maybe String
|
attributeDescription :: Maybe String
|
||||||
} deriving (Show)
|
} deriving (Show)
|
||||||
|
|
||||||
--TODO use bounded class
|
|
||||||
data Cardinality = Bounds (Integer, Integer)
|
data Cardinality = Bounds (Integer, Integer)
|
||||||
| OneBound Integer
|
| OneBound Integer
|
||||||
| NoBounds
|
| NoBounds
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import Model.Enum
|
|||||||
enumParser :: Parser EnumType
|
enumParser :: Parser EnumType
|
||||||
enumParser =
|
enumParser =
|
||||||
do
|
do
|
||||||
eName <- enumNameParser
|
eName <- try enumNameParser
|
||||||
eDescription <- optional descriptionParser
|
eDescription <- optional descriptionParser
|
||||||
values <- some enumValueParser
|
values <- some enumValueParser
|
||||||
return (MakeEnum eName eDescription values)
|
return (MakeEnum eName eDescription values)
|
||||||
@@ -18,7 +18,7 @@ enumParser =
|
|||||||
enumValueParser :: Parser EnumValue
|
enumValueParser :: Parser EnumValue
|
||||||
enumValueParser =
|
enumValueParser =
|
||||||
do
|
do
|
||||||
vName <- nameParser
|
vName <- try nameParser
|
||||||
dName <- optional enumValueDisplayNameParser
|
dName <- optional enumValueDisplayNameParser
|
||||||
vDescription <- optional descriptionParser
|
vDescription <- optional descriptionParser
|
||||||
return (MakeEnumValue vName vDescription dName)
|
return (MakeEnumValue vName vDescription dName)
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ reverseExpression e = e
|
|||||||
|
|
||||||
precedence :: String -> Int
|
precedence :: String -> Int
|
||||||
precedence "or" = 1
|
precedence "or" = 1
|
||||||
precedence "and" = 1
|
precedence "and" = 10
|
||||||
precedence "+" = 2
|
precedence "+" = 2
|
||||||
precedence "-" = 2
|
precedence "-" = 2
|
||||||
precedence "*" = 3
|
precedence "*" = 3
|
||||||
|
|||||||
@@ -14,22 +14,19 @@ functionParser :: Parser Function
|
|||||||
functionParser =
|
functionParser =
|
||||||
do
|
do
|
||||||
_ <- lexeme $ string "func"
|
_ <- lexeme $ string "func"
|
||||||
fName <- pascalNameParser
|
fName <- try pascalNameParser
|
||||||
_ <- lexeme $ char ':'
|
_ <- lexeme $ char ':'
|
||||||
fDescription <- optional descriptionParser
|
fDescription <- optional descriptionParser
|
||||||
fInput <- inputAttributesParser
|
fInput <- inputAttributesParser
|
||||||
fOutput <- outputAttributeParser
|
fOutput <- outputAttributeParser
|
||||||
fAssignments <- many assignmentParser
|
MakeFunction fName fDescription fInput fOutput <$> assignmentParser
|
||||||
return (MakeFunction fName fDescription fInput fOutput fAssignments)
|
|
||||||
|
|
||||||
assignmentParser :: Parser (Expression, Expression)
|
assignmentParser :: Parser Expression
|
||||||
assignmentParser =
|
assignmentParser =
|
||||||
do
|
do
|
||||||
_ <- lexeme $ string "assign-output"
|
_ <- lexeme $ string "assign-output"
|
||||||
name <- expressionParser
|
|
||||||
_ <- lexeme $ char ':'
|
_ <- lexeme $ char ':'
|
||||||
expr <- expressionParser
|
expressionParser
|
||||||
return (name, expr)
|
|
||||||
|
|
||||||
inputAttributesParser :: Parser [TypeAttribute]
|
inputAttributesParser :: Parser [TypeAttribute]
|
||||||
inputAttributesParser =
|
inputAttributesParser =
|
||||||
@@ -46,8 +43,8 @@ outputAttributeParser =
|
|||||||
attributeParser :: Parser TypeAttribute
|
attributeParser :: Parser TypeAttribute
|
||||||
attributeParser =
|
attributeParser =
|
||||||
do
|
do
|
||||||
nam <- camelNameParser
|
nam <- try camelNameParser
|
||||||
typ <- pascalNameParser <|> camelNameParser
|
typ <- try (pascalNameParser <|> camelNameParser)
|
||||||
crd <- cardinalityParser
|
crd <- cardinalityParser
|
||||||
desc <- optional descriptionParser
|
desc <- optional descriptionParser
|
||||||
return $ MakeTypeAttribute nam (MakeType typ Nothing Nothing []) crd desc
|
return $ MakeTypeAttribute nam (MakeType typ Nothing Nothing []) crd desc
|
||||||
|
|||||||
@@ -27,19 +27,33 @@ pascalNameParser :: Parser String
|
|||||||
pascalNameParser =
|
pascalNameParser =
|
||||||
do
|
do
|
||||||
first <- upperChar
|
first <- upperChar
|
||||||
rest <- lexeme $ many (letterChar <|> digitChar <|> char '_')
|
rest <- lexeme $ many allowedChars
|
||||||
return (first : rest)
|
if first:rest `notElem` restrictedNames then return (first:rest) else fail ((first:rest) ++ " is a restricted name")
|
||||||
|
|
||||||
camelNameParser :: Parser String
|
camelNameParser :: Parser String
|
||||||
camelNameParser =
|
camelNameParser =
|
||||||
do
|
do
|
||||||
first <- lowerChar
|
first <- lowerChar
|
||||||
rest <- lexeme $ many (letterChar <|> digitChar <|> char '_')
|
rest <- lexeme $ many allowedChars
|
||||||
return (first : rest)
|
if first:rest `notElem` restrictedNames then return (first:rest) else fail ((first:rest) ++ " is a restricted name")
|
||||||
|
|
||||||
nameParser :: Parser String
|
nameParser :: Parser String
|
||||||
nameParser =
|
nameParser =
|
||||||
do
|
do
|
||||||
first <- letterChar <|> char '_'
|
first <- letterChar <|> char '_'
|
||||||
rest <- lexeme $ many (letterChar <|> digitChar <|> char '_')
|
rest <- lexeme $ many allowedChars
|
||||||
return (first:rest)
|
if first:rest `notElem` restrictedNames then return (first:rest) else fail ((first:rest) ++ " is a restricted name")
|
||||||
|
|
||||||
|
allowedChars :: Parser Char
|
||||||
|
allowedChars = letterChar <|> digitChar <|> char '_'
|
||||||
|
|
||||||
|
restrictedNames :: [String]
|
||||||
|
restrictedNames = [
|
||||||
|
"displayName",
|
||||||
|
"enum",
|
||||||
|
"func",
|
||||||
|
"type",
|
||||||
|
"extends",
|
||||||
|
"inputs",
|
||||||
|
"output"
|
||||||
|
]
|
||||||
@@ -10,7 +10,7 @@ import Parser.General
|
|||||||
typeParser :: Parser Type
|
typeParser :: Parser Type
|
||||||
typeParser =
|
typeParser =
|
||||||
do
|
do
|
||||||
tName <- typeNameParser
|
tName <- try typeNameParser
|
||||||
tSuper <- optional superTypeParser
|
tSuper <- optional superTypeParser
|
||||||
_ <- lexeme $ char ':'
|
_ <- lexeme $ char ':'
|
||||||
tDescription <- optional descriptionParser
|
tDescription <- optional descriptionParser
|
||||||
@@ -27,8 +27,8 @@ superTypeParser =
|
|||||||
typeAttributeParser :: Parser TypeAttribute
|
typeAttributeParser :: Parser TypeAttribute
|
||||||
typeAttributeParser =
|
typeAttributeParser =
|
||||||
do
|
do
|
||||||
aName <- camelNameParser
|
aName <- try camelNameParser
|
||||||
aType <- nameParser
|
aType <- try nameParser
|
||||||
card <- cardinalityParser
|
card <- cardinalityParser
|
||||||
desc <- optional descriptionParser
|
desc <- optional descriptionParser
|
||||||
return (MakeTypeAttribute aName (MakeType aType Nothing Nothing []) card desc)
|
return (MakeTypeAttribute aName (MakeType aType Nothing Nothing []) card desc)
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import PrettyPrinter.Type
|
|||||||
|
|
||||||
-- show printStatementTree
|
-- show printStatementTree
|
||||||
|
|
||||||
|
printFunction :: Function -> String
|
||||||
|
printFunction = show . printFunctionSignature
|
||||||
|
|
||||||
printFunctionSignature :: Function -> Doc a
|
printFunctionSignature :: Function -> Doc a
|
||||||
printFunctionSignature (MakeFunction name description inputs output _) =
|
printFunctionSignature (MakeFunction name description inputs output _) =
|
||||||
printDescription description (pretty name <+> prettyPrintType (Prelude.map printCardinality (inputs ++ [output])))
|
printDescription description (pretty name <+> prettyPrintType (Prelude.map printCardinality (inputs ++ [output])))
|
||||||
|
|||||||
11
src/PrettyPrinter/RosettaObject.hs
Normal file
11
src/PrettyPrinter/RosettaObject.hs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module PrettyPrinter.RosettaObject where
|
||||||
|
|
||||||
|
import Model.RosettaObject
|
||||||
|
import PrettyPrinter.Enum
|
||||||
|
import PrettyPrinter.Function
|
||||||
|
import PrettyPrinter.Type
|
||||||
|
|
||||||
|
printRosettaObject :: RosettaObject -> String
|
||||||
|
printRosettaObject (EnumObject a) = printEnum a
|
||||||
|
printRosettaObject (TypeObject a) = printType a
|
||||||
|
printRosettaObject (FunctionObject a) = printFunction a
|
||||||
@@ -7,15 +7,24 @@ import PrettyPrinter.General
|
|||||||
import Model.Type
|
import Model.Type
|
||||||
|
|
||||||
printType :: Type -> String
|
printType :: Type -> String
|
||||||
printType (MakeType name _ description attributes) =
|
printType (MakeType name (Just (MakeType super _ _ _)) description attributes) = printType (MakeType name Nothing description (superToAttribute super:attributes))
|
||||||
show $ printDescription description (vcat [nest 4 $ vcat ("data" <+> pretty name <+> "=" <+> "Make" <> pretty name <+> "{": map printAttribute attributes), "}", ""])
|
printType (MakeType _ (Just (BasicType _)) _ _) = error "Can't extend basic types"
|
||||||
|
printType (MakeType name Nothing description attributes) =
|
||||||
|
show $ printDescription description (vcat [nest 4 $ vcat ("data" <+> pretty name <+> "=" <+> "Make" <> pretty name <+> "{": printAttributes attributes), "}", ""])
|
||||||
printType (BasicType name) = show $ pretty name
|
printType (BasicType name) = show $ pretty name
|
||||||
|
|
||||||
|
--printSuperType :: Maybe Type -> Doc a
|
||||||
|
--printSuperType (Just (MakeType name _ _ _)) = "super" <+> "::" <+> pretty name
|
||||||
|
--printSuperType (Just (BasicType _)) = error "Can't extend basic types"
|
||||||
|
--printSuperType Nothing = emptyDoc
|
||||||
|
|
||||||
|
superToAttribute :: String -> TypeAttribute
|
||||||
|
superToAttribute name = MakeTypeAttribute "super" (MakeType name Nothing Nothing []) (Bounds (1, 1)) (Just "Pointer to super class")
|
||||||
|
|
||||||
printAttributes :: [TypeAttribute] -> [Doc a]
|
printAttributes :: [TypeAttribute] -> [Doc a]
|
||||||
printAttributes [] = []
|
printAttributes [] = []
|
||||||
printAttributes [at] = [printAttribute at]
|
printAttributes [at] = [printAttribute at]
|
||||||
printAttributes (at : ats) = (printAttribute at <> ",") : printAttributes ats
|
printAttributes (at : ats) = (printAttribute at <> ",") : printAttributes ats
|
||||||
|
|
||||||
|
|
||||||
printAttribute :: TypeAttribute -> Doc a
|
printAttribute :: TypeAttribute -> Doc a
|
||||||
printAttribute (MakeTypeAttribute name typ crd description) =
|
printAttribute (MakeTypeAttribute name typ crd description) =
|
||||||
|
|||||||
@@ -51,7 +51,21 @@ defaultMap = [
|
|||||||
|
|
||||||
Func "count" [BasicType "Any"] (BasicType "Integer")
|
Func "count" [BasicType "Any"] (BasicType "Integer")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
addFunction :: ([Type], [Symbol]) -> Function -> Either [TypeCheckError] [Symbol]
|
||||||
|
addFunction (definedTypes, definedSymbols) (MakeFunction name _ inps out _)
|
||||||
|
| null (lefts checkedInputs) && isRight checkedOutput = Right $ Func name (map attributeType (rights checkedInputs)) (attributeType $ fromRightUnsafe checkedOutput) : allSymbols
|
||||||
|
| isLeft checkedOutput = Left [fromLeftUnsafe checkedOutput]
|
||||||
|
| otherwise = Left $ lefts checkedInputs
|
||||||
|
where
|
||||||
|
checkedInputs = checkAttributes definedTypes inps
|
||||||
|
checkedOutput = head $ checkAttributes definedTypes [out]
|
||||||
|
allSymbols = addVariables definedSymbols inps
|
||||||
|
|
||||||
|
addVariables :: [Symbol] -> [TypeAttribute] -> [Symbol]
|
||||||
|
addVariables s [] = s
|
||||||
|
addVariables s ((MakeTypeAttribute name typ _ _) : vars) = Var name typ : addVariables s vars
|
||||||
|
|
||||||
checkExpression :: [Symbol] -> Expression -> Either TypeCheckError Type
|
checkExpression :: [Symbol] -> Expression -> Either TypeCheckError Type
|
||||||
checkExpression symbolMap (Variable var) = findVarType var symbolMap
|
checkExpression symbolMap (Variable var) = findVarType var symbolMap
|
||||||
checkExpression _ (Int _) = Right $ BasicType "Integer"
|
checkExpression _ (Int _) = Right $ BasicType "Integer"
|
||||||
@@ -65,7 +79,7 @@ checkExpression symbolMap (Function name exps) = checkFunctionCall symbolMap nam
|
|||||||
checkExpression symbolMap (PostfixExp name ex) = checkFunctionCall symbolMap name [checkExpression symbolMap ex]
|
checkExpression symbolMap (PostfixExp name ex) = checkFunctionCall symbolMap name [checkExpression symbolMap ex]
|
||||||
checkExpression symbolMap (InfixExp name ex1 ex2) = checkFunctionCall symbolMap name (checkExpression symbolMap ex1: [checkExpression symbolMap ex2])
|
checkExpression symbolMap (InfixExp name ex1 ex2) = checkFunctionCall symbolMap name (checkExpression symbolMap ex1: [checkExpression symbolMap ex2])
|
||||||
checkExpression symbolMap (IfSimple cond ex)
|
checkExpression symbolMap (IfSimple cond ex)
|
||||||
| isLeft condType && isLeft (typeMatch (fromRightUnsafe condType) (BasicType "Boolean")) = checkExpression symbolMap ex
|
| isRight condType && isRight (typeMatch (fromRightUnsafe condType) (BasicType "Boolean")) = checkExpression symbolMap ex
|
||||||
| otherwise = Left IfConditionNotBoolean
|
| otherwise = Left IfConditionNotBoolean
|
||||||
where condType = checkExpression symbolMap cond
|
where condType = checkExpression symbolMap cond
|
||||||
checkExpression symbolMap (IfElse cond ex1 ex2)
|
checkExpression symbolMap (IfElse cond ex1 ex2)
|
||||||
@@ -95,7 +109,7 @@ checkList1 symbs (ex : exps) typ
|
|||||||
checkFunctionCall :: [Symbol] -> String -> [Either TypeCheckError Type] -> Either TypeCheckError Type
|
checkFunctionCall :: [Symbol] -> String -> [Either TypeCheckError Type] -> Either TypeCheckError Type
|
||||||
checkFunctionCall [] fun args = Left $ UndefinedFunction $ "Undefined function: \"" ++ fun ++ "\" [" ++ concatMap typeName (rights args) ++ "]"
|
checkFunctionCall [] fun args = Left $ UndefinedFunction $ "Undefined function: \"" ++ fun ++ "\" [" ++ concatMap typeName (rights args) ++ "]"
|
||||||
checkFunctionCall ((Func n a r):symbolMap) name args
|
checkFunctionCall ((Func n a r):symbolMap) name args
|
||||||
| length right /= length args = Left ErrorInsideFunction
|
| length right /= length args = Left $ ErrorInsideFunction (name ++ ": " ++ show args)
|
||||||
| name == n && all isRight (zipWith typeMatch a right) = Right r
|
| name == n && all isRight (zipWith typeMatch a right) = Right r
|
||||||
| otherwise = checkFunctionCall symbolMap name args
|
| otherwise = checkFunctionCall symbolMap name args
|
||||||
where right = rights args
|
where right = rights args
|
||||||
@@ -118,14 +132,4 @@ findVarType var [] = Left $ UndefinedVariable var
|
|||||||
findVarType x ((Var name typ):symbols)
|
findVarType x ((Var name typ):symbols)
|
||||||
| x == name = Right typ
|
| x == name = Right typ
|
||||||
| otherwise = findVarType x symbols
|
| otherwise = findVarType x symbols
|
||||||
findVarType x (_:symbols) = findVarType x symbols
|
findVarType x (_:symbols) = findVarType x symbols
|
||||||
|
|
||||||
fromRightUnsafe :: Either a b -> b
|
|
||||||
fromRightUnsafe x = case x of
|
|
||||||
Left _ -> error "Value is Left"
|
|
||||||
Right b -> b
|
|
||||||
|
|
||||||
fromLeftUnsafe :: Either a b -> a
|
|
||||||
fromLeftUnsafe x = case x of
|
|
||||||
Left a -> a
|
|
||||||
Right _ -> error "Value is Right"
|
|
||||||
@@ -1,32 +1,53 @@
|
|||||||
module Semantic.TypeChecker where
|
module Semantic.TypeChecker where
|
||||||
|
|
||||||
import Model.Type
|
import Model.Type
|
||||||
|
import Data.Either
|
||||||
|
|
||||||
data TypeCheckError =
|
data TypeCheckError =
|
||||||
UndefinedType String
|
UndefinedType String
|
||||||
| IfConditionNotBoolean
|
| IfConditionNotBoolean
|
||||||
| IfExpressionsDifferentTypes
|
| IfExpressionsDifferentTypes
|
||||||
| UndefinedFunction String
|
| UndefinedFunction String
|
||||||
| ErrorInsideFunction
|
| ErrorInsideFunction String
|
||||||
| UndefinedVariable String
|
| UndefinedVariable String
|
||||||
| TypeMismatch String String
|
| TypeMismatch String String
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
checkAttributes :: [Type] -> [TypeAttribute] -> [Either TypeCheckError Type]
|
checkType :: [Type] -> Type -> Either [TypeCheckError] Type
|
||||||
checkAttributes _ [] = []
|
checkType definedTypes (MakeType name super desc attr)
|
||||||
checkAttributes definedTypes ((MakeTypeAttribute _ name _ _):as) = checkType definedTypes name : checkAttributes definedTypes as
|
| null (lefts checkedAttr) = Right $ MakeType name super desc (rights checkedAttr)
|
||||||
|
| otherwise = Left $ lefts checkedAttr
|
||||||
|
where checkedAttr = checkAttributes definedTypes attr
|
||||||
|
checkType _ (BasicType b) = Right (BasicType b)
|
||||||
|
|
||||||
checkType :: [Type] -> Type -> Either TypeCheckError Type
|
checkAttributes :: [Type] -> [TypeAttribute] -> [Either TypeCheckError TypeAttribute]
|
||||||
checkType _ (MakeType "int" _ _ _) = Right $ BasicType "Integer"
|
checkAttributes _ [] = []
|
||||||
checkType _ (MakeType "string" _ _ _) = Right $ BasicType "String"
|
checkAttributes definedTypes ((MakeTypeAttribute name typ crd desc):as)
|
||||||
checkType _ (MakeType "number" _ _ _) = Right $ BasicType "Double"
|
| isRight checked = Right (MakeTypeAttribute name (fromRightUnsafe checked) crd desc) : checkAttributes definedTypes as
|
||||||
checkType _ (MakeType "boolean" _ _ _) = Right $ BasicType "Bool"
|
| otherwise = Left (fromLeftUnsafe checked) : checkAttributes definedTypes as
|
||||||
checkType _ (MakeType "time" _ _ _) = Right $ BasicType "Time"
|
where checked = checkAttributeType definedTypes typ
|
||||||
checkType definedTypes name
|
|
||||||
|
checkAttributeType :: [Type] -> Type -> Either TypeCheckError Type
|
||||||
|
checkAttributeType _ (MakeType "int" _ _ _) = Right $ BasicType "Integer"
|
||||||
|
checkAttributeType _ (MakeType "string" _ _ _) = Right $ BasicType "String"
|
||||||
|
checkAttributeType _ (MakeType "number" _ _ _) = Right $ BasicType "Double"
|
||||||
|
checkAttributeType _ (MakeType "boolean" _ _ _) = Right $ BasicType "Bool"
|
||||||
|
checkAttributeType _ (MakeType "time" _ _ _) = Right $ BasicType "Time"
|
||||||
|
checkAttributeType definedTypes name
|
||||||
| name `elem` definedTypes = Right name
|
| name `elem` definedTypes = Right name
|
||||||
| otherwise = Left $ UndefinedType (typeName name)
|
| otherwise = Left $ UndefinedType (typeName name)
|
||||||
|
|
||||||
addDefinedTypes :: [Type] -> [Type] -> [Type]
|
addDefinedTypes :: [Type] -> [Type] -> [Type]
|
||||||
addDefinedTypes l [] = l
|
addDefinedTypes l [] = l
|
||||||
addDefinedTypes l (BasicType _ : ts) = addDefinedTypes l ts
|
addDefinedTypes l (BasicType _ : ts) = addDefinedTypes l ts
|
||||||
addDefinedTypes l (t:ts) = t : addDefinedTypes l ts
|
addDefinedTypes l (t:ts) = t : addDefinedTypes l ts
|
||||||
|
|
||||||
|
fromRightUnsafe :: (Show a) => Either a b -> b
|
||||||
|
fromRightUnsafe x = case x of
|
||||||
|
Left a -> error ("Value is Left" ++ show a)
|
||||||
|
Right b -> b
|
||||||
|
|
||||||
|
fromLeftUnsafe :: Either a b -> a
|
||||||
|
fromLeftUnsafe x = case x of
|
||||||
|
Left a -> a
|
||||||
|
Right _ -> error "Value is Right"
|
||||||
Reference in New Issue
Block a user