Commit 4d121574 authored by Kenton Varda's avatar Kenton Varda

Implement annotations.

parent 7a7e0b64
...@@ -27,6 +27,7 @@ import Grammar ...@@ -27,6 +27,7 @@ import Grammar
import Semantics import Semantics
import Token(Located(Located)) import Token(Located(Located))
import Parser(parseFile) import Parser(parseFile)
import Control.Monad(unless)
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.Map((!)) import Data.Map((!))
import qualified Data.Set as Set import qualified Data.Set as Set
...@@ -153,7 +154,27 @@ lookupDesc scope name = lookupDesc (descParent scope) name ...@@ -153,7 +154,27 @@ lookupDesc scope name = lookupDesc (descParent scope) name
builtinTypeMap :: Map.Map String Desc builtinTypeMap :: Map.Map String Desc
builtinTypeMap = Map.fromList builtinTypeMap = Map.fromList
([(builtinTypeName t, DescBuiltinType t) | t <- builtinTypes] ++ ([(builtinTypeName t, DescBuiltinType t) | t <- builtinTypes] ++
[("List", DescBuiltinList)]) [("List", DescBuiltinList), ("id", DescAnnotation builtinId)])
builtinId = AnnotationDesc
{ annotationName = "id"
, annotationParent = DescFile FileDesc
{ fileName = "capnproto-builtins.capnp"
, fileImports = []
, fileAliases = []
, fileConstants = []
, fileEnums = []
, fileStructs = []
, fileInterfaces = []
, fileAnnotations = Map.empty
, fileMemberMap = Map.fromList [("id", Just $ DescAnnotation builtinId)]
, fileImportMap = Map.empty
, fileStatements = [DescAnnotation builtinId]
}
, annotationType = BuiltinType BuiltinText
, annotationAnnotations = Map.fromList [(idId, (builtinId, TextDesc idId))]
, annotationTargets = Set.fromList [minBound::AnnotationTarget .. maxBound::AnnotationTarget]
}
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
...@@ -283,6 +304,31 @@ compileType scope (TypeExpression n (param:moreParams)) = do ...@@ -283,6 +304,31 @@ compileType scope (TypeExpression n (param:moreParams)) = do
else makeError (declNamePos n) "'List' requires exactly one type parameter." else makeError (declNamePos n) "'List' requires exactly one type parameter."
_ -> makeError (declNamePos n) "Only the type 'List' can have type parameters." _ -> makeError (declNamePos n) "Only the type 'List' can have type parameters."
compileAnnotation :: Desc -> AnnotationTarget -> Annotation -> Status (AnnotationDesc, ValueDesc)
compileAnnotation scope kind (Annotation name (Located pos value)) = do
nameDesc <- lookupDesc scope name
annDesc <- case nameDesc of
DescAnnotation a -> return a
_ -> makeError (declNamePos name)
$ printf "'%s' is not an annotation." (declNameString name)
unless (Set.member kind (annotationTargets annDesc))
(makeError (declNamePos name)
$ printf "'%s' cannot be used on %s." (declNameString name) (show kind))
compiledValue <- compileValue pos (annotationType annDesc) value
return (annDesc, compiledValue)
compileAnnotationMap :: Desc -> AnnotationTarget -> [Annotation] -> Status AnnotationMap
compileAnnotationMap scope kind annotations = do
compiled <- doAll $ map (compileAnnotation scope kind) annotations
-- Makes a map entry for the annotation keyed by ID. Throws out annotations with no ID.
let makeMapEntry ann@(desc, _) =
case Map.lookup idId $ annotationAnnotations desc of
Just (_, TextDesc globalId) -> Just (globalId, ann)
_ -> Nothing
return $ Map.fromList $ mapMaybe makeMapEntry compiled
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
findDupesBy :: Ord a => (b -> a) -> [b] -> [[b]] findDupesBy :: Ord a => (b -> a) -> [b] -> [[b]]
...@@ -345,8 +391,8 @@ requireNoMoreThanOneFieldNumberLessThan name pos num fields = Active () errors w ...@@ -345,8 +391,8 @@ requireNoMoreThanOneFieldNumberLessThan name pos num fields = Active () errors w
extractFieldNumbers :: [Declaration] -> [Located Integer] extractFieldNumbers :: [Declaration] -> [Located Integer]
extractFieldNumbers decls = concat extractFieldNumbers decls = concat
([ num | FieldDecl _ num _ _ <- decls ] ([ num | FieldDecl _ num _ _ _ <- decls ]
:[ num:extractFieldNumbers uDecls | UnionDecl _ num uDecls <- decls ]) :[ num:extractFieldNumbers uDecls | UnionDecl _ num _ uDecls <- decls ])
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
...@@ -486,34 +532,22 @@ packFields fields unions = (finalState, finalUnionState, Map.fromList packedItem ...@@ -486,34 +532,22 @@ packFields fields unions = (finalState, finalUnionState, Map.fromList packedItem
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
-- For CompiledMemberStatus, the second parameter contains members that should be inserted into the data CompiledStatementStatus = CompiledStatementStatus String (Status Desc)
-- parent's map, e.g. fields defined in a union which should be considered members of the parent
-- struct as well. Usually (except in the case of unions) this map is empty.
data CompiledStatementStatus = CompiledMemberStatus String (Status Desc)
| CompiledOptionStatus (Status OptionAssignmentDesc)
toCompiledStatement :: CompiledStatementStatus -> Maybe CompiledStatement
toCompiledStatement (CompiledMemberStatus _ (Active desc _)) = Just (CompiledMember desc)
toCompiledStatement (CompiledOptionStatus (Active desc _)) = Just (CompiledOption desc)
toCompiledStatement _ = Nothing
compiledErrors (CompiledMemberStatus _ status) = statusErrors status compiledErrors (CompiledStatementStatus _ status) = statusErrors status
compiledErrors (CompiledOptionStatus status) = statusErrors status
compileChildDecls :: Desc -> [Declaration] compileChildDecls :: Desc -> [Declaration]
-> Status ([Desc], MemberMap, OptionMap, [CompiledStatement]) -> Status ([Desc], MemberMap)
compileChildDecls desc decls = Active (members, memberMap, options, statements) errors where compileChildDecls desc decls = Active (members, memberMap) errors where
compiledDecls = map (compileDecl desc) decls compiledDecls = map (compileDecl desc) decls
memberMap = Map.fromList memberPairs memberMap = Map.fromList memberPairs
members = [member | (_, Just member) <- memberPairs] members = [member | (_, Just member) <- memberPairs]
memberPairs = [(name, statusToMaybe status) | CompiledMemberStatus name status <- compiledDecls] memberPairs = [(name, statusToMaybe status)
options = Map.fromList [(optionName (optionAssignmentOption o), o) | CompiledStatementStatus name status <- compiledDecls]
| CompiledOptionStatus (Active o _) <- compiledDecls]
errors = concatMap compiledErrors compiledDecls errors = concatMap compiledErrors compiledDecls
statements = mapMaybe toCompiledStatement compiledDecls
compileDecl scope (AliasDecl (Located _ name) target) = compileDecl scope (AliasDecl (Located _ name) target) =
CompiledMemberStatus name (do CompiledStatementStatus name (do
targetDesc <- lookupDesc scope target targetDesc <- lookupDesc scope target
return (DescAlias AliasDesc return (DescAlias AliasDesc
{ aliasName = name { aliasName = name
...@@ -521,53 +555,57 @@ compileDecl scope (AliasDecl (Located _ name) target) = ...@@ -521,53 +555,57 @@ compileDecl scope (AliasDecl (Located _ name) target) =
, aliasTarget = targetDesc , aliasTarget = targetDesc
})) }))
compileDecl scope (ConstantDecl (Located _ name) t (Located valuePos value)) = compileDecl scope (ConstantDecl (Located _ name) t annotations (Located valuePos value)) =
CompiledMemberStatus name (do CompiledStatementStatus name (do
typeDesc <- compileType scope t typeDesc <- compileType scope t
valueDesc <- compileValue valuePos typeDesc value valueDesc <- compileValue valuePos typeDesc value
compiledAnnotations <- compileAnnotationMap scope ConstantAnnotation annotations
return (DescConstant ConstantDesc return (DescConstant ConstantDesc
{ constantName = name { constantName = name
, constantParent = scope , constantParent = scope
, constantType = typeDesc , constantType = typeDesc
, constantValue = valueDesc , constantValue = valueDesc
, constantAnnotations = compiledAnnotations
})) }))
compileDecl scope (EnumDecl (Located _ name) decls) = compileDecl scope (EnumDecl (Located _ name) annotations decls) =
CompiledMemberStatus name (feedback (\desc -> do CompiledStatementStatus name (feedback (\desc -> do
(members, memberMap, options, statements) <- compileChildDecls desc decls (members, memberMap) <- compileChildDecls desc decls
requireNoDuplicateNames decls requireNoDuplicateNames decls
let numbers = [ num | EnumValueDecl _ num _ <- decls ] let numbers = [ num | EnumValueDecl _ num _ <- decls ]
requireSequentialNumbering "Enum values" numbers requireSequentialNumbering "Enum values" numbers
requireOrdinalsInRange numbers requireOrdinalsInRange numbers
compiledAnnotations <- compileAnnotationMap scope EnumAnnotation annotations
return (DescEnum EnumDesc return (DescEnum EnumDesc
{ enumName = name { enumName = name
, enumParent = scope , enumParent = scope
, enumValues = [d | DescEnumValue d <- members] , enumValues = [d | DescEnumValue d <- members]
, enumOptions = options , enumAnnotations = compiledAnnotations
, enumMemberMap = memberMap , enumMemberMap = memberMap
, enumStatements = statements , enumStatements = members
}))) })))
compileDecl (DescEnum parent) (EnumValueDecl (Located _ name) (Located _ number) decls) = compileDecl scope@(DescEnum parent)
CompiledMemberStatus name (feedback (\desc -> do (EnumValueDecl (Located _ name) (Located _ number) annotations) =
(_, _, options, statements) <- compileChildDecls desc decls CompiledStatementStatus name (do
compiledAnnotations <- compileAnnotationMap scope EnumValueAnnotation annotations
return (DescEnumValue EnumValueDesc return (DescEnumValue EnumValueDesc
{ enumValueName = name { enumValueName = name
, enumValueParent = parent , enumValueParent = parent
, enumValueNumber = number , enumValueNumber = number
, enumValueOptions = options , enumValueAnnotations = compiledAnnotations
, enumValueStatements = statements }))
})))
compileDecl _ (EnumValueDecl (Located pos name) _ _) = compileDecl _ (EnumValueDecl (Located pos name) _ _) =
CompiledMemberStatus name (makeError pos "Enum values can only appear inside enums.") CompiledStatementStatus name (makeError pos "Enum values can only appear inside enums.")
compileDecl scope (StructDecl (Located _ name) decls) = compileDecl scope (StructDecl (Located _ name) annotations decls) =
CompiledMemberStatus name (feedback (\desc -> do CompiledStatementStatus name (feedback (\desc -> do
(members, memberMap, options, statements) <- compileChildDecls desc decls (members, memberMap) <- compileChildDecls desc decls
requireNoDuplicateNames decls requireNoDuplicateNames decls
let fieldNums = extractFieldNumbers decls let fieldNums = extractFieldNumbers decls
requireSequentialNumbering "Fields" fieldNums requireSequentialNumbering "Fields" fieldNums
requireOrdinalsInRange fieldNums requireOrdinalsInRange fieldNums
compiledAnnotations <- compileAnnotationMap scope StructAnnotation annotations
return (let return (let
fields = [d | DescField d <- members] fields = [d | DescField d <- members]
unions = [d | DescUnion d <- members] unions = [d | DescUnion d <- members]
...@@ -583,19 +621,21 @@ compileDecl scope (StructDecl (Located _ name) decls) = ...@@ -583,19 +621,21 @@ compileDecl scope (StructDecl (Located _ name) decls) =
, structNestedEnums = [d | DescEnum d <- members] , structNestedEnums = [d | DescEnum d <- members]
, structNestedStructs = [d | DescStruct d <- members] , structNestedStructs = [d | DescStruct d <- members]
, structNestedInterfaces = [d | DescInterface d <- members] , structNestedInterfaces = [d | DescInterface d <- members]
, structOptions = options , structAnnotations = compiledAnnotations
, structMemberMap = memberMap , structMemberMap = memberMap
, structStatements = statements , structStatements = members
, structFieldPackingMap = fieldPackingMap , structFieldPackingMap = fieldPackingMap
}))) })))
compileDecl (DescStruct parent) (UnionDecl (Located _ name) (Located numPos number) decls) = compileDecl scope@(DescStruct parent)
CompiledMemberStatus name (feedback (\desc -> do (UnionDecl (Located _ name) (Located numPos number) annotations decls) =
(members, memberMap, options, statements) <- compileChildDecls desc decls CompiledStatementStatus name (feedback (\desc -> do
(members, memberMap) <- compileChildDecls desc decls
let fields = [f | DescField f <- members] let fields = [f | DescField f <- members]
orderedFieldNumbers = List.sort $ map fieldNumber fields orderedFieldNumbers = List.sort $ map fieldNumber fields
discriminantMap = Map.fromList $ zip orderedFieldNumbers [0..] discriminantMap = Map.fromList $ zip orderedFieldNumbers [0..]
requireNoMoreThanOneFieldNumberLessThan name numPos number fields requireNoMoreThanOneFieldNumberLessThan name numPos number fields
compiledAnnotations <- compileAnnotationMap scope UnionAnnotation annotations
return (let return (let
(tagOffset, tagPacking) = structFieldPackingMap parent ! number (tagOffset, tagPacking) = structFieldPackingMap parent ! number
in DescUnion UnionDesc in DescUnion UnionDesc
...@@ -605,17 +645,17 @@ compileDecl (DescStruct parent) (UnionDecl (Located _ name) (Located numPos numb ...@@ -605,17 +645,17 @@ compileDecl (DescStruct parent) (UnionDecl (Located _ name) (Located numPos numb
, unionTagOffset = tagOffset , unionTagOffset = tagOffset
, unionTagPacking = tagPacking , unionTagPacking = tagPacking
, unionFields = fields , unionFields = fields
, unionOptions = options , unionAnnotations = compiledAnnotations
, unionMemberMap = memberMap , unionMemberMap = memberMap
, unionStatements = statements , unionStatements = members
, unionFieldDiscriminantMap = discriminantMap , unionFieldDiscriminantMap = discriminantMap
}))) })))
compileDecl _ (UnionDecl (Located pos name) _ _) = compileDecl _ (UnionDecl (Located pos name) _ _ _) =
CompiledMemberStatus name (makeError pos "Unions can only appear inside structs.") CompiledStatementStatus name (makeError pos "Unions can only appear inside structs.")
compileDecl scope compileDecl scope
(FieldDecl (Located pos name) (Located _ number) typeExp defaultValue) = (FieldDecl (Located pos name) (Located _ number) typeExp annotations defaultValue) =
CompiledMemberStatus name (do CompiledStatementStatus name (do
parent <- case scope of parent <- case scope of
DescStruct s -> return s DescStruct s -> return s
DescUnion u -> return (unionParent u) DescUnion u -> return (unionParent u)
...@@ -627,6 +667,7 @@ compileDecl scope ...@@ -627,6 +667,7 @@ compileDecl scope
defaultDesc <- case defaultValue of defaultDesc <- case defaultValue of
Just (Located defaultPos value) -> fmap Just (compileValue defaultPos typeDesc value) Just (Located defaultPos value) -> fmap Just (compileValue defaultPos typeDesc value)
Nothing -> return Nothing Nothing -> return Nothing
compiledAnnotations <- compileAnnotationMap scope FieldAnnotation annotations
return (let return (let
(offset, packing) = structFieldPackingMap parent ! number (offset, packing) = structFieldPackingMap parent ! number
in DescField FieldDesc in DescField FieldDesc
...@@ -638,16 +679,17 @@ compileDecl scope ...@@ -638,16 +679,17 @@ compileDecl scope
, fieldUnion = unionDesc , fieldUnion = unionDesc
, fieldType = typeDesc , fieldType = typeDesc
, fieldDefaultValue = defaultDesc , fieldDefaultValue = defaultDesc
, fieldOptions = Map.empty -- TODO , fieldAnnotations = compiledAnnotations
})) }))
compileDecl scope (InterfaceDecl (Located _ name) decls) = compileDecl scope (InterfaceDecl (Located _ name) annotations decls) =
CompiledMemberStatus name (feedback (\desc -> do CompiledStatementStatus name (feedback (\desc -> do
(members, memberMap, options, statements) <- compileChildDecls desc decls (members, memberMap) <- compileChildDecls desc decls
requireNoDuplicateNames decls requireNoDuplicateNames decls
let numbers = [ num | MethodDecl _ num _ _ _ <- decls ] let numbers = [ num | MethodDecl _ num _ _ _ <- decls ]
requireSequentialNumbering "Methods" numbers requireSequentialNumbering "Methods" numbers
requireOrdinalsInRange numbers requireOrdinalsInRange numbers
compiledAnnotations <- compileAnnotationMap scope InterfaceAnnotation annotations
return (DescInterface InterfaceDesc return (DescInterface InterfaceDesc
{ interfaceName = name { interfaceName = name
, interfaceParent = scope , interfaceParent = scope
...@@ -657,53 +699,62 @@ compileDecl scope (InterfaceDecl (Located _ name) decls) = ...@@ -657,53 +699,62 @@ compileDecl scope (InterfaceDecl (Located _ name) decls) =
, interfaceNestedEnums = [d | DescEnum d <- members] , interfaceNestedEnums = [d | DescEnum d <- members]
, interfaceNestedStructs = [d | DescStruct d <- members] , interfaceNestedStructs = [d | DescStruct d <- members]
, interfaceNestedInterfaces = [d | DescInterface d <- members] , interfaceNestedInterfaces = [d | DescInterface d <- members]
, interfaceOptions = options , interfaceAnnotations = compiledAnnotations
, interfaceMemberMap = memberMap , interfaceMemberMap = memberMap
, interfaceStatements = statements , interfaceStatements = members
}))) })))
compileDecl scope@(DescInterface parent) compileDecl scope@(DescInterface parent)
(MethodDecl (Located _ name) (Located _ number) params returnType decls) = (MethodDecl (Located _ name) (Located _ number) params returnType annotations) =
CompiledMemberStatus name (feedback (\desc -> do CompiledStatementStatus name (feedback (\desc -> do
paramDescs <- doAll (map (compileParam scope) params) paramDescs <- doAll (map (compileParam desc) (zip [0..] params))
returnTypeDesc <- compileType scope returnType returnTypeDesc <- compileType scope returnType
(_, _, options, statements) <- compileChildDecls desc decls compiledAnnotations <- compileAnnotationMap scope MethodAnnotation annotations
return (DescMethod MethodDesc return (DescMethod MethodDesc
{ methodName = name { methodName = name
, methodParent = parent , methodParent = parent
, methodNumber = number , methodNumber = number
, methodParams = paramDescs , methodParams = paramDescs
, methodReturnType = returnTypeDesc , methodReturnType = returnTypeDesc
, methodOptions = options , methodAnnotations = compiledAnnotations
, methodStatements = statements
}))) })))
compileDecl _ (MethodDecl (Located pos name) _ _ _ _) = compileDecl _ (MethodDecl (Located pos name) _ _ _ _) =
CompiledMemberStatus name (makeError pos "Methods can only appear inside interfaces.") CompiledStatementStatus name (makeError pos "Methods can only appear inside interfaces.")
compileDecl scope (OptionDecl name (Located valuePos value)) = compileDecl scope (AnnotationDecl (Located _ name) typeExp annotations targets) =
CompiledOptionStatus (do CompiledStatementStatus name (do
uncheckedOptionDesc <- lookupDesc scope name typeDesc <- compileType scope typeExp
optionDesc <- case uncheckedOptionDesc of compiledAnnotations <- compileAnnotationMap scope AnnotationAnnotation annotations
(DescOption d) -> return d return (DescAnnotation AnnotationDesc
_ -> makeError (declNamePos name) (printf "'%s' is not an option." (declNameString name)) { annotationName = name
valueDesc <- compileValue valuePos (optionType optionDesc) value , annotationParent = scope
return OptionAssignmentDesc , annotationType = typeDesc
{ optionAssignmentParent = scope , annotationAnnotations = compiledAnnotations
, optionAssignmentOption = optionDesc , annotationTargets = Set.fromList targets
, optionAssignmentValue = valueDesc }))
})
compileParam scope (name, typeExp, defaultValue) = do compileParam scope@(DescMethod parent)
(ordinal, ParamDecl name typeExp annotations defaultValue) = do
typeDesc <- compileType scope typeExp typeDesc <- compileType scope typeExp
defaultDesc <- case defaultValue of defaultDesc <- case defaultValue of
Just (Located pos value) -> fmap Just (compileValue pos typeDesc value) Just (Located pos value) -> fmap Just (compileValue pos typeDesc value)
Nothing -> return Nothing Nothing -> return Nothing
return (name, typeDesc, defaultDesc) compiledAnnotations <- compileAnnotationMap scope ParamAnnotation annotations
return ParamDesc
compileFile name decls importMap = { paramName = name
, paramParent = parent
, paramNumber = ordinal
, paramType = typeDesc
, paramDefaultValue = defaultDesc
, paramAnnotations = compiledAnnotations
}
compileParam _ _ = error "scope of parameter was not a method"
compileFile name decls annotations importMap =
feedback (\desc -> do feedback (\desc -> do
(members, memberMap, options, statements) <- compileChildDecls (DescFile desc) decls (members, memberMap) <- compileChildDecls (DescFile desc) decls
requireNoDuplicateNames decls requireNoDuplicateNames decls
compiledAnnotations <- compileAnnotationMap (DescFile desc) FileAnnotation annotations
return FileDesc return FileDesc
{ fileName = name { fileName = name
, fileImports = Map.elems importMap , fileImports = Map.elems importMap
...@@ -712,10 +763,10 @@ compileFile name decls importMap = ...@@ -712,10 +763,10 @@ compileFile name decls importMap =
, fileEnums = [d | DescEnum d <- members] , fileEnums = [d | DescEnum d <- members]
, fileStructs = [d | DescStruct d <- members] , fileStructs = [d | DescStruct d <- members]
, fileInterfaces = [d | DescInterface d <- members] , fileInterfaces = [d | DescInterface d <- members]
, fileOptions = options , fileAnnotations = compiledAnnotations
, fileMemberMap = memberMap , fileMemberMap = memberMap
, fileImportMap = importMap , fileImportMap = importMap
, fileStatements = statements , fileStatements = members
}) })
dedup :: Ord a => [a] -> [a] dedup :: Ord a => [a] -> [a]
...@@ -729,7 +780,7 @@ emptyFileDesc filename = FileDesc ...@@ -729,7 +780,7 @@ emptyFileDesc filename = FileDesc
, fileEnums = [] , fileEnums = []
, fileStructs = [] , fileStructs = []
, fileInterfaces = [] , fileInterfaces = []
, fileOptions = Map.empty , fileAnnotations = Map.empty
, fileMemberMap = Map.empty , fileMemberMap = Map.empty
, fileImportMap = Map.empty , fileImportMap = Map.empty
, fileStatements = [] , fileStatements = []
...@@ -741,7 +792,7 @@ parseAndCompileFile :: Monad m ...@@ -741,7 +792,7 @@ parseAndCompileFile :: Monad m
-> (String -> m (Either FileDesc String)) -- Callback to import other files. -> (String -> m (Either FileDesc String)) -- Callback to import other files.
-> m (Status FileDesc) -- Compiled file and/or errors. -> m (Status FileDesc) -- Compiled file and/or errors.
parseAndCompileFile filename text importCallback = do parseAndCompileFile filename text importCallback = do
let (decls, parseErrors) = parseFile filename text let (decls, annotations, parseErrors) = parseFile filename text
importNames = dedup $ concatMap declImports decls importNames = dedup $ concatMap declImports decls
doImport (Located pos name) = do doImport (Located pos name) = do
result <- importCallback name result <- importCallback name
...@@ -773,4 +824,4 @@ parseAndCompileFile filename text importCallback = do ...@@ -773,4 +824,4 @@ parseAndCompileFile filename text importCallback = do
imports <- doAll importStatuses imports <- doAll importStatuses
-- Compile the file! -- Compile the file!
compileFile filename decls $ Map.fromList imports) compileFile filename decls annotations $ Map.fromList imports)
...@@ -45,6 +45,10 @@ typeImports :: TypeExpression -> [Located String] ...@@ -45,6 +45,10 @@ typeImports :: TypeExpression -> [Located String]
typeImports (TypeExpression name params) = typeImports (TypeExpression name params) =
maybeToList (declNameImport name) ++ concatMap typeImports params maybeToList (declNameImport name) ++ concatMap typeImports params
data Annotation = Annotation DeclName (Located FieldValue) deriving(Show)
annotationImports (Annotation name _) = maybeToList $ declNameImport name
data FieldValue = VoidFieldValue data FieldValue = VoidFieldValue
| BoolFieldValue Bool | BoolFieldValue Bool
| IntegerFieldValue Integer | IntegerFieldValue Integer
...@@ -56,43 +60,75 @@ data FieldValue = VoidFieldValue ...@@ -56,43 +60,75 @@ data FieldValue = VoidFieldValue
| UnionFieldValue String FieldValue | UnionFieldValue String FieldValue
deriving (Show) deriving (Show)
data ParamDecl = ParamDecl String TypeExpression [Annotation] (Maybe (Located FieldValue))
deriving (Show)
paramImports (ParamDecl _ t ann _) = typeImports t ++ concatMap annotationImports ann
data AnnotationTarget = FileAnnotation
| ConstantAnnotation
| EnumAnnotation
| EnumValueAnnotation
| StructAnnotation
| FieldAnnotation
| UnionAnnotation
| InterfaceAnnotation
| MethodAnnotation
| ParamAnnotation
| AnnotationAnnotation
deriving(Eq, Ord, Bounded, Enum)
instance Show AnnotationTarget where
show FileAnnotation = "file"
show ConstantAnnotation = "const"
show EnumAnnotation = "enum"
show EnumValueAnnotation = "enumerant"
show StructAnnotation = "struct"
show FieldAnnotation = "field"
show UnionAnnotation = "union"
show InterfaceAnnotation = "interface"
show MethodAnnotation = "method"
show ParamAnnotation = "param"
show AnnotationAnnotation = "annotation"
data Declaration = AliasDecl (Located String) DeclName data Declaration = AliasDecl (Located String) DeclName
| ConstantDecl (Located String) TypeExpression (Located FieldValue) | ConstantDecl (Located String) TypeExpression [Annotation] (Located FieldValue)
| EnumDecl (Located String) [Declaration] | EnumDecl (Located String) [Annotation] [Declaration]
| EnumValueDecl (Located String) (Located Integer) [Declaration] | EnumValueDecl (Located String) (Located Integer) [Annotation]
| StructDecl (Located String) [Declaration] | StructDecl (Located String) [Annotation] [Declaration]
| FieldDecl (Located String) (Located Integer) | FieldDecl (Located String) (Located Integer)
TypeExpression (Maybe (Located FieldValue)) TypeExpression [Annotation] (Maybe (Located FieldValue))
| UnionDecl (Located String) (Located Integer) [Declaration] | UnionDecl (Located String) (Located Integer) [Annotation] [Declaration]
| InterfaceDecl (Located String) [Declaration] | InterfaceDecl (Located String) [Annotation] [Declaration]
| MethodDecl (Located String) (Located Integer) | MethodDecl (Located String) (Located Integer) [ParamDecl]
[(String, TypeExpression, Maybe (Located FieldValue))] TypeExpression [Annotation]
TypeExpression [Declaration] | AnnotationDecl (Located String) TypeExpression [Annotation] [AnnotationTarget]
| OptionDecl DeclName (Located FieldValue)
deriving (Show) deriving (Show)
declarationName :: Declaration -> Maybe (Located String) declarationName :: Declaration -> Maybe (Located String)
declarationName (AliasDecl n _) = Just n declarationName (AliasDecl n _) = Just n
declarationName (ConstantDecl n _ _) = Just n declarationName (ConstantDecl n _ _ _) = Just n
declarationName (EnumDecl n _) = Just n declarationName (EnumDecl n _ _) = Just n
declarationName (EnumValueDecl n _ _) = Just n declarationName (EnumValueDecl n _ _) = Just n
declarationName (StructDecl n _) = Just n declarationName (StructDecl n _ _) = Just n
declarationName (FieldDecl n _ _ _) = Just n declarationName (FieldDecl n _ _ _ _) = Just n
declarationName (UnionDecl n _ _) = Just n declarationName (UnionDecl n _ _ _) = Just n
declarationName (InterfaceDecl n _) = Just n declarationName (InterfaceDecl n _ _) = Just n
declarationName (MethodDecl n _ _ _ _) = Just n declarationName (MethodDecl n _ _ _ _) = Just n
declarationName (OptionDecl _ _) = Nothing declarationName (AnnotationDecl n _ _ _) = Just n
declImports :: Declaration -> [Located String] declImports :: Declaration -> [Located String]
declImports (AliasDecl _ name) = maybeToList $ declNameImport name declImports (AliasDecl _ name) = maybeToList (declNameImport name)
declImports (ConstantDecl _ t _) = typeImports t declImports (ConstantDecl _ t ann _) = typeImports t ++ concatMap annotationImports ann
declImports (EnumDecl _ decls) = concatMap declImports decls declImports (EnumDecl _ ann decls) = concatMap annotationImports ann ++ concatMap declImports decls
declImports (EnumValueDecl _ _ decls) = concatMap declImports decls declImports (EnumValueDecl _ _ ann) = concatMap annotationImports ann
declImports (StructDecl _ decls) = concatMap declImports decls declImports (StructDecl _ ann decls) = concatMap annotationImports ann ++
declImports (FieldDecl _ _ t _) = typeImports t concatMap declImports decls
declImports (UnionDecl _ _ decls) = concatMap declImports decls declImports (FieldDecl _ _ t ann _) = typeImports t ++ concatMap annotationImports ann
declImports (InterfaceDecl _ decls) = concatMap declImports decls declImports (UnionDecl _ _ ann decls) = concatMap annotationImports ann ++
declImports (MethodDecl _ _ params t decls) = concatMap declImports decls
concat [paramsImports, typeImports t, concatMap declImports decls] where declImports (InterfaceDecl _ ann decls) = concatMap annotationImports ann ++
paramsImports = concat [typeImports pt | (_, pt, _) <- params] concatMap declImports decls
declImports (OptionDecl name _) = maybeToList $ declNameImport name declImports (MethodDecl _ _ params t ann) =
concat [concatMap paramImports params, typeImports t, concatMap annotationImports ann]
declImports (AnnotationDecl _ t ann _) = typeImports t ++ concatMap annotationImports ann
...@@ -48,7 +48,7 @@ keywords = ...@@ -48,7 +48,7 @@ keywords =
, (StructKeyword, "struct") , (StructKeyword, "struct")
, (UnionKeyword, "union") , (UnionKeyword, "union")
, (InterfaceKeyword, "interface") , (InterfaceKeyword, "interface")
, (OptionKeyword, "option") , (AnnotationKeyword, "annotation")
] ]
languageDef :: T.LanguageDef st languageDef :: T.LanguageDef st
...@@ -114,15 +114,17 @@ tokenSequence = do ...@@ -114,15 +114,17 @@ tokenSequence = do
token :: Parser Token token :: Parser Token
token = keyword token = keyword
<|> identifier <|> identifier
<|> liftM ParenthesizedList (parens (sepBy tokenSequence (symbol ","))) <|> liftM ParenthesizedList (parens (sepBy tokenSequence (symbol ",")))
<|> liftM BracketedList (brackets (sepBy tokenSequence (symbol ","))) <|> liftM BracketedList (brackets (sepBy tokenSequence (symbol ",")))
<|> liftM toLiteral naturalOrFloat <|> liftM toLiteral naturalOrFloat
<|> liftM LiteralString stringLiteral <|> liftM LiteralString stringLiteral
<|> liftM (const AtSign) (symbol "@") <|> liftM (const AtSign) (symbol "@")
<|> liftM (const Colon) (symbol ":") <|> liftM (const Colon) (symbol ":")
<|> liftM (const Period) (symbol ".") <|> liftM (const DollarSign) (symbol "$")
<|> liftM (const EqualsSign) (symbol "=") <|> liftM (const Period) (symbol ".")
<|> liftM (const MinusSign) (symbol "-") <|> liftM (const EqualsSign) (symbol "=")
<|> liftM (const MinusSign) (symbol "-")
<|> liftM (const Asterisk) (symbol "*")
<|> liftM (const ExclamationPoint) (symbol "!") <|> liftM (const ExclamationPoint) (symbol "!")
<?> "token" <?> "token"
......
...@@ -42,9 +42,11 @@ tokenErrorString (LiteralFloat f) = "float literal " ++ show f ...@@ -42,9 +42,11 @@ tokenErrorString (LiteralFloat f) = "float literal " ++ show f
tokenErrorString (LiteralString s) = "string literal " ++ show s tokenErrorString (LiteralString s) = "string literal " ++ show s
tokenErrorString AtSign = "\"@\"" tokenErrorString AtSign = "\"@\""
tokenErrorString Colon = "\":\"" tokenErrorString Colon = "\":\""
tokenErrorString DollarSign = "\"$\""
tokenErrorString Period = "\".\"" tokenErrorString Period = "\".\""
tokenErrorString EqualsSign = "\"=\"" tokenErrorString EqualsSign = "\"=\""
tokenErrorString MinusSign = "\"-\"" tokenErrorString MinusSign = "\"-\""
tokenErrorString Asterisk = "\"*\""
tokenErrorString ExclamationPoint = "\"!\"" tokenErrorString ExclamationPoint = "\"!\""
tokenErrorString VoidKeyword = "keyword \"void\"" tokenErrorString VoidKeyword = "keyword \"void\""
tokenErrorString TrueKeyword = "keyword \"true\"" tokenErrorString TrueKeyword = "keyword \"true\""
...@@ -62,7 +64,7 @@ tokenErrorString EnumKeyword = "keyword \"enum\"" ...@@ -62,7 +64,7 @@ tokenErrorString EnumKeyword = "keyword \"enum\""
tokenErrorString StructKeyword = "keyword \"struct\"" tokenErrorString StructKeyword = "keyword \"struct\""
tokenErrorString UnionKeyword = "keyword \"union\"" tokenErrorString UnionKeyword = "keyword \"union\""
tokenErrorString InterfaceKeyword = "keyword \"interface\"" tokenErrorString InterfaceKeyword = "keyword \"interface\""
tokenErrorString OptionKeyword = "keyword \"option\"" tokenErrorString AnnotationKeyword = "keyword \"annotation\""
type TokenParser = Parsec [Located Token] [ParseError] type TokenParser = Parsec [Located Token] [ParseError]
...@@ -105,9 +107,11 @@ literalVoid = tokenParser (matchSimpleToken VoidKeyword) <?> "\"void\"" ...@@ -105,9 +107,11 @@ literalVoid = tokenParser (matchSimpleToken VoidKeyword) <?> "\"void\""
atSign = tokenParser (matchSimpleToken AtSign) <?> "\"@\"" atSign = tokenParser (matchSimpleToken AtSign) <?> "\"@\""
colon = tokenParser (matchSimpleToken Colon) <?> "\":\"" colon = tokenParser (matchSimpleToken Colon) <?> "\":\""
dollarSign = tokenParser (matchSimpleToken DollarSign) <?> "\"$\""
period = tokenParser (matchSimpleToken Period) <?> "\".\"" period = tokenParser (matchSimpleToken Period) <?> "\".\""
equalsSign = tokenParser (matchSimpleToken EqualsSign) <?> "\"=\"" equalsSign = tokenParser (matchSimpleToken EqualsSign) <?> "\"=\""
minusSign = tokenParser (matchSimpleToken MinusSign) <?> "\"=\"" minusSign = tokenParser (matchSimpleToken MinusSign) <?> "\"-\""
asterisk = tokenParser (matchSimpleToken Asterisk) <?> "\"*\""
importKeyword = tokenParser (matchSimpleToken ImportKeyword) <?> "\"import\"" importKeyword = tokenParser (matchSimpleToken ImportKeyword) <?> "\"import\""
usingKeyword = tokenParser (matchSimpleToken UsingKeyword) <?> "\"using\"" usingKeyword = tokenParser (matchSimpleToken UsingKeyword) <?> "\"using\""
constKeyword = tokenParser (matchSimpleToken ConstKeyword) <?> "\"const\"" constKeyword = tokenParser (matchSimpleToken ConstKeyword) <?> "\"const\""
...@@ -115,7 +119,8 @@ enumKeyword = tokenParser (matchSimpleToken EnumKeyword) <?> "\"enum\"" ...@@ -115,7 +119,8 @@ enumKeyword = tokenParser (matchSimpleToken EnumKeyword) <?> "\"enum\""
structKeyword = tokenParser (matchSimpleToken StructKeyword) <?> "\"struct\"" structKeyword = tokenParser (matchSimpleToken StructKeyword) <?> "\"struct\""
unionKeyword = tokenParser (matchSimpleToken UnionKeyword) <?> "\"union\"" unionKeyword = tokenParser (matchSimpleToken UnionKeyword) <?> "\"union\""
interfaceKeyword = tokenParser (matchSimpleToken InterfaceKeyword) <?> "\"interface\"" interfaceKeyword = tokenParser (matchSimpleToken InterfaceKeyword) <?> "\"interface\""
optionKeyword = tokenParser (matchSimpleToken OptionKeyword) <?> "\"option\"" annotationKeyword = tokenParser (matchSimpleToken AnnotationKeyword) <?> "\"annotation\""
onKeyword = tokenParser (matchSimpleToken OnKeyword) <?> "\"on\""
parenthesizedList parser = do parenthesizedList parser = do
items <- tokenParser (matchUnary ParenthesizedList) items <- tokenParser (matchUnary ParenthesizedList)
...@@ -153,9 +158,19 @@ nameWithOrdinal = do ...@@ -153,9 +158,19 @@ nameWithOrdinal = do
ordinal <- located literalInt ordinal <- located literalInt
return (name, ordinal) return (name, ordinal)
topLine :: Maybe [Located Statement] -> TokenParser Declaration annotation :: TokenParser Annotation
topLine Nothing = optionDecl <|> aliasDecl <|> constantDecl annotation = do
topLine (Just statements) = typeDecl statements dollarSign
name <- declName
value <- located (try (parenthesized fieldValue)
<|> liftM RecordFieldValue (parenthesizedList fieldAssignment)
<|> return VoidFieldValue)
return (Annotation name value)
topLine :: Maybe [Located Statement] -> TokenParser (Either Declaration Annotation)
topLine Nothing = liftM Left (aliasDecl <|> constantDecl <|> annotationDecl)
<|> liftM Right annotation
topLine (Just statements) = liftM Left $ typeDecl statements
aliasDecl = do aliasDecl = do
usingKeyword usingKeyword
...@@ -169,9 +184,10 @@ constantDecl = do ...@@ -169,9 +184,10 @@ constantDecl = do
name <- located varIdentifier name <- located varIdentifier
colon colon
typeName <- typeExpression typeName <- typeExpression
annotations <- many annotation
equalsSign equalsSign
value <- located fieldValue value <- located fieldValue
return (ConstantDecl name typeName value) return (ConstantDecl name typeName annotations value)
typeDecl statements = enumDecl statements typeDecl statements = enumDecl statements
<|> structDecl statements <|> structDecl statements
...@@ -180,48 +196,48 @@ typeDecl statements = enumDecl statements ...@@ -180,48 +196,48 @@ typeDecl statements = enumDecl statements
enumDecl statements = do enumDecl statements = do
enumKeyword enumKeyword
name <- located typeIdentifier name <- located typeIdentifier
annotations <- many annotation
children <- parseBlock enumLine statements children <- parseBlock enumLine statements
return (EnumDecl name children) return (EnumDecl name annotations children)
enumLine :: Maybe [Located Statement] -> TokenParser Declaration enumLine :: Maybe [Located Statement] -> TokenParser Declaration
enumLine Nothing = optionDecl <|> enumValueDecl [] enumLine Nothing = enumValueDecl
enumLine (Just statements) = enumValueDecl statements enumLine (Just _) = fail "Blocks not allowed here."
enumValueDecl statements = do enumValueDecl = do
(name, value) <- nameWithOrdinal (name, value) <- nameWithOrdinal
children <- parseBlock enumValueLine statements annotations <- many annotation
return (EnumValueDecl name value children) return (EnumValueDecl name value annotations)
enumValueLine :: Maybe [Located Statement] -> TokenParser Declaration
enumValueLine Nothing = optionDecl
enumValueLine (Just _) = fail "Blocks not allowed here."
structDecl statements = do structDecl statements = do
structKeyword structKeyword
name <- located typeIdentifier name <- located typeIdentifier
annotations <- many annotation
children <- parseBlock structLine statements children <- parseBlock structLine statements
return (StructDecl name children) return (StructDecl name annotations children)
structLine :: Maybe [Located Statement] -> TokenParser Declaration structLine :: Maybe [Located Statement] -> TokenParser Declaration
structLine Nothing = optionDecl <|> constantDecl <|> fieldDecl structLine Nothing = constantDecl <|> fieldDecl <|> annotationDecl
structLine (Just statements) = typeDecl statements <|> unionDecl statements <|> unionDecl statements structLine (Just statements) = typeDecl statements <|> unionDecl statements <|> unionDecl statements
unionDecl statements = do unionDecl statements = do
(name, ordinal) <- nameWithOrdinal (name, ordinal) <- nameWithOrdinal
unionKeyword unionKeyword
annotations <- many annotation
children <- parseBlock unionLine statements children <- parseBlock unionLine statements
return (UnionDecl name ordinal children) return (UnionDecl name ordinal annotations children)
unionLine :: Maybe [Located Statement] -> TokenParser Declaration unionLine :: Maybe [Located Statement] -> TokenParser Declaration
unionLine Nothing = optionDecl <|> fieldDecl unionLine Nothing = fieldDecl
unionLine (Just _) = fail "Blocks not allowed here." unionLine (Just _) = fail "Blocks not allowed here."
fieldDecl = do fieldDecl = do
(name, ordinal) <- nameWithOrdinal (name, ordinal) <- nameWithOrdinal
colon colon
t <- typeExpression t <- typeExpression
annotations <- many annotation
value <- optionMaybe (equalsSign >> located fieldValue) value <- optionMaybe (equalsSign >> located fieldValue)
return (FieldDecl name ordinal t value) return (FieldDecl name ordinal t annotations value)
negativeFieldValue = liftM (IntegerFieldValue . negate) literalInt negativeFieldValue = liftM (IntegerFieldValue . negate) literalInt
<|> liftM (FloatFieldValue . negate) literalFloat <|> liftM (FloatFieldValue . negate) literalFloat
...@@ -252,38 +268,61 @@ fieldAssignment = do ...@@ -252,38 +268,61 @@ fieldAssignment = do
interfaceDecl statements = do interfaceDecl statements = do
interfaceKeyword interfaceKeyword
name <- located typeIdentifier name <- located typeIdentifier
annotations <- many annotation
children <- parseBlock interfaceLine statements children <- parseBlock interfaceLine statements
return (InterfaceDecl name children) return (InterfaceDecl name annotations children)
interfaceLine :: Maybe [Located Statement] -> TokenParser Declaration interfaceLine :: Maybe [Located Statement] -> TokenParser Declaration
interfaceLine Nothing = optionDecl <|> constantDecl <|> methodDecl [] interfaceLine Nothing = constantDecl <|> methodDecl <|> annotationDecl
interfaceLine (Just statements) = typeDecl statements <|> methodDecl statements interfaceLine (Just statements) = typeDecl statements
methodDecl statements = do methodDecl = do
(name, ordinal) <- nameWithOrdinal (name, ordinal) <- nameWithOrdinal
params <- parenthesizedList paramDecl params <- parenthesizedList paramDecl
colon colon
t <- typeExpression t <- typeExpression
children <- parseBlock methodLine statements annotations <- many annotation
return (MethodDecl name ordinal params t children) return (MethodDecl name ordinal params t annotations)
paramDecl = do paramDecl = do
name <- varIdentifier name <- varIdentifier
colon colon
t <- typeExpression t <- typeExpression
annotations <- many annotation
value <- optionMaybe (equalsSign >> located fieldValue) value <- optionMaybe (equalsSign >> located fieldValue)
return (name, t, value) return (ParamDecl name t annotations value)
methodLine :: Maybe [Located Statement] -> TokenParser Declaration annotationDecl = do
methodLine Nothing = optionDecl annotationKeyword
methodLine (Just _) = fail "Blocks not allowed here." name <- located varIdentifier
colon
optionDecl = do t <- typeExpression
optionKeyword annotations <- many annotation
name <- declName onKeyword
equalsSign targets <- try (parenthesized asterisk >> return allAnnotationTargets)
value <- located fieldValue <|> parenthesizedList annotationTarget
return (OptionDecl name value) return (AnnotationDecl name t annotations targets)
allAnnotationTargets = [minBound::AnnotationTarget .. maxBound::AnnotationTarget]
annotationTarget = (constKeyword >> return ConstantAnnotation)
<|> (enumKeyword >> return EnumAnnotation)
<|> (structKeyword >> return StructAnnotation)
<|> (unionKeyword >> return UnionAnnotation)
<|> (interfaceKeyword >> return InterfaceAnnotation)
<|> (annotationKeyword >> return AnnotationAnnotation)
<|> (do
name <- varIdentifier
case name of
"file" -> return FileAnnotation
"enumerant" -> return EnumValueAnnotation
"field" -> return FieldAnnotation
"method" -> return MethodAnnotation
"parameter" -> return ParamAnnotation
_ -> fail "" <?> annotationTargetList)
<?> annotationTargetList
annotationTargetList = "const, enum, enumerant, struct, field, union, interface, method, \
\parameter, or annotation"
extractErrors :: Either ParseError (a, [ParseError]) -> [ParseError] extractErrors :: Either ParseError (a, [ParseError]) -> [ParseError]
extractErrors (Left err) = [err] extractErrors (Left err) = [err]
...@@ -322,21 +361,23 @@ parseCollectingErrors parser tokenSequence = runParser parser' [] "" tokens wher ...@@ -322,21 +361,23 @@ parseCollectingErrors parser tokenSequence = runParser parser' [] "" tokens wher
errors <- getState errors <- getState
return (result, errors) return (result, errors)
parseStatement :: (Maybe [Located Statement] -> TokenParser Declaration) parseStatement :: (Maybe [Located Statement] -> TokenParser a)
-> Located Statement -> Located Statement
-> Either ParseError (Declaration, [ParseError]) -> Either ParseError (a, [ParseError])
parseStatement parser (Located _ (Line tokens)) = parseStatement parser (Located _ (Line tokens)) =
parseCollectingErrors (parser Nothing) tokens parseCollectingErrors (parser Nothing) tokens
parseStatement parser (Located _ (Block tokens statements)) = parseStatement parser (Located _ (Block tokens statements)) =
parseCollectingErrors (parser (Just statements)) tokens parseCollectingErrors (parser (Just statements)) tokens
parseFileTokens :: [Located Statement] -> ([Declaration], [ParseError]) parseFileTokens :: [Located Statement] -> ([Declaration], [Annotation], [ParseError])
parseFileTokens statements = (decls, errors) where parseFileTokens statements = (decls, annotations, errors) where
results :: [Either ParseError (Either Declaration Annotation, [ParseError])]
results = map (parseStatement topLine) statements results = map (parseStatement topLine) statements
errors = concatMap extractErrors results errors = concatMap extractErrors results
decls = [ result | Right (result, _) <- results ] decls = [ decl | Right (Left decl, _) <- results ]
annotations = [ ann | Right (Right ann, _) <- results ]
parseFile :: String -> String -> ([Declaration], [ParseError]) parseFile :: String -> String -> ([Declaration], [Annotation], [ParseError])
parseFile filename text = case parse lexer filename text of parseFile filename text = case parse lexer filename text of
Left e -> ([], [e]) Left e -> ([], [], [e])
Right statements -> parseFileTokens statements Right statements -> parseFileTokens statements
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
module Semantics where module Semantics where
import qualified Data.Map as Map import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.List as List import qualified Data.List as List
import qualified Data.Maybe as Maybe import qualified Data.Maybe as Maybe
import Data.Int (Int8, Int16, Int32, Int64) import Data.Int (Int8, Int16, Int32, Int64)
...@@ -32,11 +33,14 @@ import Data.Char (chr) ...@@ -32,11 +33,14 @@ import Data.Char (chr)
import Text.Printf(printf) import Text.Printf(printf)
import Control.Monad(join) import Control.Monad(join)
import Util(delimit) import Util(delimit)
import Grammar(AnnotationTarget(..))
-- Field counts are 16-bit, therefore there cannot be more than 65535 fields, therefore the max -- Field counts are 16-bit, therefore there cannot be more than 65535 fields, therefore the max
-- ordinal is 65534. -- ordinal is 65534.
maxOrdinal = 65534 :: Integer maxOrdinal = 65534 :: Integer
idId = "com.capnproto.compiler.builtin.id"
type ByteString = [Word8] type ByteString = [Word8]
data Desc = DescFile FileDesc data Desc = DescFile FileDesc
...@@ -49,7 +53,8 @@ data Desc = DescFile FileDesc ...@@ -49,7 +53,8 @@ data Desc = DescFile FileDesc
| DescField FieldDesc | DescField FieldDesc
| DescInterface InterfaceDesc | DescInterface InterfaceDesc
| DescMethod MethodDesc | DescMethod MethodDesc
| DescOption OptionDesc | DescParam ParamDesc
| DescAnnotation AnnotationDesc
| DescBuiltinType BuiltinType | DescBuiltinType BuiltinType
| DescBuiltinList | DescBuiltinList
...@@ -63,7 +68,8 @@ descName (DescUnion d) = unionName d ...@@ -63,7 +68,8 @@ descName (DescUnion d) = unionName d
descName (DescField d) = fieldName d descName (DescField d) = fieldName d
descName (DescInterface d) = interfaceName d descName (DescInterface d) = interfaceName d
descName (DescMethod d) = methodName d descName (DescMethod d) = methodName d
descName (DescOption d) = optionName d descName (DescParam d) = paramName d
descName (DescAnnotation d) = annotationName d
descName (DescBuiltinType d) = builtinTypeName d descName (DescBuiltinType d) = builtinTypeName d
descName DescBuiltinList = "List" descName DescBuiltinList = "List"
...@@ -77,7 +83,8 @@ descParent (DescUnion d) = DescStruct (unionParent d) ...@@ -77,7 +83,8 @@ descParent (DescUnion d) = DescStruct (unionParent d)
descParent (DescField d) = DescStruct (fieldParent d) descParent (DescField d) = DescStruct (fieldParent d)
descParent (DescInterface d) = interfaceParent d descParent (DescInterface d) = interfaceParent d
descParent (DescMethod d) = DescInterface (methodParent d) descParent (DescMethod d) = DescInterface (methodParent d)
descParent (DescOption d) = optionParent d descParent (DescParam d) = DescMethod (paramParent d)
descParent (DescAnnotation d) = annotationParent d
descParent (DescBuiltinType _) = error "Builtin type has no parent." descParent (DescBuiltinType _) = error "Builtin type has no parent."
descParent DescBuiltinList = error "Builtin type has no parent." descParent DescBuiltinList = error "Builtin type has no parent."
...@@ -263,10 +270,10 @@ data FileDesc = FileDesc ...@@ -263,10 +270,10 @@ data FileDesc = FileDesc
, fileEnums :: [EnumDesc] , fileEnums :: [EnumDesc]
, fileStructs :: [StructDesc] , fileStructs :: [StructDesc]
, fileInterfaces :: [InterfaceDesc] , fileInterfaces :: [InterfaceDesc]
, fileOptions :: OptionMap , fileAnnotations :: AnnotationMap
, fileMemberMap :: MemberMap , fileMemberMap :: MemberMap
, fileImportMap :: Map.Map String FileDesc , fileImportMap :: Map.Map String FileDesc
, fileStatements :: [CompiledStatement] , fileStatements :: [Desc]
} }
data AliasDesc = AliasDesc data AliasDesc = AliasDesc
...@@ -279,6 +286,7 @@ data ConstantDesc = ConstantDesc ...@@ -279,6 +286,7 @@ data ConstantDesc = ConstantDesc
{ constantName :: String { constantName :: String
, constantParent :: Desc , constantParent :: Desc
, constantType :: TypeDesc , constantType :: TypeDesc
, constantAnnotations :: AnnotationMap
, constantValue :: ValueDesc , constantValue :: ValueDesc
} }
...@@ -286,17 +294,16 @@ data EnumDesc = EnumDesc ...@@ -286,17 +294,16 @@ data EnumDesc = EnumDesc
{ enumName :: String { enumName :: String
, enumParent :: Desc , enumParent :: Desc
, enumValues :: [EnumValueDesc] , enumValues :: [EnumValueDesc]
, enumOptions :: OptionMap , enumAnnotations :: AnnotationMap
, enumMemberMap :: MemberMap , enumMemberMap :: MemberMap
, enumStatements :: [CompiledStatement] , enumStatements :: [Desc]
} }
data EnumValueDesc = EnumValueDesc data EnumValueDesc = EnumValueDesc
{ enumValueName :: String { enumValueName :: String
, enumValueParent :: EnumDesc , enumValueParent :: EnumDesc
, enumValueNumber :: Integer , enumValueNumber :: Integer
, enumValueOptions :: OptionMap , enumValueAnnotations :: AnnotationMap
, enumValueStatements :: [CompiledStatement]
} }
data StructDesc = StructDesc data StructDesc = StructDesc
...@@ -310,9 +317,9 @@ data StructDesc = StructDesc ...@@ -310,9 +317,9 @@ data StructDesc = StructDesc
, structNestedEnums :: [EnumDesc] , structNestedEnums :: [EnumDesc]
, structNestedStructs :: [StructDesc] , structNestedStructs :: [StructDesc]
, structNestedInterfaces :: [InterfaceDesc] , structNestedInterfaces :: [InterfaceDesc]
, structOptions :: OptionMap , structAnnotations :: AnnotationMap
, structMemberMap :: MemberMap , structMemberMap :: MemberMap
, structStatements :: [CompiledStatement] , structStatements :: [Desc]
-- Don't use this directly, use the members of FieldDesc and UnionDesc. -- Don't use this directly, use the members of FieldDesc and UnionDesc.
-- This field is exposed here only because I was too lazy to create a way to pass it on -- This field is exposed here only because I was too lazy to create a way to pass it on
...@@ -327,9 +334,9 @@ data UnionDesc = UnionDesc ...@@ -327,9 +334,9 @@ data UnionDesc = UnionDesc
, unionTagOffset :: Integer , unionTagOffset :: Integer
, unionTagPacking :: PackingState , unionTagPacking :: PackingState
, unionFields :: [FieldDesc] , unionFields :: [FieldDesc]
, unionOptions :: OptionMap , unionAnnotations :: AnnotationMap
, unionMemberMap :: MemberMap , unionMemberMap :: MemberMap
, unionStatements :: [CompiledStatement] , unionStatements :: [Desc]
-- Maps field numbers to discriminants for all fields in the union. -- Maps field numbers to discriminants for all fields in the union.
, unionFieldDiscriminantMap :: Map.Map Integer Integer , unionFieldDiscriminantMap :: Map.Map Integer Integer
...@@ -344,7 +351,7 @@ data FieldDesc = FieldDesc ...@@ -344,7 +351,7 @@ data FieldDesc = FieldDesc
, fieldUnion :: Maybe (UnionDesc, Integer) -- Integer is value of union discriminant. , fieldUnion :: Maybe (UnionDesc, Integer) -- Integer is value of union discriminant.
, fieldType :: TypeDesc , fieldType :: TypeDesc
, fieldDefaultValue :: Maybe ValueDesc , fieldDefaultValue :: Maybe ValueDesc
, fieldOptions :: OptionMap , fieldAnnotations :: AnnotationMap
} }
data InterfaceDesc = InterfaceDesc data InterfaceDesc = InterfaceDesc
...@@ -356,66 +363,70 @@ data InterfaceDesc = InterfaceDesc ...@@ -356,66 +363,70 @@ data InterfaceDesc = InterfaceDesc
, interfaceNestedEnums :: [EnumDesc] , interfaceNestedEnums :: [EnumDesc]
, interfaceNestedStructs :: [StructDesc] , interfaceNestedStructs :: [StructDesc]
, interfaceNestedInterfaces :: [InterfaceDesc] , interfaceNestedInterfaces :: [InterfaceDesc]
, interfaceOptions :: OptionMap , interfaceAnnotations :: AnnotationMap
, interfaceMemberMap :: MemberMap , interfaceMemberMap :: MemberMap
, interfaceStatements :: [CompiledStatement] , interfaceStatements :: [Desc]
} }
data MethodDesc = MethodDesc data MethodDesc = MethodDesc
{ methodName :: String { methodName :: String
, methodParent :: InterfaceDesc , methodParent :: InterfaceDesc
, methodNumber :: Integer , methodNumber :: Integer
, methodParams :: [(String, TypeDesc, Maybe ValueDesc)] , methodParams :: [ParamDesc]
, methodReturnType :: TypeDesc , methodReturnType :: TypeDesc
, methodOptions :: OptionMap , methodAnnotations :: AnnotationMap
, methodStatements :: [CompiledStatement]
} }
type OptionMap = Map.Map String OptionAssignmentDesc data ParamDesc = ParamDesc
{ paramName :: String
data OptionAssignmentDesc = OptionAssignmentDesc , paramParent :: MethodDesc
{ optionAssignmentParent :: Desc , paramNumber :: Integer
, optionAssignmentOption :: OptionDesc , paramType :: TypeDesc
, optionAssignmentValue :: ValueDesc , paramDefaultValue :: Maybe ValueDesc
, paramAnnotations :: AnnotationMap
} }
data OptionDesc = OptionDesc data AnnotationDesc = AnnotationDesc
{ optionName :: String { annotationName :: String
, optionParent :: Desc , annotationParent :: Desc
, optionId :: String , annotationType :: TypeDesc
, optionType :: TypeDesc , annotationAnnotations :: AnnotationMap
, optionDefaultValue :: Maybe ValueDesc , annotationTargets :: Set.Set AnnotationTarget
} }
data CompiledStatement = CompiledMember Desc type AnnotationMap = Map.Map String (AnnotationDesc, ValueDesc)
| CompiledOption OptionAssignmentDesc
-- TODO: Print options as well as members. Will be ugly-ish.
descToCode :: String -> Desc -> String descToCode :: String -> Desc -> String
descToCode indent (DescFile desc) = printf "# %s\n%s" descToCode indent self@(DescFile desc) = printf "# %s\n%s%s"
(fileName desc) (fileName desc)
(concatMap (statementToCode indent) (fileStatements desc)) (concatMap ((++ ";\n") . annotationCode (descParent self)) $ Map.toList $ fileAnnotations desc)
(concatMap (descToCode indent) (fileStatements desc))
descToCode indent (DescAlias desc) = printf "%susing %s = %s;\n" indent descToCode indent (DescAlias desc) = printf "%susing %s = %s;\n" indent
(aliasName desc) (aliasName desc)
(descQualifiedName (aliasParent desc) (aliasTarget desc)) (descQualifiedName (aliasParent desc) (aliasTarget desc))
descToCode indent (DescConstant desc) = printf "%sconst %s: %s = %s;\n" indent descToCode indent self@(DescConstant desc) = printf "%sconst %s: %s%s = %s;\n" indent
(constantName desc) (constantName desc)
(typeName (constantParent desc) (constantType desc)) (typeName (descParent self) (constantType desc))
(annotationsCode (descParent self) $ constantAnnotations desc)
(valueString (constantValue desc)) (valueString (constantValue desc))
descToCode indent (DescEnum desc) = printf "%senum %s {\n%s%s}\n" indent descToCode indent self@(DescEnum desc) = printf "%senum %s%s {\n%s%s}\n" indent
(enumName desc) (enumName desc)
(annotationsCode (descParent self) $ enumAnnotations desc)
(blockCode indent (enumStatements desc)) (blockCode indent (enumStatements desc))
indent indent
descToCode indent (DescEnumValue desc) = printf "%s%s @%d%s" indent descToCode indent self@(DescEnumValue desc) = printf "%s%s @%d%s;\n" indent
(enumValueName desc) (enumValueNumber desc) (maybeBlockCode indent $ enumValueStatements desc) (enumValueName desc) (enumValueNumber desc)
descToCode indent (DescStruct desc) = printf "%sstruct %s {\n%s%s}\n" indent (annotationsCode (descParent self) $ enumValueAnnotations desc)
descToCode indent self@(DescStruct desc) = printf "%sstruct %s%s {\n%s%s}\n" indent
(structName desc) (structName desc)
(annotationsCode (descParent self) $ structAnnotations desc)
(blockCode indent (structStatements desc)) (blockCode indent (structStatements desc))
indent indent
descToCode indent (DescField desc) = printf "%s%s@%d%s: %s%s; # %s\n" indent descToCode indent self@(DescField desc) = printf "%s%s@%d%s: %s%s%s; # %s\n" indent
(fieldName desc) (fieldNumber desc) (fieldName desc) (fieldNumber desc)
(case fieldUnion desc of { Nothing -> ""; Just (u, _) -> " in " ++ unionName u}) (case fieldUnion desc of { Nothing -> ""; Just (u, _) -> " in " ++ unionName u})
(typeName (DescStruct (fieldParent desc)) (fieldType desc)) (typeName (descParent self) (fieldType desc))
(annotationsCode (descParent self) $ fieldAnnotations desc)
(case fieldDefaultValue desc of { Nothing -> ""; Just v -> " = " ++ valueString v; }) (case fieldDefaultValue desc of { Nothing -> ""; Just v -> " = " ++ valueString v; })
(case fieldSize $ fieldType desc of (case fieldSize $ fieldType desc of
SizeReference -> printf "ref[%d]" $ fieldOffset desc SizeReference -> printf "ref[%d]" $ fieldOffset desc
...@@ -424,41 +435,53 @@ descToCode indent (DescField desc) = printf "%s%s@%d%s: %s%s; # %s\n" indent ...@@ -424,41 +435,53 @@ descToCode indent (DescField desc) = printf "%s%s@%d%s: %s%s; # %s\n" indent
bits = sizeInBits s bits = sizeInBits s
offset = fieldOffset desc offset = fieldOffset desc
in printf "bits[%d, %d)" (offset * bits) ((offset + 1) * bits)) in printf "bits[%d, %d)" (offset * bits) ((offset + 1) * bits))
descToCode indent (DescUnion desc) = printf "%sunion %s@%d { # [%d, %d)\n%s%s}\n" indent descToCode indent self@(DescUnion desc) = printf "%sunion %s@%d%s { # [%d, %d)\n%s%s}\n" indent
(unionName desc) (unionNumber desc) (unionName desc) (unionNumber desc)
(annotationsCode (descParent self) $ unionAnnotations desc)
(unionTagOffset desc * 16) (unionTagOffset desc * 16 + 16) (unionTagOffset desc * 16) (unionTagOffset desc * 16 + 16)
(blockCode indent $ unionStatements desc) (blockCode indent $ unionStatements desc)
indent indent
descToCode indent (DescInterface desc) = printf "%sinterface %s {\n%s%s}\n" indent descToCode indent self@(DescInterface desc) = printf "%sinterface %s%s {\n%s%s}\n" indent
(interfaceName desc) (interfaceName desc)
(annotationsCode (descParent self) $ interfaceAnnotations desc)
(blockCode indent (interfaceStatements desc)) (blockCode indent (interfaceStatements desc))
indent indent
descToCode indent (DescMethod desc) = printf "%s%s@%d(%s): %s%s" indent descToCode indent self@(DescMethod desc) = printf "%s%s@%d(%s): %s%s" indent
(methodName desc) (methodNumber desc) (methodName desc) (methodNumber desc)
(delimit ", " (map paramToCode (methodParams desc))) (delimit ", " (map (descToCode indent . DescParam) (methodParams desc)))
(typeName scope (methodReturnType desc)) (typeName (descParent self) (methodReturnType desc))
(maybeBlockCode indent $ methodStatements desc) where (annotationsCode (descParent self) $ methodAnnotations desc)
scope = DescInterface (methodParent desc) descToCode _ self@(DescParam desc) = printf "%s: %s%s%s"
paramToCode (name, t, Nothing) = printf "%s: %s" name (typeName scope t) (paramName desc)
paramToCode (name, t, Just v) = printf "%s: %s = %s" (typeName (descParent self) (paramType desc))
name (typeName scope t) (valueString v) (annotationsCode (descParent self) $ paramAnnotations desc)
descToCode _ (DescOption _) = error "options not implemented" (case paramDefaultValue desc of
Just v -> printf " = %s" $ valueString v
Nothing -> "")
descToCode indent self@(DescAnnotation desc) = printf "%sannotation %s: %s%s on(%s);\n" indent
(annotationName desc)
(typeName (descParent self) (annotationType desc))
(annotationsCode (descParent self) $ annotationAnnotations desc)
(delimit ", " $ map show $ Set.toList $ annotationTargets desc)
descToCode _ (DescBuiltinType _) = error "Can't print code for builtin type." descToCode _ (DescBuiltinType _) = error "Can't print code for builtin type."
descToCode _ DescBuiltinList = error "Can't print code for builtin type." descToCode _ DescBuiltinList = error "Can't print code for builtin type."
statementToCode :: String -> CompiledStatement -> String maybeBlockCode :: String -> [Desc] -> String
statementToCode indent (CompiledMember desc) = descToCode indent desc
statementToCode indent (CompiledOption desc) = printf "%s%s.%s = %s;\n" indent
(descQualifiedName (optionAssignmentParent desc) $ optionParent $ optionAssignmentOption desc)
(optionName $ optionAssignmentOption desc)
(valueString (optionAssignmentValue desc))
maybeBlockCode :: String -> [CompiledStatement] -> String
maybeBlockCode _ [] = ";\n" maybeBlockCode _ [] = ";\n"
maybeBlockCode indent statements = printf " {\n%s%s}\n" (blockCode indent statements) indent maybeBlockCode indent statements = printf " {\n%s%s}\n" (blockCode indent statements) indent
blockCode :: String -> [CompiledStatement] -> String blockCode :: String -> [Desc] -> String
blockCode indent = concatMap (statementToCode (" " ++ indent)) blockCode indent = concatMap (descToCode (" " ++ indent))
annotationCode :: Desc -> (String, (AnnotationDesc, ValueDesc)) -> String
annotationCode scope (_, (desc, VoidDesc)) =
printf "$%s" (descQualifiedName scope (DescAnnotation desc))
annotationCode _ (annId, (desc, val)) | annId == idId =
printf "$id(%s)" (valueString val)
annotationCode scope (_, (desc, val)) =
printf "$%s(%s)" (descQualifiedName scope (DescAnnotation desc)) (valueString val)
annotationsCode scope = concatMap ((' ':) . annotationCode scope) . Map.toList
instance Show FileDesc where { show desc = descToCode "" (DescFile desc) } instance Show FileDesc where { show desc = descToCode "" (DescFile desc) }
instance Show AliasDesc where { show desc = descToCode "" (DescAlias desc) } instance Show AliasDesc where { show desc = descToCode "" (DescAlias desc) }
...@@ -469,3 +492,5 @@ instance Show StructDesc where { show desc = descToCode "" (DescStruct desc) } ...@@ -469,3 +492,5 @@ instance Show StructDesc where { show desc = descToCode "" (DescStruct desc) }
instance Show FieldDesc where { show desc = descToCode "" (DescField desc) } instance Show FieldDesc where { show desc = descToCode "" (DescField desc) }
instance Show InterfaceDesc where { show desc = descToCode "" (DescInterface desc) } instance Show InterfaceDesc where { show desc = descToCode "" (DescInterface desc) }
instance Show MethodDesc where { show desc = descToCode "" (DescMethod desc) } instance Show MethodDesc where { show desc = descToCode "" (DescMethod desc) }
instance Show ParamDesc where { show desc = descToCode "" (DescParam desc) }
instance Show AnnotationDesc where { show desc = descToCode "" (DescAnnotation desc) }
...@@ -54,9 +54,11 @@ data Token = Identifier String ...@@ -54,9 +54,11 @@ data Token = Identifier String
| FalseKeyword | FalseKeyword
| AtSign | AtSign
| Colon | Colon
| DollarSign
| Period | Period
| EqualsSign | EqualsSign
| MinusSign | MinusSign
| Asterisk
| ExclamationPoint | ExclamationPoint
| InKeyword | InKeyword
| OfKeyword -- We reserve some common, short English words for use as future keywords. | OfKeyword -- We reserve some common, short English words for use as future keywords.
...@@ -71,7 +73,7 @@ data Token = Identifier String ...@@ -71,7 +73,7 @@ data Token = Identifier String
| StructKeyword | StructKeyword
| UnionKeyword | UnionKeyword
| InterfaceKeyword | InterfaceKeyword
| OptionKeyword | AnnotationKeyword
deriving (Data, Typeable, Show, Eq) deriving (Data, Typeable, Show, Eq)
data Statement = Line TokenSequence data Statement = Line TokenSequence
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment