Skip to content

Commit 5294a7c

Browse files
committed
#[dyn_alloc] attribute.
Introduce the `#[dyn_alloc]` attribute that applies to extern types only. It tells the compiler that the type allocates its storage dynamically on the heap. Rust knows the size of the stack-allocated portion of such types statically and allows using them as part of recursive typedefs. This is a step towards supporting generic container types. Currently the compiler has built-in support for Vec, Set, Map, TinySet types. Adding new container types, e.g., the immutable containers that will be introduced shortly, requires changes to the compiler. There are two reasons for this. First, the compiler needs to know how to iterate over instances of these types in for-loops. Second, it must be aware that these types allocate their storage dynamically and can therefore be safely used to construct recursive typedefs. This commit takes care of the latter: instead of maintaining a list of known dynamically allocated types in the compiler, we allow the programmer to label types as dynamically allocated using the new attribute.
1 parent 267a13c commit 5294a7c

File tree

5 files changed

+47
-9
lines changed

5 files changed

+47
-9
lines changed

doc/tutorial/tutorial.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3011,6 +3011,18 @@ to optimize data structures layout:
30113011
extern type IObj<'A>
30123012
```
30133013
3014+
### `#[dyn_alloc]`
3015+
3016+
This attribute is applicable to `extern type` declarations. It tells the
3017+
compiler that the type allocates its storage dynamically on the heap. Rust
3018+
knows the size of the stack-allocated portion of such types statically and
3019+
allows using them as part of recursive typedefs.
3020+
3021+
```
3022+
#[dyn_alloc]
3023+
extern type Set<'A>
3024+
```
3025+
30143026
### `#[custom_serde]`
30153027
30163028
Tells DDlog not to generate `Serialize` and `Deserialize` implementations for a type.

lib/ddlog_std.dl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ function max(g: Group<'K, 'V>): 'V {
558558
/*
559559
* Vec
560560
*/
561+
#[dyn_alloc]
561562
extern type Vec<'A>
562563

