Macro cell_gc::gc_heap_type
[−]
[src]
macro_rules! gc_heap_type { { $(#[$attr:meta])* pub enum $($etc:tt)* } => { ... }; { $(#[$attr:meta])* enum $($etc:tt)* } => { ... }; { $(#[$attr:meta])* pub struct $($etc:tt)* } => { ... }; { $(#[$attr:meta])* struct $($etc:tt)* } => { ... }; { @as_item $x:item } => { ... }; { @as_expr $x:expr } => { ... }; { @gc_heap_struct ( $(#[$attr:meta])* ) ( $($maybe_pub:tt)* ) struct $fields_type:ident / $ref_type:ident / $storage_type:ident <'h> { $($field_name:ident / $field_setter_name:ident : $field_type: ty),* } } => { ... }; { @for_each_variant $_helper:tt {} $all_results:tt ($($ctn:tt)*) } => { ... }; { @for_each_variant ($($helper:tt)*) { $variant_name:ident } $acc:tt $ctn:tt } => { ... }; { @for_each_variant ($($helper:tt)*) { $variant_name:ident , $($more_variants:tt)* } $acc:tt $ctn:tt } => { ... }; { @for_each_variant ($($helper:tt)*) { $variant_name:ident ( $($field_types:tt)* ) } $acc:tt $ctn:tt } => { ... }; { @for_each_variant ($($helper:tt)*) { $variant_name:ident ( $($field_types:tt)* ), $($more_variants:tt)* } $acc:tt $ctn:tt } => { ... }; { @for_each_variant ($($helper:tt)*) { $variant_name:ident { $($field_name:ident : $field_type:ty),* } } $acc:tt $ctn:tt } => { ... }; { @for_each_variant ($($helper:tt)*) { $variant_name:ident { $($field_name:ident : $field_type:ty),* }, $($more_variants:tt)* } $acc:tt $ctn:tt } => { ... }; { @next_variant $helper:tt $more_variants:tt { $($acc:tt)* } $ctn:tt { $($rv:tt)* } } => { ... }; { @zip_idents_with_types $_leftovers:tt () ($(($binding:ident : $btype:ty))*) ($($ctn:tt)*) } => { ... }; { @zip_idents_with_types ($id:ident $($ids:tt)*) (($t:ty) $($ts:tt)*) ($($acc:tt)*) $ctn:tt } => { ... }; { @enum_in_heap_variant $variant_name:ident NO_FIELDS ($($ctn:tt)*) } => { ... }; { @enum_in_heap_variant $variant_name:ident ( $($field_type:ty),* ) ($($ctn:tt)*) } => { ... }; { @enum_in_heap_variant $variant_name:ident { $($field_name:ident : $field_type:ty),* } ($($ctn:tt)*) } => { ... }; { @enum_declare_in_heap_type ( $($maybe_pub:tt)* ) $storage_type:ident { $($variants:tt)* } } => { ... }; { @enum_mark_variant $storage_type:ident $name:ident NO_FIELDS ($($ctn:tt)*) } => { ... }; { @enum_mark_variant $storage_type:ident $name:ident ( $($field_type:ty),* ) $ctn:tt } => { ... }; { @enum_mark_variant_continued $storage_type:ident $name:ident ($($ctn:tt)*) ( $(($binding:ident : $field_type:ty))* ) } => { ... }; { @enum_mark_variant $storage_type:ident $name:ident { $($field_name:ident : $field_type:ty),* } ($($ctn:tt)*) } => { ... }; { @enum_mark_expr ($self_ref:expr) { $($arms:tt)* } } => { ... }; { @enum_into_heap_variant $stack_type:ident $storage_type:ident $name:ident NO_FIELDS ($($ctn:tt)*) } => { ... }; { @enum_into_heap_variant $stack_type:ident $storage_type:ident $name:ident ( $($field_type:ty),* ) $ctn:tt } => { ... }; { @enum_into_heap_variant_continued $stack_type:ident $storage_type:ident $name:ident ($($ctn:tt)*) ( $(($binding:ident : $field_type:ty))* ) } => { ... }; { @enum_into_heap_variant $stack_type:ident $storage_type:ident $name:ident { $($field_name:ident : $field_type:ty),* } ($($ctn:tt)*) } => { ... }; { @enum_into_heap_expr ($self_:expr) { $($accumulated_output:tt)* } } => { ... }; { @enum_from_heap_variant $stack_type:ident $storage_type:ident $name:ident NO_FIELDS ($($ctn:tt)*) } => { ... }; { @enum_from_heap_variant $stack_type:ident $storage_type:ident $name:ident ( $($field_type:ty),* ) $ctn:tt } => { ... }; { @enum_from_heap_variant_continued $stack_type:ident $storage_type:ident $name:ident ($($ctn:tt)*) ( $(($binding:ident : $field_type:ty))* ) } => { ... }; { @enum_from_heap_variant $stack_type:ident $storage_type:ident $name:ident { $($field_name:ident : $field_type:ty),* } ($($ctn:tt)*) } => { ... }; { @enum_from_heap_expr ($self_ref:expr) { $($arms:tt)* } } => { ... }; { @gc_heap_enum ($(#[$attr:meta])*) ($($maybe_pub:tt)*) enum $stack_type:ident / $storage_type:ident <'h> $variants:tt } => { ... }; }
The gc_heap_type!
macro can declare structs and enums for use with Heap::alloc
.
The argument to `gc_heap_type! is a struct or enum, with the following syntax:
heap-type: attr* heap-struct attr* heap-enum attr: "#" "[" META "]" heap-struct: "pub"? "struct" IDENT "/" IDENT "/" IDENT "<'h>" "{" heap-struct-field,* "}" heap-struct-field: IDENT / IDENT ":" TYPE heap-enum: "pub"? "enum" IDENT "/" IDENT "<'h>" "{" heap-enum-variant,* "}" heap-enum-variant: IDENT IDENT "(" TYPE,* ")"
This syntax is almost a subset of real Rust struct and enum syntax. The only difference is that in some places we require two or three identifiers, instead of one:
The three names of a struct are: (1) the type you'll use to create instances and call
heap.alloc
with; (2) aRef
smart pointer type (whatheap.alloc
returns; and (3) the in-heap version of the struct, which you can just ignore. Attributes that appear in your code are applied only to the first of these three types.The two names of a struct field are: (1) the field name, which doubles as the name of the getter on the
Ref
struct; (2) the setter name.The two names of an enum are (1) the type you'll use; (2) the in-heap version of the enum, which you can just ignore. Threre's not a
Ref
type because at the moment, we don't support direct allocation of enums in the heap; they can only be fields of heap structs.
The exact lifetime name 'h
is required. (A bizarre restriction - but
I had little success getting the macro to accept an arbitrary lifetime
passed in by the macro caller.)
Trailing commas are not supported everywhere they should be. (Sorry!)
Examples
A very simple "object" type for a text adventure game:
#[macro_use] extern crate cell_gc; use cell_gc::collections::VecRef; gc_heap_type! { struct Object / ObjectRef / ObjectInHeap <'h> { name / set_name : String, description / set_description: String, children / set_children: VecRef<'h, ObjectRef<'h>> } }
Note that children
is a VecRef<'h, ObjectRef<'h>>
; that is, it is
a reference to a separately GC-allocated Vec<ObjectRef<'h>>
, which is
a vector of references to other objects. In other words, this is exactly
what you would have in Java for a field declared like this:
public ArrayList<Object> children;
The API generated by this macro looks like this:
struct Object<'h> { name: String, description: String, children: VecRef<'h, ObjectRef<'h>> } struct ObjectRef<'h> { /* all fields private */ } impl<'h> ObjectRef<'h> { fn name(&self) -> String fn set_name(&self, name: String) fn description(&self) -> String fn set_description(&self, description: String) fn children(&self) -> VecRef<'h, ObjectRef<'h>> fn set_children(&self, children: VecRef<'h, ObjectRef<'h>>) }
(You may never actually use that set_children()
method.
Instead, you'll initialize the children
field with a vector when you
create the object, and then you'll most likely mutate that existing vector
rather than ever creating a new one.)
You can allocate Object
s in the heap using heap.alloc(Object { ... })
,
and make one Object
a child of another by using obj1.children().push(obj2)
.