Description
I've been trying to marshall a type constructor with 2 parameters and it appears that the stack is not aligning correctly. I'm probably not using the Getable and Pushable traits correctly, any pointers would be great. Here is some example code outlining the issue:
#[macro_use]
extern crate gluon_codegen;
#[macro_use]
extern crate gluon_vm;
use gluon::{
base::types::ArcType,
import::add_extern_module,
new_vm,
vm::{
api::{ActiveThread, Getable, Pushable, UserdataValue, ValueRef, VmType},
internal::Value,
thread::Thread,
ExternModule, Result, Variants,
},
Compiler,
};
#[derive(Debug, Clone)]
struct ExternalValue(f64);
#[derive(Debug, Clone, Userdata)]
struct ValueWrapper(ExternalValue);
impl ValueWrapper {
fn new(_: ()) -> ValueWrapper {
ValueWrapper(ExternalValue(0.0))
}
fn load(vm: &Thread) -> Result<ExternModule> {
vm.register_type::<ValueWrapper>("Value", &[])?;
ExternModule::new(
vm,
record! {
type Value => ValueWrapper,
new => primitive!(1, ValueWrapper::new),
},
)
}
}
#[derive(Debug)]
enum ExternalEnumOne {
One,
Two(f64, f64),
}
#[derive(Debug)]
struct EnumOneWrapper(ExternalEnumOne);
impl VmType for EnumOneWrapper {
type Type = Self;
fn make_type(vm: &Thread) -> ArcType {
vm.find_type_info("example.types.EnumOne")
.expect("Could not find type EnumOneWrapper")
.into_type()
}
}
impl<'vm> Pushable<'vm> for EnumOneWrapper {
fn push(self, context: &mut ActiveThread<'vm>) -> Result<()> {
match self.0 {
ExternalEnumOne::One => context.push(Value::tag(0)),
ExternalEnumOne::Two(one, two) => {
one.push(context)?;
two.push(context)?;
let thread = context.thread();
context.context().push_new_data(thread, 1, 2).unwrap();
}
};
Ok(())
}
}
impl<'vm, 'value> Getable<'vm, 'value> for EnumOneWrapper {
fn from_value(_vm: &'vm Thread, data: Variants<'value>) -> EnumOneWrapper {
match data.as_ref() {
ValueRef::Data(data) => match data.tag() {
0 => EnumOneWrapper(ExternalEnumOne::One),
1 => EnumOneWrapper(ExternalEnumOne::Two(
match data.get(0).unwrap() {
ValueRef::Float(value) => value,
_ => panic!("Failed to marshall ExternalEnumOne::Two"),
},
match data.get(1).unwrap() {
ValueRef::Float(value) => value,
_ => panic!("Failed to marshall ExternalEnumOne::Two"),
},
)),
_ => panic!("Invalid VmTag for EnumOneWrapper."),
},
_ => panic!("EnumOneWrapper is not a complex type."),
}
}
}
#[derive(Debug)]
enum ExternalEnumTwo {
A(ExternalEnumOne),
B {
value: ExternalValue,
enum_one: ExternalEnumOne,
},
}
#[derive(Debug)]
struct EnumTwoWrapper(ExternalEnumTwo);
impl EnumTwoWrapper {
fn id(self) -> EnumTwoWrapper {
self
}
fn load(vm: &Thread) -> Result<ExternModule> {
ExternModule::new(
vm,
record! {
id => primitive!(1, EnumTwoWrapper::id),
},
)
}
}
impl VmType for EnumTwoWrapper {
type Type = Self;
fn make_type(vm: &Thread) -> ArcType {
vm.find_type_info("example.types.EnumTwo")
.expect("Could not find type EnumTwoWrapper")
.into_type()
}
}
impl<'vm> Pushable<'vm> for EnumTwoWrapper {
fn push(self, context: &mut ActiveThread<'vm>) -> Result<()> {
match self.0 {
ExternalEnumTwo::A(value) => {
EnumOneWrapper(value).push(context)?;
let thread = context.thread();
context.context().push_new_data(thread, 0, 1).unwrap();
}
ExternalEnumTwo::B { value, enum_one } => {
(record! {
value => ValueWrapper(value),
enum_one => EnumOneWrapper(enum_one)
})
.push(context)?;
let thread = context.thread();
context.context().push_new_data(thread, 1, 1).unwrap();
}
};
Ok(())
}
}
impl<'vm, 'value> Getable<'vm, 'value> for EnumTwoWrapper {
fn from_value(vm: &'vm Thread, data: Variants<'value>) -> EnumTwoWrapper {
match data.as_ref() {
ValueRef::Data(data) => match data.tag() {
0 => EnumTwoWrapper(ExternalEnumTwo::A(
EnumOneWrapper::from_value(vm, data.get_variant(0).unwrap()).0,
)),
1 => match data.get(0).unwrap() {
ValueRef::Data(data) => {
let UserdataValue(ValueWrapper(external_value)) =
<UserdataValue<ValueWrapper>>::from_value(
vm,
data.lookup_field(vm, "value").unwrap(),
);
EnumTwoWrapper(ExternalEnumTwo::B {
value: external_value,
enum_one: EnumOneWrapper::from_value(
vm,
data.lookup_field(vm, "enum_one").unwrap(),
)
.0,
})
}
_ => panic!("Unable to marshall ExternalEnumTwo::B."),
},
_ => panic!("Invalid VmTag for EnumTwoWrapper."),
},
_ => panic!("EnumTwoWrapper is not a complex type."),
}
}
}
fn main() {
let vm = new_vm();
let mut compiler = Compiler::new();
add_extern_module(&vm, "example.value", ValueWrapper::load);
let src = r#"
let { Value } = import! example.value
type EnumOne = | One | Two Float Float
type EnumTwo = | A EnumOne | B { value: Value, enum_one: EnumOne }
{
EnumOne,
EnumTwo,
}
"#;
compiler.load_script(&vm, "example.types", src).unwrap();
add_extern_module(&vm, "example.enum_two.prim", EnumTwoWrapper::load);
let script1 = r#"
let { EnumOne, EnumTwo } = import! example.types
let { id } = import! example.enum_two.prim
id (A One)
"#;
let (value, _) = compiler
.run_expr::<EnumTwoWrapper>(&vm, "example1", script1)
.unwrap();
println!("{:#?}", value);
let script2 = r#"
let { new } = import! example.value
let { EnumOne, EnumTwo } = import! example.types
let { id } = import! example.enum_two.prim
id (B { value = new (), enum_one = One })
"#;
let (value, _) = compiler
.run_expr::<EnumTwoWrapper>(&vm, "example2", script2)
.unwrap();
println!("{:#?}", value);
let script3 = r#"
let { new } = import! example.value
let { EnumOne, EnumTwo } = import! example.types
let { id } = import! example.enum_two.prim
id (B { value = new (), enum_one = Two 0.0 0.0 })
"#;
let (value, _) = compiler
.run_expr::<EnumTwoWrapper>(&vm, "example3", script3)
.unwrap();
println!("{:#?}", value);
}
I get the error 'ValueRef is not an Userdata' and it looks like one of the arguments passed to the 'Two' constructor is causing a misalignment of the stack. I modified gluon locally to print out the data that is trying to get interpreted as Userdata and it shows Float(0.0). Here is the output of running the script:
EnumTwoWrapper(
A(
One
)
)
EnumTwoWrapper(
B {
value: ExternalValue(
0.0
),
enum_one: One
}
)
thread 'main' panicked at 'ValueRef is not an Userdata: Float(
0.0
)', /home/tyler/Desktop/vulkan/gluon/vm/src/api/mod.rs:629:22
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:71
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:59
at src/libstd/panicking.rs:211
3: std::panicking::default_hook
at src/libstd/panicking.rs:227
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:491
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:398
6: std::panicking::begin_panic_fmt
at src/libstd/panicking.rs:353
7: <&'value T as gluon_vm::api::Getable<'vm, 'value>>::from_value
at ./<::std::macros::panic macros>:8
8: <gluon_vm::api::UserdataValue<T> as gluon_vm::api::Getable<'vm, 'value>>::from_value
at /home/tyler/Desktop/vulkan/gluon/vm/src/api/mod.rs:601
9: <marshall_test::EnumTwoWrapper as gluon_vm::api::Getable<'vm, 'value>>::from_value
at src/main.rs:169
10: gluon::Compiler::run_expr::{{closure}}
at /home/tyler/Desktop/vulkan/gluon/src/lib.rs:602
11: <futures::future::and_then::AndThen<A, B, F> as futures::future::Future>::poll::{{closure}}::{{closure}}
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/future/and_then.rs:34
12: <core::result::Result<T, E>>::map
at /rustc/9fda7c2237db910e41d6a712e9a2139b352e558b/src/libcore/result.rs:468
13: <futures::future::and_then::AndThen<A, B, F> as futures::future::Future>::poll::{{closure}}
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/future/and_then.rs:33
14: <futures::future::chain::Chain<A, B, C>>::poll
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/future/chain.rs:39
15: <futures::future::and_then::AndThen<A, B, F> as futures::future::Future>::poll
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/future/and_then.rs:32
16: <futures::task_impl::Spawn<T>>::poll_future_notify::{{closure}}
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/mod.rs:329
17: <futures::task_impl::Spawn<T>>::enter::{{closure}}
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/mod.rs:399
18: futures::task_impl::std::set
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/std/mod.rs:78
19: <futures::task_impl::Spawn<T>>::enter
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/mod.rs:399
20: <futures::task_impl::Spawn<T>>::poll_fn_notify
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/mod.rs:291
21: <futures::task_impl::Spawn<T>>::poll_future_notify
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/mod.rs:329
22: futures::task_impl::std::<impl futures::task_impl::Spawn<F>>::wait_future::{{closure}}
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/std/mod.rs:231
23: futures::task_impl::std::ThreadNotify::with_current::{{closure}}
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/std/mod.rs:478
24: <std::thread::local::LocalKey<T>>::try_with
at /rustc/9fda7c2237db910e41d6a712e9a2139b352e558b/src/libstd/thread/local.rs:309
25: <std::thread::local::LocalKey<T>>::with
at /rustc/9fda7c2237db910e41d6a712e9a2139b352e558b/src/libstd/thread/local.rs:255
26: futures::task_impl::std::ThreadNotify::with_current
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/std/mod.rs:478
27: futures::task_impl::std::<impl futures::task_impl::Spawn<F>>::wait_future
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/task_impl/std/mod.rs:228
28: futures::future::Future::wait
at /home/tyler/.cargo/registry/src/github.yoyoweb123.workers.dev-1ecc6299db9ec823/futures-0.1.26/src/future/mod.rs:299
29: gluon::Compiler::run_expr
at /home/tyler/Desktop/vulkan/gluon/src/lib.rs:598
30: marshall_test::main
at src/main.rs:238
31: std::rt::lang_start::{{closure}}
at /rustc/9fda7c2237db910e41d6a712e9a2139b352e558b/src/libstd/rt.rs:74
32: std::panicking::try::do_call
at src/libstd/rt.rs:59
at src/libstd/panicking.rs:310
33: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:102
34: std::rt::lang_start_internal
at src/libstd/panicking.rs:289
at src/libstd/panic.rs:398
at src/libstd/rt.rs:58
35: std::rt::lang_start
at /rustc/9fda7c2237db910e41d6a712e9a2139b352e558b/src/libstd/rt.rs:74
36: main
37: __libc_start_main
38: _start
Activity