From 61143f5d126c2bc0cf8af12857c82ab45f6e2128 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Tue, 8 Jun 2021 11:28:01 +0200 Subject: [PATCH] experimental PVLV support Signed-off-by: Wolfgang Bumiller --- perlmod-test/src/pkg142.rs | 12 ++++++++++++ perlmod/src/ffi.rs | 4 ++++ perlmod/src/glue.c | 13 +++++++++++++ perlmod/src/scalar.rs | 17 +++++++++++++++++ test.pl | 8 ++++++++ 5 files changed, 54 insertions(+) diff --git a/perlmod-test/src/pkg142.rs b/perlmod-test/src/pkg142.rs index b45e0cf..6a9b75a 100644 --- a/perlmod-test/src/pkg142.rs +++ b/perlmod-test/src/pkg142.rs @@ -10,4 +10,16 @@ mod export { Ok(a + b) } + + #[export] + fn test(t: Option) -> Result<(), Error> { + println!("test called with {:?}", t); + Ok(()) + } + + #[export] + fn teststr(t: Option<&str>) -> Result<(), Error> { + println!("teststr called with {:?}", t); + Ok(()) + } } diff --git a/perlmod/src/ffi.rs b/perlmod/src/ffi.rs index 1703ecd..b37c661 100644 --- a/perlmod/src/ffi.rs +++ b/perlmod/src/ffi.rs @@ -107,6 +107,10 @@ extern "C" { pub fn RSPL_LEAVE(); pub fn RSPL_sv_reftype(sv: *const SV, ob: libc::c_int) -> *const libc::c_char; + + pub fn RSPL_PVLV() -> u32; + pub fn RSPL_LvTARG(sv: *mut SV) -> *mut SV; + pub fn RSPL_vivify_defelem(sv: *mut SV); } /// Argument marker for the stack. diff --git a/perlmod/src/glue.c b/perlmod/src/glue.c index fcafdd3..63548ca 100644 --- a/perlmod/src/glue.c +++ b/perlmod/src/glue.c @@ -301,6 +301,19 @@ extern const char* RSPL_sv_reftype(const SV *const sv, const int ob) { return sv_reftype(sv, ob); } +// We we don't need to generate the numeric value: +extern uint32_t RSPL_PVLV() { + return SVt_PVLV; +} + +extern SV* RSPL_LvTARG(SV *sv) { + return LvTARG(sv); +} + +extern void RSPL_vivify_defelem(SV *sv) { + Perl_vivify_defelem(aTHX_ sv); +} + /* These make are convoluted brainfarts: SVt_NULL undef diff --git a/perlmod/src/scalar.rs b/perlmod/src/scalar.rs index 7c92191..fb84f04 100644 --- a/perlmod/src/scalar.rs +++ b/perlmod/src/scalar.rs @@ -205,6 +205,10 @@ impl ScalarRef { let ty = ffi::RSPL_svtype(self.sv()); if ty == 0 { Type::Scalar(Flags::empty()) + } else if ty == ffi::RSPL_PVLV() { + self.get_target() + .map(|s| s.ty()) + .unwrap_or(Type::Other(99)) } else { Type::Other(ty as u8) } @@ -213,6 +217,19 @@ impl ScalarRef { } } + /// Dereference this PVLV. + pub fn get_target(&self) -> Option { + let ptr = unsafe { + ffi::RSPL_vivify_defelem(self.sv()); + ffi::RSPL_LvTARG(self.sv()) + }; + if ptr.is_null() { + None + } else { + Some(unsafe { Scalar::from_raw_ref(ptr) }) + } + } + /// Dereference this reference. pub fn dereference(&self) -> Option { let ptr = unsafe { ffi::RSPL_dereference(self.sv()) }; diff --git a/test.pl b/test.pl index 591a462..ea67f69 100644 --- a/test.pl +++ b/test.pl @@ -4,6 +4,7 @@ use v5.28.0; use lib '.'; use RSPM::Bless; +use RSPM::Foo142; my $v = RSPM::Bless->new("Hello"); $v->something(); @@ -13,3 +14,10 @@ my @ret = $v->multi_return(); say "Got: ".scalar(@ret)." values: @ret"; $v->another(54); + +my $param = { a => 1 }; +my $s = "Hello You"; +RSPM::Foo142::test(substr($s, 3, 3)); +RSPM::Foo142::teststr(substr($s, 3, 3)); +RSPM::Foo142::test($param->{x}); +RSPM::Foo142::teststr($param->{x});