Commit 13ab0872 authored by Kenton Varda's avatar Kenton Varda

Compile inline lists (TODO: code generation).

parent 7f20d533
...@@ -161,7 +161,10 @@ lookupDesc scope name = lookupDesc (descParent scope) name ...@@ -161,7 +161,10 @@ 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), ("Inline", DescBuiltinInline), ("id", DescBuiltinId)]) [("List", DescBuiltinList),
("Inline", DescBuiltinInline),
("InlineList", DescBuiltinInlineList),
("id", DescBuiltinId)])
------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------
...@@ -246,6 +249,12 @@ compileValue pos (InlineStructType desc) v = compileValue pos (StructType desc) ...@@ -246,6 +249,12 @@ compileValue pos (InlineStructType desc) v = compileValue pos (StructType desc)
compileValue _ (ListType t) (ListFieldValue l) = compileValue _ (ListType t) (ListFieldValue l) =
fmap ListDesc (doAll [ compileValue vpos t v | Located vpos v <- l ]) fmap ListDesc (doAll [ compileValue vpos t v | Located vpos v <- l ])
compileValue pos (InlineListType t s) (ListFieldValue l) = do
elements <- doAll [ compileValue vpos t v | Located vpos v <- l ]
when (List.genericLength elements /= s) $
makeError pos $ printf "Fixed-size list must have exactly %d elements." s
return $ ListDesc elements
compileValue pos (BuiltinType BuiltinVoid) _ = makeError pos "Void fields cannot have values." compileValue pos (BuiltinType BuiltinVoid) _ = makeError pos "Void fields cannot have values."
compileValue pos (BuiltinType BuiltinBool) _ = makeExpectError pos "boolean" compileValue pos (BuiltinType BuiltinBool) _ = makeExpectError pos "boolean"
compileValue pos (BuiltinType BuiltinInt8) _ = makeExpectError pos "integer" compileValue pos (BuiltinType BuiltinInt8) _ = makeExpectError pos "integer"
...@@ -263,9 +272,9 @@ compileValue pos (BuiltinType BuiltinData) _ = makeExpectError pos "string" ...@@ -263,9 +272,9 @@ compileValue pos (BuiltinType BuiltinData) _ = makeExpectError pos "string"
compileValue pos (EnumType _) _ = makeExpectError pos "enumerant name" compileValue pos (EnumType _) _ = makeExpectError pos "enumerant name"
compileValue pos (StructType _) _ = makeExpectError pos "parenthesized list of field assignments" compileValue pos (StructType _) _ = makeExpectError pos "parenthesized list of field assignments"
compileValue pos (InlineStructType _) _ = makeExpectError pos "parenthesized list of field assignments"
compileValue pos (InterfaceType _) _ = makeError pos "Interfaces can't have default values." compileValue pos (InterfaceType _) _ = makeError pos "Interfaces can't have default values."
compileValue pos (ListType _) _ = makeExpectError pos "list" compileValue pos (ListType _) _ = makeExpectError pos "list"
compileValue pos (InlineListType _ _) _ = makeExpectError pos "list"
descAsType _ (DescEnum desc) = succeed (EnumType desc) descAsType _ (DescEnum desc) = succeed (EnumType desc)
descAsType _ (DescStruct desc) = succeed (StructType desc) descAsType _ (DescStruct desc) = succeed (StructType desc)
...@@ -276,33 +285,39 @@ descAsType name DescBuiltinList = makeError (declNamePos name) message where ...@@ -276,33 +285,39 @@ descAsType name DescBuiltinList = makeError (declNamePos name) message where
message = printf "'List' requires exactly one type parameter." (declNameString name) message = printf "'List' requires exactly one type parameter." (declNameString name)
descAsType name DescBuiltinInline = makeError (declNamePos name) message where descAsType name DescBuiltinInline = makeError (declNamePos name) message where
message = printf "'Inline' requires exactly one type parameter." (declNameString name) message = printf "'Inline' requires exactly one type parameter." (declNameString name)
descAsType name DescBuiltinInlineList = makeError (declNamePos name) message where
message = printf "'InlineList' requires exactly one type parameter." (declNameString name)
descAsType name _ = makeError (declNamePos name) message where descAsType name _ = makeError (declNamePos name) message where
message = printf "'%s' is not a type." (declNameString name) message = printf "'%s' is not a type." (declNameString name)
compileType :: Desc -> TypeExpression -> Status TypeDesc compileType :: Desc -> TypeExpression -> Status TypeDesc
compileType scope (TypeExpression n []) = do compileType scope (TypeExpression n params) = do
desc <- lookupDesc scope n
descAsType n desc
compileType scope (TypeExpression n (param:moreParams)) = do
desc <- lookupDesc scope n desc <- lookupDesc scope n
case desc of case desc of
DescBuiltinList -> DescBuiltinList -> case params of
if null moreParams [TypeParameterType param] -> fmap ListType (compileType scope param)
then fmap ListType (compileType scope param) _ -> makeError (declNamePos n) "'List' requires exactly one type parameter."
else makeError (declNamePos n) "'List' requires exactly one type parameter." DescBuiltinInline -> case params of
DescBuiltinInline -> [TypeParameterType param] -> do
if null moreParams inner <- compileType scope param
then do case inner of
inner <- compileType scope param StructType s -> if structIsFixedWidth s
case inner of then return (InlineStructType s)
StructType s -> if structIsFixedWidth s else makeError (declNamePos n) $
then return (InlineStructType s) printf "'%s' cannot be inlined because it is not fixed-width."
else makeError (declNamePos n) $ (structName s)
printf "'%s' cannot be inlined because it is not fixed-width." _ -> makeError (declNamePos n) "'Inline' parameter must be a struct type."
(structName s) _ -> makeError (declNamePos n) "'Inline' requires exactly one type parameter."
_ -> makeError (declNamePos n) "'Inline' parameter must be a struct type." DescBuiltinInlineList -> case params of
else makeError (declNamePos n) "'Inline' requires exactly one type parameter." [TypeParameterType param, TypeParameterInteger size] -> do
_ -> makeError (declNamePos n) "Only the type 'List' can have type parameters." inner <- compileType scope param
return $ InlineListType inner size
_ -> makeError (declNamePos n)
"'InlineList' requires exactly two type parameters: a type and a size."
_ -> case params of
[] -> descAsType n desc
_ -> makeError (declNamePos n) $
printf "'%s' doesn't take parameters." (declNameString n)
compileAnnotation :: Desc -> AnnotationTarget -> Annotation compileAnnotation :: Desc -> AnnotationTarget -> Annotation
-> Status (Maybe AnnotationDesc, ValueDesc) -> Status (Maybe AnnotationDesc, ValueDesc)
......
...@@ -91,6 +91,7 @@ isPrimitive (StructType _) = False ...@@ -91,6 +91,7 @@ isPrimitive (StructType _) = False
isPrimitive (InlineStructType _) = False isPrimitive (InlineStructType _) = False
isPrimitive (InterfaceType _) = False isPrimitive (InterfaceType _) = False
isPrimitive (ListType _) = False isPrimitive (ListType _) = False
isPrimitive (InlineListType _ _) = False
isBlob (BuiltinType BuiltinText) = True isBlob (BuiltinType BuiltinText) = True
isBlob (BuiltinType BuiltinData) = True isBlob (BuiltinType BuiltinData) = True
...@@ -254,7 +255,7 @@ fieldContext parent desc = mkStrContext context where ...@@ -254,7 +255,7 @@ fieldContext parent desc = mkStrContext context where
Nothing -> MuVariable "" Nothing -> MuVariable ""
Just v -> MuVariable (if isDefaultZero v then "" else ", " ++ defaultMask v) Just v -> MuVariable (if isDefaultZero v then "" else ", " ++ defaultMask v)
context "fieldElementSize" = context "fieldElementSize" =
MuVariable $ cxxFieldSizeString $ elementSize $ elementType $ fieldType desc MuVariable $ cxxFieldSizeString $ fieldSize $ elementType $ fieldType desc
context "fieldElementType" = context "fieldElementType" =
MuVariable $ cxxTypeString $ elementType $ fieldType desc MuVariable $ cxxTypeString $ elementType $ fieldType desc
context "fieldUnion" = case fieldUnion desc of context "fieldUnion" = case fieldUnion desc of
......
...@@ -38,12 +38,19 @@ declNameImport (RelativeName _) = Nothing ...@@ -38,12 +38,19 @@ declNameImport (RelativeName _) = Nothing
declNameImport (ImportName s) = Just s declNameImport (ImportName s) = Just s
declNameImport (MemberName parent _) = declNameImport parent declNameImport (MemberName parent _) = declNameImport parent
data TypeExpression = TypeExpression DeclName [TypeExpression] data TypeParameter = TypeParameterType TypeExpression
| TypeParameterInteger Integer
deriving (Show)
data TypeExpression = TypeExpression DeclName [TypeParameter]
deriving (Show) deriving (Show)
typeParameterImports :: TypeParameter -> [Located String]
typeParameterImports (TypeParameterType t) = typeImports t
typeParameterImports (TypeParameterInteger _) = []
typeImports :: TypeExpression -> [Located String] typeImports :: TypeExpression -> [Located String]
typeImports (TypeExpression name params) = typeImports (TypeExpression name params) =
maybeToList (declNameImport name) ++ concatMap typeImports params maybeToList (declNameImport name) ++ concatMap typeParameterImports params
data Annotation = Annotation DeclName (Located FieldValue) deriving(Show) data Annotation = Annotation DeclName (Located FieldValue) deriving(Show)
......
...@@ -149,10 +149,14 @@ declName = do ...@@ -149,10 +149,14 @@ declName = do
members <- many (period >> located anyIdentifier) members <- many (period >> located anyIdentifier)
return (foldl MemberName base members :: DeclName) return (foldl MemberName base members :: DeclName)
typeParameter :: TokenParser TypeParameter
typeParameter = liftM TypeParameterInteger literalInt
<|> liftM TypeParameterType typeExpression
typeExpression :: TokenParser TypeExpression typeExpression :: TokenParser TypeExpression
typeExpression = do typeExpression = do
name <- declName name <- declName
suffixes <- option [] (parenthesizedList typeExpression) suffixes <- option [] (parenthesizedList typeParameter)
return (TypeExpression name suffixes) return (TypeExpression name suffixes)
nameWithOrdinal :: TokenParser (Located String, Located Integer) nameWithOrdinal :: TokenParser (Located String, Located Integer)
......
...@@ -56,6 +56,7 @@ data Desc = DescFile FileDesc ...@@ -56,6 +56,7 @@ data Desc = DescFile FileDesc
| DescBuiltinType BuiltinType | DescBuiltinType BuiltinType
| DescBuiltinList | DescBuiltinList
| DescBuiltinInline | DescBuiltinInline
| DescBuiltinInlineList
| DescBuiltinId | DescBuiltinId
descName (DescFile _) = "(top-level)" descName (DescFile _) = "(top-level)"
...@@ -73,6 +74,7 @@ descName (DescAnnotation d) = annotationName d ...@@ -73,6 +74,7 @@ descName (DescAnnotation d) = annotationName d
descName (DescBuiltinType d) = builtinTypeName d descName (DescBuiltinType d) = builtinTypeName d
descName DescBuiltinList = "List" descName DescBuiltinList = "List"
descName DescBuiltinInline = "Inline" descName DescBuiltinInline = "Inline"
descName DescBuiltinInlineList = "InlineList"
descName DescBuiltinId = "id" descName DescBuiltinId = "id"
descId (DescFile d) = fileId d descId (DescFile d) = fileId d
...@@ -90,6 +92,7 @@ descId (DescAnnotation d) = annotationId d ...@@ -90,6 +92,7 @@ descId (DescAnnotation d) = annotationId d
descId (DescBuiltinType _) = Nothing descId (DescBuiltinType _) = Nothing
descId DescBuiltinList = Nothing descId DescBuiltinList = Nothing
descId DescBuiltinInline = Nothing descId DescBuiltinInline = Nothing
descId DescBuiltinInlineList = Nothing
descId DescBuiltinId = Just "0U0T3e_SnatEfk6UcH2tcjTt1E0" descId DescBuiltinId = Just "0U0T3e_SnatEfk6UcH2tcjTt1E0"
-- Gets the ID if explicitly defined, or generates it by appending ".name" to the parent's ID. -- Gets the ID if explicitly defined, or generates it by appending ".name" to the parent's ID.
...@@ -115,6 +118,7 @@ descParent (DescAnnotation d) = annotationParent d ...@@ -115,6 +118,7 @@ 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."
descParent DescBuiltinInline = error "Builtin type has no parent." descParent DescBuiltinInline = error "Builtin type has no parent."
descParent DescBuiltinInlineList = error "Builtin type has no parent."
descParent DescBuiltinId = error "Builtin annotation has no parent." descParent DescBuiltinId = error "Builtin annotation has no parent."
descFile (DescFile d) = d descFile (DescFile d) = d
...@@ -135,6 +139,7 @@ descAnnotations (DescAnnotation d) = annotationAnnotations d ...@@ -135,6 +139,7 @@ descAnnotations (DescAnnotation d) = annotationAnnotations d
descAnnotations (DescBuiltinType _) = Map.empty descAnnotations (DescBuiltinType _) = Map.empty
descAnnotations DescBuiltinList = Map.empty descAnnotations DescBuiltinList = Map.empty
descAnnotations DescBuiltinInline = Map.empty descAnnotations DescBuiltinInline = Map.empty
descAnnotations DescBuiltinInlineList = Map.empty
descAnnotations DescBuiltinId = Map.empty descAnnotations DescBuiltinId = Map.empty
descRuntimeImports (DescFile _) = error "Not to be called on files." descRuntimeImports (DescFile _) = error "Not to be called on files."
...@@ -152,6 +157,7 @@ descRuntimeImports (DescAnnotation d) = annotationRuntimeImports d ...@@ -152,6 +157,7 @@ descRuntimeImports (DescAnnotation d) = annotationRuntimeImports d
descRuntimeImports (DescBuiltinType _) = [] descRuntimeImports (DescBuiltinType _) = []
descRuntimeImports DescBuiltinList = [] descRuntimeImports DescBuiltinList = []
descRuntimeImports DescBuiltinInline = [] descRuntimeImports DescBuiltinInline = []
descRuntimeImports DescBuiltinInlineList = []
descRuntimeImports DescBuiltinId = [] descRuntimeImports DescBuiltinId = []
type MemberMap = Map.Map String (Maybe Desc) type MemberMap = Map.Map String (Maybe Desc)
...@@ -221,6 +227,7 @@ data TypeDesc = BuiltinType BuiltinType ...@@ -221,6 +227,7 @@ data TypeDesc = BuiltinType BuiltinType
| InlineStructType StructDesc | InlineStructType StructDesc
| InterfaceType InterfaceDesc | InterfaceType InterfaceDesc
| ListType TypeDesc | ListType TypeDesc
| InlineListType TypeDesc Integer
typeRuntimeImports (BuiltinType _) = [] typeRuntimeImports (BuiltinType _) = []
typeRuntimeImports (EnumType d) = [descFile (DescEnum d)] typeRuntimeImports (EnumType d) = [descFile (DescEnum d)]
...@@ -228,6 +235,7 @@ typeRuntimeImports (StructType d) = [descFile (DescStruct d)] ...@@ -228,6 +235,7 @@ typeRuntimeImports (StructType d) = [descFile (DescStruct d)]
typeRuntimeImports (InlineStructType d) = [descFile (DescStruct d)] typeRuntimeImports (InlineStructType d) = [descFile (DescStruct d)]
typeRuntimeImports (InterfaceType d) = [descFile (DescInterface d)] typeRuntimeImports (InterfaceType d) = [descFile (DescInterface d)]
typeRuntimeImports (ListType d) = typeRuntimeImports d typeRuntimeImports (ListType d) = typeRuntimeImports d
typeRuntimeImports (InlineListType d _) = typeRuntimeImports d
data DataSectionSize = DataSection1 | DataSection8 | DataSection16 | DataSection32 data DataSectionSize = DataSection1 | DataSection8 | DataSection16 | DataSection32
| DataSectionWords Integer | DataSectionWords Integer
...@@ -310,19 +318,24 @@ fieldSize (InlineStructType StructDesc { structDataSize = ds, structPointerCount ...@@ -310,19 +318,24 @@ fieldSize (InlineStructType StructDesc { structDataSize = ds, structPointerCount
SizeInlineComposite ds ps SizeInlineComposite ds ps
fieldSize (InterfaceType _) = SizeReference fieldSize (InterfaceType _) = SizeReference
fieldSize (ListType _) = SizeReference fieldSize (ListType _) = SizeReference
fieldSize (InlineListType element size) = let
elementSize (StructType StructDesc { structDataSize = DataSection1, structPointerCount = 0 }) = minDataSectionForBits bits
SizeData Size1 | bits <= 1 = DataSection1
elementSize (StructType StructDesc { structDataSize = DataSection8, structPointerCount = 0 }) = | bits <= 8 = DataSection8
SizeData Size8 | bits <= 16 = DataSection16
elementSize (StructType StructDesc { structDataSize = DataSection16, structPointerCount = 0 }) = | bits <= 32 = DataSection32
SizeData Size16 | otherwise = DataSectionWords $ div (bits + 63) 64
elementSize (StructType StructDesc { structDataSize = DataSection32, structPointerCount = 0 }) = dataSection = case fieldSize element of
SizeData Size32 SizeVoid -> DataSectionWords 0
elementSize (StructType StructDesc { structDataSize = ds, structPointerCount = pc }) = SizeData s -> minDataSectionForBits $ dataSizeInBits s * size
SizeInlineComposite ds pc SizeReference -> DataSectionWords 0
elementSize (InlineStructType s) = elementSize (StructType s) SizeInlineComposite ds _ -> minDataSectionForBits $ dataSectionBits ds
elementSize t = fieldSize t pointerCount = case fieldSize element of
SizeVoid -> 0
SizeData _ -> 0
SizeReference -> size
SizeInlineComposite _ pc -> pc
in SizeInlineComposite dataSection pointerCount
-- Render the type descriptor's name as a string, appropriate for use in the given scope. -- Render the type descriptor's name as a string, appropriate for use in the given scope.
typeName :: Desc -> TypeDesc -> String typeName :: Desc -> TypeDesc -> String
...@@ -332,6 +345,7 @@ typeName scope (StructType desc) = descQualifiedName scope (DescStruct desc) ...@@ -332,6 +345,7 @@ typeName scope (StructType desc) = descQualifiedName scope (DescStruct desc)
typeName scope (InlineStructType desc) = descQualifiedName scope (DescStruct desc) typeName scope (InlineStructType desc) = descQualifiedName scope (DescStruct desc)
typeName scope (InterfaceType desc) = descQualifiedName scope (DescInterface desc) typeName scope (InterfaceType desc) = descQualifiedName scope (DescInterface desc)
typeName scope (ListType t) = "List(" ++ typeName scope t ++ ")" typeName scope (ListType t) = "List(" ++ typeName scope t ++ ")"
typeName scope (InlineListType t s) = printf "InlineList(%s, %d)" (typeName scope t) s
-- Computes the qualified name for the given descriptor within the given scope. -- Computes the qualified name for the given descriptor within the given scope.
-- At present the scope is only used to determine whether the target is in the same file. If -- At present the scope is only used to determine whether the target is in the same file. If
...@@ -589,6 +603,7 @@ descToCode indent self@(DescAnnotation desc) = printf "%sannotation %s: %s on(%s ...@@ -589,6 +603,7 @@ descToCode indent self@(DescAnnotation desc) = printf "%sannotation %s: %s on(%s
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."
descToCode _ DescBuiltinInline = error "Can't print code for builtin type." descToCode _ DescBuiltinInline = error "Can't print code for builtin type."
descToCode _ DescBuiltinInlineList = error "Can't print code for builtin type."
descToCode _ DescBuiltinId = error "Can't print code for builtin annotation." descToCode _ DescBuiltinId = error "Can't print code for builtin annotation."
maybeBlockCode :: String -> [Desc] -> String maybeBlockCode :: String -> [Desc] -> String
......
...@@ -66,13 +66,7 @@ encodeDataValue _ (Float64Desc v) = EncodedBytes $ bytes (doubleToWord v) 8 ...@@ -66,13 +66,7 @@ encodeDataValue _ (Float64Desc v) = EncodedBytes $ bytes (doubleToWord v) 8
encodeDataValue _ (TextDesc _) = error "Not fixed-width data." encodeDataValue _ (TextDesc _) = error "Not fixed-width data."
encodeDataValue _ (DataDesc _) = error "Not fixed-width data." encodeDataValue _ (DataDesc _) = error "Not fixed-width data."
encodeDataValue _ (EnumerantValueDesc v) = EncodedBytes $ bytes (enumerantNumber v) 2 encodeDataValue _ (EnumerantValueDesc v) = EncodedBytes $ bytes (enumerantNumber v) 2
encodeDataValue (StructType desc) (StructValueDesc assignments) = let encodeDataValue _ (StructValueDesc _) = error "Not fixed-width data."
(dataBytes, refBytes, childBytes) = encodeStruct desc assignments 0
in if null refBytes && null childBytes
then EncodedBytes dataBytes
else error "encodeDataValue called on struct that wasn't plain data."
encodeDataValue (InlineStructType desc) v = encodeDataValue (StructType desc) v
encodeDataValue _ (StructValueDesc _) = error "Type/value mismatch."
encodeDataValue _ (ListDesc _) = error "Not fixed-width data." encodeDataValue _ (ListDesc _) = error "Not fixed-width data."
encodeMaskedDataValue t v Nothing = encodeDataValue t v encodeMaskedDataValue t v Nothing = encodeDataValue t v
...@@ -86,18 +80,19 @@ encodePointerValue _ (DataDesc d) = ...@@ -86,18 +80,19 @@ encodePointerValue _ (DataDesc d) =
(encodeListReference (SizeData Size8) (genericLength d), padToWord d) (encodeListReference (SizeData Size8) (genericLength d), padToWord d)
encodePointerValue (StructType desc) (StructValueDesc assignments) = let encodePointerValue (StructType desc) (StructValueDesc assignments) = let
(dataBytes, refBytes, childBytes) = encodeStruct desc assignments 0 (dataBytes, refBytes, childBytes) = encodeStruct desc assignments 0
in (encodeStructReference desc, concat [padToWord dataBytes, refBytes, childBytes]) in (encodeStructReference desc, concat [dataBytes, refBytes, childBytes])
encodePointerValue (InlineStructType desc) v = encodePointerValue (StructType desc) v encodePointerValue (InlineStructType _) _ =
encodePointerValue (ListType elementType) (ListDesc items) = error "Tried to encode inline struct as a pointer."
(encodeListReference (elementSize elementType) (genericLength items), encodePointerValue (ListType elementType) (ListDesc items) = encodeList elementType items
encodeList elementType items) encodePointerValue (InlineListType _ _) _ =
error "Tried to encode inline list as a pointer."
encodePointerValue _ _ = error "Unknown pointer type." encodePointerValue _ _ = error "Unknown pointer type."
-- Given a sorted list of (bitOffset, data), pack into a byte array. -- Given a sorted list of (bitOffset, data), pack into a byte array.
packBytes :: Integer -- Total size of array to pack, in bits. packBytes :: Integer -- Total size of array to pack, in bits.
-> [(Integer, EncodedData)] -- (offset, data) pairs to pack. Must be in order. -> [(Integer, EncodedData)] -- (offset, data) pairs to pack. Must be in order.
-> [Word8] -> [Word8]
packBytes size = loop 0 where packBytes size = padToWord . loop 0 where
loop :: Integer -> [(Integer, EncodedData)] -> [Word8] loop :: Integer -> [(Integer, EncodedData)] -> [Word8]
loop bit [] | bit <= size = genericReplicate (div (size - bit + 7) 8) 0 loop bit [] | bit <= size = genericReplicate (div (size - bit + 7) 8) 0
loop bit [] | bit > size = error "Data values overran size." loop bit [] | bit > size = error "Data values overran size."
...@@ -136,6 +131,13 @@ encodeStructReference desc offset = ...@@ -136,6 +131,13 @@ encodeStructReference desc offset =
bytes (dataSectionWordSize $ structDataSize desc) 2 ++ bytes (dataSectionWordSize $ structDataSize desc) 2 ++
bytes (structPointerCount desc) 2 bytes (structPointerCount desc) 2
encodeInlineStructListReference elementDataSize elementPointerCount elementCount offset = let
dataBits = dataSectionBits elementDataSize * elementCount
dataWords = div (dataBits + 63) 64
in bytes (offset * 4 + structTag) 4 ++
bytes dataWords 2 ++
bytes (elementPointerCount * elementCount) 2
encodeListReference elemSize@(SizeInlineComposite ds rc) elementCount offset = encodeListReference elemSize@(SizeInlineComposite ds rc) elementCount offset =
bytes (offset * 4 + listTag) 4 ++ bytes (offset * 4 + listTag) 4 ++
bytes (fieldSizeEnum elemSize + shiftL (elementCount * (dataSectionWordSize ds + rc)) 3) 4 bytes (fieldSizeEnum elemSize + shiftL (elementCount * (dataSectionWordSize ds + rc)) 3) 4
...@@ -179,73 +181,173 @@ structDataSectionValues assignments = let ...@@ -179,73 +181,173 @@ structDataSectionValues assignments = let
encodeMaskedDataValue (fieldType f) v (fieldDefaultValue f)) encodeMaskedDataValue (fieldType f) v (fieldDefaultValue f))
| (f@FieldDesc { fieldOffset = DataOffset _ _ }, v) <- assignments] | (f@FieldDesc { fieldOffset = DataOffset _ _ }, v) <- assignments]
inlineStructValues = do -- List monad! inlineCompositeValues = do -- List monad!
(FieldDesc { fieldOffset = InlineCompositeOffset off _ sectionSize _ }, (FieldDesc { fieldType = t
StructValueDesc v) <- assignments , fieldOffset = InlineCompositeOffset off _ sectionSize _ }, v) <- assignments
let bitOffset = off * dataSizeInBits (dataSectionAlignment sectionSize) let bitOffset = off * dataSizeInBits (dataSectionAlignment sectionSize)
(pos, v2) <- structDataSectionValues v (pos, v2) <- case (t, v) of
(InlineStructType _, StructValueDesc v2) -> structDataSectionValues v2
(InlineListType t2 _, ListDesc v2) -> inlineListDataSectionValues t2 v2
_ -> error "Non-inline-composite had inline-composite offset."
return (pos + bitOffset, v2) return (pos + bitOffset, v2)
unionTags = [(unionTagOffset u * 16, unionTags = [(unionTagOffset u * 16,
encodeDataValue (BuiltinType BuiltinUInt16) (UInt16Desc $ fromIntegral n)) encodeDataValue (BuiltinType BuiltinUInt16) (UInt16Desc $ fromIntegral n))
| (FieldDesc {fieldUnion = Just (u, n)}, _) <- assignments] | (FieldDesc {fieldUnion = Just (u, n)}, _) <- assignments]
in simpleValues ++ inlineStructValues ++ unionTags in simpleValues ++ inlineCompositeValues ++ unionTags
structPointerSectionValues :: [(FieldDesc, ValueDesc)] -> [(Integer, (Integer -> [Word8], [Word8]))] structPointerSectionValues :: [(FieldDesc, ValueDesc)] -> [(Integer, (Integer -> [Word8], [Word8]))]
structPointerSectionValues assignments = let structPointerSectionValues assignments = let
simpleValues = [(off, encodePointerValue (fieldType f) v) simpleValues = [(off, encodePointerValue (fieldType f) v)
| (f@FieldDesc { fieldOffset = PointerOffset off }, v) <- assignments] | (f@FieldDesc { fieldOffset = PointerOffset off }, v) <- assignments]
inlineStructValues = do -- List monad! inlineCompositeValues = do -- List monad!
(FieldDesc { fieldOffset = InlineCompositeOffset _ off _ _ }, (FieldDesc { fieldType = t
StructValueDesc v) <- assignments , fieldOffset = InlineCompositeOffset _ off _ _ }, v) <- assignments
(pos, v2) <- structPointerSectionValues v (pos, v2) <- case (t, v) of
(InlineStructType _, StructValueDesc v2) -> structPointerSectionValues v2
(InlineListType t2 _, ListDesc v2) -> inlineListPointerSectionValues t2 v2
_ -> error "Non-inline-composite had inline-composite offset."
return (pos + off, v2) return (pos + off, v2)
in simpleValues ++ inlineStructValues in simpleValues ++ inlineCompositeValues
encodeList elementType elements = case elementSize elementType of ------------------------------------------------------------------------------------------
SizeVoid -> []
SizeInlineComposite _ _ -> let encodeList :: TypeDesc -- Type of each element.
handleStructType desc = let -> [ValueDesc] -- Element values.
count = genericLength elements -> (Integer -> [Word8], -- Encodes the pointer, given the offset.
tag = encodeStructReference desc count [Word8]) -- Body bytes.
(elemBytes, childBytes) = encodeStructList 0 desc [v | StructValueDesc v <- elements]
in concat [tag, elemBytes, childBytes] -- Encode a list of empty structs as void.
in case elementType of encodeList (StructType StructDesc {
StructType desc -> handleStructType desc structDataSize = DataSectionWords 0, structPointerCount = 0 }) elements =
InlineStructType desc -> handleStructType desc (encodeListReference SizeVoid (genericLength elements), [])
_ -> error "Only structs can be inline composites."
SizeReference -> refBytes ++ childBytes where
encodedElements = zip [0..] $ map (encodePointerValue elementType) elements
(refBytes, childBytes) = packPointers (genericLength elements) encodedElements 0
SizeData size -> let
bits = dataSizeInBits size
encodedElements = zip [0,bits..] $ map (encodeDataValue elementType) elements
in padToWord $ packBytes (genericLength elements * bits) encodedElements
-- Encode an inline-composite struct list. Not used in cases where the struct is data-only and -- Encode a list of sub-word data-only structs as a list of primitives.
-- fits into 32 bits or less. encodeList (StructType desc@StructDesc { structDataSize = ds, structPointerCount = 0 }) elements
encodeStructList :: Integer -> StructDesc -> [[(FieldDesc, ValueDesc)]] -> ([Word8], [Word8]) | dataSectionBits ds <= 64 = let
encodeStructList o desc elements = loop (o + eSize * genericLength elements) elements where in (encodeListReference (SizeData $ dataSectionAlignment ds) (genericLength elements),
inlineStructListDataSection desc elements)
-- Encode a list of single-pointer structs as a list of pointers.
encodeList (StructType desc@StructDesc {
structDataSize = DataSectionWords 0, structPointerCount = 1 }) elements = let
(refBytes, childBytes) = inlineStructListPointerSection desc elements
in (encodeListReference SizeReference (genericLength elements), refBytes ++ childBytes)
-- Encode a list of any other sort of struct.
encodeList (StructType desc) elements = let
count = genericLength elements
tag = encodeStructReference desc count
eSize = dataSectionWordSize (structDataSize desc) + structPointerCount desc eSize = dataSectionWordSize (structDataSize desc) + structPointerCount desc
structElems = [v | StructValueDesc v <- elements]
(elemBytes, childBytes) = loop (eSize * genericLength structElems) structElems
loop _ [] = ([], []) loop _ [] = ([], [])
loop offset (element:rest) = let loop offset (element:rest) = let
offsetFromElementEnd = offset - eSize offsetFromElementEnd = offset - eSize
(dataBytes, refBytes, childBytes) = encodeStruct desc element offsetFromElementEnd (dataBytes, refBytes, childBytes2) = encodeStruct desc element offsetFromElementEnd
childLen = genericLength childBytes childLen = genericLength childBytes2
childWordLen = if mod childLen 8 == 0 childWordLen = if mod childLen 8 == 0
then div childLen 8 then div childLen 8
else error "Child not word-aligned." else error "Child not word-aligned."
(restBytes, restChildren) = loop (offsetFromElementEnd + childWordLen) rest (restBytes, restChildren) = loop (offsetFromElementEnd + childWordLen) rest
in (padToWord dataBytes ++ refBytes ++ restBytes, childBytes ++ restChildren) in (dataBytes ++ refBytes ++ restBytes, childBytes2 ++ restChildren)
in (encodeListReference (SizeInlineComposite (structDataSize desc) (structPointerCount desc))
(genericLength elements),
concat [tag, elemBytes, childBytes])
-- A list of inline structs is encoded into separate data and pointer sections, and the
-- pointer to it is actually a struct pointer.
encodeList (InlineStructType desc) elements = let
dataBytes = inlineStructListDataSection desc elements
(refBytes, childBytes) = inlineStructListPointerSection desc elements
in case (structDataSize desc, structPointerCount desc) of
(ds, 0) -> -- If only data, encode as a primitive list.
(encodeListReference (SizeData $ dataSectionAlignment ds)
(div (genericLength elements * dataSectionBits ds)
(dataSizeInBits (dataSectionAlignment ds))),
dataBytes)
(DataSectionWords 0, pc) -> -- If only pointers, encode as a pointer list.
(encodeListReference SizeReference (genericLength elements * pc),
refBytes ++ childBytes)
(ds, pc) -> -- Otherwise, encode as a struct.
(encodeInlineStructListReference ds pc (genericLength elements),
concat [dataBytes, refBytes, childBytes])
-- Encode a list of inline lists by just concatenating all the elements. The number of inner
-- lists can be determined at runtime by dividing the total size by the fixed inline list size.
encodeList (InlineListType t _) elements = encodeList t (concat [l | ListDesc l <- elements])
-- Encode primitive types.
encodeList elementType elements = let
eSize = fieldSize elementType
dataBytes = case eSize of
SizeVoid -> []
SizeInlineComposite _ _ -> error "All inline composites should have been handled above."
SizeReference -> refBytes ++ childBytes where
encodedElements = zip [0..] $ map (encodePointerValue elementType) elements
(refBytes, childBytes) = packPointers (genericLength elements) encodedElements 0
SizeData size -> let
bits = dataSizeInBits size
encodedElements = zip [0,bits..] $ map (encodeDataValue elementType) elements
in packBytes (genericLength elements * bits) encodedElements
in (encodeListReference eSize (genericLength elements), dataBytes)
---------------------------------------------
inlineListDataSectionValues elementType elements = case fieldSize elementType of
SizeVoid -> []
(SizeInlineComposite _ _) -> case elementType of
InlineStructType desc -> inlineStructListDataSectionValues desc elements
InlineListType t _ -> inlineListDataSectionValues t (concat [l | ListDesc l <- elements])
_ -> error "Unknown inline composite type."
SizeReference -> []
SizeData size -> let
bits = dataSizeInBits size
in zip [0,bits..] $ map (encodeDataValue elementType) elements
inlineListPointerSectionValues elementType elements = case fieldSize elementType of
SizeVoid -> []
(SizeInlineComposite _ _) -> case elementType of
InlineStructType desc -> inlineStructListPointerSectionValues desc elements
InlineListType t _ -> inlineListPointerSectionValues t (concat [l | ListDesc l <- elements])
_ -> error "Unknown inline composite type."
SizeReference -> zip [0..] $ map (encodePointerValue elementType) elements
SizeData _ -> []
inlineStructListDataSection elementDesc elements =
packBytes (genericLength elements * dataSectionBits (structDataSize elementDesc))
(sortBy (compare `on` fst) $ inlineStructListDataSectionValues elementDesc elements)
inlineStructListDataSectionValues elementDesc elements = do
let bits = dataSectionBits $ structDataSize elementDesc
(i, StructValueDesc e) <- zip [0..] elements
(off, v) <- structDataSectionValues e
return (off + bits * i, v)
inlineStructListPointerSection elementDesc elements =
packPointers
(genericLength elements * structPointerCount elementDesc)
(sortBy (compare `on` fst) $ inlineStructListPointerSectionValues elementDesc elements)
0
inlineStructListPointerSectionValues elementDesc elements = do
let ptrs = structPointerCount elementDesc
(i, StructValueDesc e) <- zip [0..] elements
(off, v) <- structPointerSectionValues e
return (off + ptrs * i, v)
------------------------------------------------------------------------------------------
encodeMessage (StructType desc) (StructValueDesc assignments) = let encodeMessage (StructType desc) (StructValueDesc assignments) = let
(dataBytes, refBytes, childBytes) = encodeStruct desc assignments 0 (dataBytes, refBytes, childBytes) = encodeStruct desc assignments 0
in concat [encodeStructReference desc (0::Integer), padToWord dataBytes, refBytes, childBytes] in concat [encodeStructReference desc (0::Integer), dataBytes, refBytes, childBytes]
encodeMessage (InlineStructType desc) val = encodeMessage (StructType desc) val encodeMessage (InlineStructType desc) val = encodeMessage (StructType desc) val
encodeMessage (ListType elementType) (ListDesc elements) = encodeMessage (ListType elementType) (ListDesc elements) = let
encodeListReference (elementSize elementType) (genericLength elements) (0::Integer) ++ (ptr, listBytes) = encodeList elementType elements
encodeList elementType elements in ptr (0::Integer) ++ listBytes
encodeMessage (InlineListType elementType _) val = encodeMessage (ListType elementType) val
encodeMessage _ _ = error "Not a message." encodeMessage _ _ = error "Not a message."
...@@ -355,7 +355,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}() ...@@ -355,7 +355,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}()
{{/fieldIsInlineStruct}} {{/fieldIsInlineStruct}}
{{/fieldIsStruct}} {{/fieldIsStruct}}
{{! ------------------------------------------------------------------------------------------- }} {{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsList}} {{#fieldIsNonStructList}}
inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() { inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldUnion}} {{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}}, CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
...@@ -367,9 +367,7 @@ inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() { ...@@ -367,9 +367,7 @@ inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}} {{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}})); {{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
} }
{{/fieldIsList}}
{{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsNonStructList}}
inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) { inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
{{#fieldUnion}} {{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}::Which>( _builder.setDataField<{{unionTitleCase}}::Which>(
...@@ -423,6 +421,18 @@ inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}( ...@@ -423,6 +421,18 @@ inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(
{{/fieldIsNonStructList}} {{/fieldIsNonStructList}}
{{! ------------------------------------------------------------------------------------------- }} {{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsStructList}} {{#fieldIsStructList}}
inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Reader(_reader.getListField(
{{fieldOffset}} * ::capnproto::REFERENCES,
::capnproto::internal::FieldSize::INLINE_COMPOSITE,
{{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
}
inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) { inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
{{#fieldUnion}} {{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}::Which>( _builder.setDataField<{{unionTitleCase}}::Which>(
......
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