563564
extern function vec_empty(): Vec<'A>
@@ -667,6 +668,7 @@ function update_nth(v: mut Vec<'X>, idx: usize, value: 'X): bool {
667668
* Map
668669
*/
669670

671+
#[dyn_alloc]
670672
extern type Map<'K,'V>
671673

672674
extern function map_empty(): Map<'K, 'V>
@@ -713,6 +715,7 @@ function keys(m: Map<'K, 'V>): Vec<'K> {
713715
* Set
714716
*/
715717

718+
#[dyn_alloc]
716719
extern type Set<'A>
717720

718721
extern function set_singleton(x: 'X): Set<'X>

lib/tinyset.dl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* `Set64`, which is a set of values that fit in 64 bits and can be cloned by
55
* copying (e.g., 8, 16, 32, or 64-bit integers). */
66

7+
#[dyn_alloc]
78
extern type Set64<'X>
89

910
extern function size(s: Set64<'X>): bit<64>

src/Language/DifferentialDatalog/Attribute.hs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{-
2-
Copyright (c) 2020 VMware, Inc.
2+
Copyright (c) 2021 VMware, Inc.
33
SPDX-License-Identifier: MIT
44
55
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -53,6 +53,7 @@ typedefValidateAttrs d tdef@TypeDef{..} = do
5353
_ <- tdefCheckCustomSerdeAttr d tdef
5454
_ <- tdefCheckCustomFromRecord d tdef
5555
_ <- tdefCheckSharedRefAttr d tdef
56+
_ <- tdefCheckDynAllocAttr d tdef
5657
_ <- tdefCheckAliasAttr d tdef
5758
_ <- checkRustAttrs d tdefAttrs
5859
maybe (return ()) (typeValidateAttrs d) tdefType
@@ -84,6 +85,9 @@ typedefValidateAttr d TypeDef{..} attr = do
8485
$ "'sharef_ref' attribute is only applicable to extern types."
8586
check d (length tdefArgs == 1) (pos attr)
8687
$ "Types annotated with 'shared_ref' must have exactly one type argument, e.g., \"Ref<'T>\"."
88+
"dyn_alloc" -> do
89+
check d (isNothing tdefType) (pos attr)
90+
$ "'dyn_alloc' attribute is only applicable to extern types."
8791
"alias" -> do
8892
case tdefType of
8993
Just TUser{} -> err d (pos attr) "The 'alias' attribute does not apply to struct types."
@@ -203,6 +207,22 @@ tdefGetSharedRefAttr d tdef =
203207
Left e -> error e
204208
Right b -> b
205209

210+
{- 'dyn_alloc' attribute: Tells DDlog that the type is a shared reference in
211+
- the style of `Ref` and `Intern`. -}
212+
tdefCheckDynAllocAttr :: (MonadError String me) => DatalogProgram -> TypeDef -> me Bool
213+
tdefCheckDynAllocAttr d TypeDef{..} =
214+
case find ((== "dyn_alloc") . name) tdefAttrs of
215+
Nothing -> return False
216+
Just attr -> do check d (attrVal attr == eTrue) (pos attr)
217+
"The value of 'dyn_alloc' attribute must be 'true' or empty"
218+
return True
219+
220+
tdefGetDynAllocAttr :: DatalogProgram -> TypeDef -> Bool
221+
tdefGetDynAllocAttr d tdef =
222+
case tdefCheckDynAllocAttr d tdef of
223+
Left e -> error e
224+
Right b -> b
225+
206226
{- 'alias' attribute: Tells DDlog not to generate Rust declaration for the type
207227
- and instead replace all occurrences of the type with its definition. -}
208228
tdefCheckAliasAttr :: (MonadError String me) => DatalogProgram -> TypeDef -> me Bool

src/Language/DifferentialDatalog/Type.hs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{-
2-
Copyright (c) 2018-2020 VMware, Inc.
2+
Copyright (c) 2018-2021 VMware, Inc.
33
SPDX-License-Identifier: MIT
44
55
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -48,7 +48,7 @@ module Language.DifferentialDatalog.Type(
4848
typDeref',
4949
typDeref'',
5050
isBool, isBit, isSigned, isBigInt, isInteger, isFP, isString, isStruct, isTuple, isGroup, isDouble, isFloat,
51-
isMap, isTinySet, isSharedRef,
51+
isMap, isTinySet, isSharedRef, isDynAlloced,
5252
isOption, isResult,
5353
checkTypesMatch,
5454
typesMatch,
@@ -105,10 +105,6 @@ sET_TYPES = [mOD_STD ++ "::Set", mOD_STD ++ "::Vec", tINYSET_TYPE]
105105
tINYSET_TYPE :: String
106106
tINYSET_TYPE = "tinyset::Set64"
107107

108-
-- Dynamically allocated types.
109-
dYNAMIC_TYPES :: [String]
110-
dYNAMIC_TYPES = mAP_TYPE : sET_TYPES
111-
112108
gROUP_TYPE :: String
113109
gROUP_TYPE = mOD_STD ++ "::Group"
114110

@@ -475,6 +471,12 @@ isSharedRef d a =
475471
TOpaque _ t _ -> tdefGetSharedRefAttr d $ getType d t
476472
_ -> False
477473

474+
isDynAlloced :: (WithType a) => DatalogProgram -> a -> Bool
475+
isDynAlloced d a =
476+
case typ' d a of
477+
TOpaque _ t _ -> tdefGetDynAllocAttr d $ getType d t
478+
_ -> False
479+
478480
isOption :: (WithType a) => DatalogProgram -> a -> Bool
479481
isOption d a = case typ'' d a of
480482
TUser _ t _ | t == oPTION_TYPE -> True
@@ -546,9 +548,9 @@ typeStaticMemberTypes' :: DatalogProgram -> Type -> [String]
546548
typeStaticMemberTypes' d TStruct{..} = concatMap (typeStaticMemberTypes d . typ)
547549
$ concatMap consArgs typeCons
548550
typeStaticMemberTypes' d TTuple{..} = concatMap (typeStaticMemberTypes d . typ) typeTupArgs
549-
typeStaticMemberTypes' d t@TUser{..} | elem typeName dYNAMIC_TYPES || isSharedRef d t = []
551+
typeStaticMemberTypes' d t@TUser{..} | isDynAlloced d t || isSharedRef d t = []
550552
| otherwise = typeName : concatMap (typeStaticMemberTypes d) typeArgs
551-
typeStaticMemberTypes' d t@TOpaque{..} | elem typeName dYNAMIC_TYPES || isSharedRef d t = []
553+
typeStaticMemberTypes' d t@TOpaque{..} | isDynAlloced d t || isSharedRef d t = []
552554
| otherwise = concatMap (typeStaticMemberTypes d) typeArgs
553555
typeStaticMemberTypes' _ _ = []
554556

0 commit comments

Comments
 (0)