Skip to content

Commit

Permalink
feat(vm): Let Getable return types bound to the lifetime of Variants (g…
Browse files Browse the repository at this point in the history
…luon-lang#587)

feat(vm): Let `Getable` return types bound to the lifetime of Variants
  • Loading branch information
Marwes authored Jul 12, 2018
1 parent bbbb0e3 commit 010a7f7
Show file tree
Hide file tree
Showing 11 changed files with 3,057 additions and 3,048 deletions.
2 changes: 1 addition & 1 deletion c-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ pub extern "C" fn glu_get_light_userdata(

fn get_value<T>(vm: &Thread, index: VmIndex, out: &mut T) -> Error
where
T: for<'vm> Getable<'vm>,
T: for<'vm, 'value> Getable<'vm, 'value>,
{
let mut context = vm.context();
let stack = context.stack.current_frame();
Expand Down
20 changes: 11 additions & 9 deletions codegen/src/getable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ where

quote! {
#ident: if let Some(val) = data.lookup_field(vm, #quoted_ident) {
<#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
<#field_ty as ::gluon::vm::api::Getable<'__vm, '__value>>::from_value(vm, val)
} else {
panic!("Cannot find the field '{}'. Do the type definitions match?", #quoted_ident);
}
Expand All @@ -72,7 +72,7 @@ where

quote! {
if let Some(val) = data.get_variant(#tag) {
<#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
<#field_ty as ::gluon::vm::api::Getable<'__vm, '__value>>::from_value(vm, val)
} else {
panic!("Cannot find the field with tag '{}'. Do the type definitions match?", #tag);
}
Expand All @@ -89,7 +89,8 @@ where
fn derive_enum(ast: DataEnum, ident: Ident, generics: Generics) -> TokenStream {
let cons;
{
let variants = ast.variants
let variants = ast
.variants
.iter()
.enumerate()
.map(|(tag, variant)| gen_variant_match(&ident, tag, variant));
Expand All @@ -116,15 +117,16 @@ fn gen_impl(ident: Ident, generics: Generics, cons_expr: TokenStream) -> TokenSt
// generate bounds like T: Getable for every type parameter
let getable_bounds = create_getable_bounds(&generics);

let (impl_generics, ty_generics, where_clause) = split_for_impl(&generics, &["'__vm"]);
let (impl_generics, ty_generics, where_clause) =
split_for_impl(&generics, &["'__vm", "'__value"]);

quote! {
#[automatically_derived]
#[allow(unused_attributes, unused_variables)]
impl #impl_generics ::gluon::vm::api::Getable<'__vm> for #ident #ty_generics
impl #impl_generics ::gluon::vm::api::Getable<'__vm, '__value> for #ident #ty_generics
#where_clause #(#getable_bounds,)* #(#lifetime_bounds),*
{
fn from_value(vm: &'__vm ::gluon::vm::thread::Thread, variants: ::gluon::vm::Variants) -> Self {
fn from_value(vm: &'__vm ::gluon::vm::thread::Thread, variants: ::gluon::vm::Variants<'__value>) -> Self {
let data = match variants.as_ref() {
::gluon::vm::api::ValueRef::Data(data) => data,
val => panic!("Unexpected value: '{:?}'. Do the type definitions match?", val),
Expand Down Expand Up @@ -174,7 +176,7 @@ where

quote! {
if let Some(val) = data.get_variant(#idx) {
<#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
<#field_ty as ::gluon::vm::api::Getable<'__vm, '__value>>::from_value(vm, val)
} else {
panic!("Enum does not contain data at index '{}'. Do the type definitions match?", #idx)
}
Expand All @@ -199,7 +201,7 @@ where

quote! {
#field_ident: if let Some(val) = data.get_variant(#idx) {
<#field_ty as ::gluon::vm::api::Getable<'__vm>>::from_value(vm, val)
<#field_ty as ::gluon::vm::api::Getable<'__vm, '__value>>::from_value(vm, val)
} else {
panic!("Enum does not contain data at index '{}'. Do the type definitions match?", #idx)
}
Expand All @@ -214,7 +216,7 @@ where
fn create_getable_bounds(generics: &Generics) -> Vec<TokenStream> {
map_type_params(generics, |ty| {
quote! {
#ty: ::gluon::vm::api::Getable<'__vm>
#ty: ::gluon::vm::api::Getable<'__vm, '__value>
}
})
}
Expand Down
4 changes: 2 additions & 2 deletions examples/http/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ struct StatusCodeContainer(#[serde(with = "RemoteStatusCode")] StatusCode);

define_vmtype! { StatusCode, StatusCodeContainer }

impl<'vm> Getable<'vm> for Wrap<StatusCode> {
fn from_value(vm: &'vm Thread, value: Variants) -> Self {
impl<'vm, 'value> Getable<'vm, 'value> for Wrap<StatusCode> {
fn from_value(vm: &'vm Thread, value: Variants<'value>) -> Self {
use gluon::vm::api::de::De;
Wrap((De::<StatusCodeContainer>::from_value(vm, value).0).0)
}
Expand Down
15 changes: 8 additions & 7 deletions examples/marshalling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ impl api::VmType for Enum {
}
}

impl<'vm> api::Pushable<'vm> for Enum {
impl<'vm, 'value> api::Pushable<'vm> for Enum {
fn push(self, thread: &'vm Thread, context: &mut Context) -> vm::Result<()> {
api::ser::Ser(self).push(thread, context)
}
}

impl<'vm> api::Getable<'vm> for Enum {
fn from_value(thread: &'vm Thread, value: vm::Variants) -> Self {
impl<'vm, 'value> api::Getable<'vm, 'value> for Enum {
fn from_value(thread: &'vm Thread, value: vm::Variants<'value>) -> Self {
api::de::De::from_value(thread, value).0
}
}
Expand Down Expand Up @@ -241,7 +241,8 @@ where

fn make_type(vm: &Thread) -> ArcType {
// get the type defined in Gluon
let ty = vm.find_type_info("examples.wrapper.User")
let ty = vm
.find_type_info("examples.wrapper.User")
.expect("Could not find type")
.into_type();

Expand Down Expand Up @@ -275,11 +276,11 @@ where
}
}

impl<'vm, T> Getable<'vm> for GluonUser<T>
impl<'vm, 'value, T> Getable<'vm, 'value> for GluonUser<T>
where
T: Getable<'vm>,
T: Getable<'vm, 'value>,
{
fn from_value(vm: &'vm Thread, data: Variants) -> GluonUser<T> {
fn from_value(vm: &'vm Thread, data: Variants<'value>) -> GluonUser<T> {
// get the data, it must be a complex type
let data = match data.as_ref() {
ValueRef::Data(data) => data,
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ impl Compiler {
expr_str: &str,
) -> Result<(T, ArcType)>
where
T: Getable<'vm> + VmType + Send + 'vm,
T: for<'value> Getable<'vm, 'value> + VmType + Send + 'vm,
{
let expected = T::make_type(vm);
expr_str
Expand Down Expand Up @@ -564,7 +564,7 @@ impl Compiler {
expr_str: &str,
) -> BoxFutureValue<'static, (T, ArcType), Error>
where
T: for<'vm> Getable<'vm> + VmType + Send + 'static,
T: for<'vm, 'value> Getable<'vm, 'value> + VmType + Send + 'static,
{
let expected = T::make_type(&vm);
let vm = vm.root_thread();
Expand Down
4 changes: 2 additions & 2 deletions tests/support/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn load_script(vm: &Thread, filename: &str, input: &str) -> ::gluon::Result<
#[allow(dead_code)]
pub fn run_expr_<'vm, T>(vm: &'vm Thread, s: &str, implicit_prelude: bool) -> T
where
T: Getable<'vm> + VmType + Send + 'vm,
T: for<'value> Getable<'vm, 'value> + VmType + Send + 'vm,
{
Compiler::new()
.implicit_prelude(implicit_prelude)
Expand All @@ -33,7 +33,7 @@ where
#[allow(dead_code)]
pub fn run_expr<'vm, T>(vm: &'vm Thread, s: &str) -> T
where
T: Getable<'vm> + VmType + Send + 'vm,
T: for<'value> Getable<'vm, 'value> + VmType + Send + 'vm,
{
run_expr_(vm, s, false)
}
Expand Down
Loading

0 comments on commit 010a7f7

Please sign in to comment.