pub struct Cv(/* private fields */);Expand description
Non-null pointer to a Perl CV. Same ABI as *mut CV.
Implementations§
Source§impl Cv
impl Cv
Sourcepub unsafe fn from_raw_unchecked(p: *mut CV) -> Self
pub unsafe fn from_raw_unchecked(p: *mut CV) -> Self
Wrap a raw *mut CV without checking for null.
§Safety
Caller must guarantee p is non-null and points to a valid CV
for at least the lifetime of the resulting Cv.
Sourcepub fn from_coderef(sv: *mut SV) -> Option<Cv>
pub fn from_coderef(sv: *mut SV) -> Option<Cv>
Dereference a Perl-level coderef SV (\&sub, sub {...})
into its CV. Returns None when sv is null, not a
reference, or references something other than a CODE value.
Sourcepub fn is_xsub(&self) -> bool
pub fn is_xsub(&self) -> bool
True when this CV is an XSUB (C-implemented). XSUBs have no
OP tree; root / start / padlist return null for them.
Sourcepub fn padlist(&self) -> *const PADLIST
pub fn padlist(&self) -> *const PADLIST
The CV’s PADLIST (lexical scratchpad), or null for XSUBs.
Sourcepub fn file(&self) -> Option<String>
pub fn file(&self) -> Option<String>
Source file the sub was compiled from (CvFILE);
"(eval N)" for string-eval’d subs.
Examples found in repository?
29fn main() {
30 let mut perl = Perl::new();
31 perl.parse_env_args(env::args(), env::vars());
32
33 let sv0 = perl.get_sv("0", 0).expect("$0 is always set");
34 let main_file = String::from_utf8_lossy(sv0.pv(&perl)).into_owned();
35 println!("$0 = {main_file:?}");
36
37 let mut walker = StashWalker::new(&perl);
38 walker.walk("main", &mut |e| {
39 let file = e.cv.file();
40 println!("sub {}::{} file {:?}", e.package, e.name, file);
41 if file.as_deref() == Some(main_file.as_str()) {
42 if let Some(root) = e.cv.root_op() {
43 print_tree(&perl, root, 1);
44 }
45 }
46 });
47}More examples
19fn main() {
20 let mut perl = Perl::new();
21 perl.parse_env_args(env::args(), env::vars());
22
23 let sv0 = perl.get_sv("0", 0).expect("$0 is always set");
24 let main_file = String::from_utf8_lossy(sv0.pv(&perl)).into_owned();
25 println!("$0 = {main_file:?}");
26
27 let mut walker = StashWalker::new(&perl);
28 walker.walk("main", &mut |e| {
29 if e.cv.file().as_deref() != Some(main_file.as_str()) {
30 return;
31 }
32 let qual = e
33 .cv
34 .names(&perl)
35 .map(|(full, _)| full)
36 .unwrap_or_else(|| format!("{}::{}", e.package, e.name));
37 let line = e.cv.first_cop(&perl).map(|c| c.line());
38 println!("sub {qual} (first statement at line {line:?})");
39
40 let lexicals: Vec<String> = e
41 .cv
42 .pad_names()
43 .flatten() // skip unnamed slots
44 .filter_map(|pn| {
45 // Target/temporary slots have a non-null but empty PV;
46 // only real `my`/`our` names are interesting here.
47 let pv = pn.pv().filter(|s| !s.is_empty())?;
48 Some(match pn.type_stash_name() {
49 Some(t) => format!("{pv}: {t}"),
50 None => pv,
51 })
52 })
53 .collect();
54 println!(" lexicals: {lexicals:?}");
55
56 let ops: Vec<&str> = e
57 .cv
58 .start_op()
59 .into_iter()
60 .flat_map(|s| s.next_iter())
61 .take(20)
62 .map(|o| o.name().unwrap_or("<custom>"))
63 .collect();
64 println!(" ops (execution order, first 20): {}", ops.join(" "));
65 });
66}Sourcepub fn root_op(&self) -> Option<Op>
pub fn root_op(&self) -> Option<Op>
Examples found in repository?
29fn main() {
30 let mut perl = Perl::new();
31 perl.parse_env_args(env::args(), env::vars());
32
33 let sv0 = perl.get_sv("0", 0).expect("$0 is always set");
34 let main_file = String::from_utf8_lossy(sv0.pv(&perl)).into_owned();
35 println!("$0 = {main_file:?}");
36
37 let mut walker = StashWalker::new(&perl);
38 walker.walk("main", &mut |e| {
39 let file = e.cv.file();
40 println!("sub {}::{} file {:?}", e.package, e.name, file);
41 if file.as_deref() == Some(main_file.as_str()) {
42 if let Some(root) = e.cv.root_op() {
43 print_tree(&perl, root, 1);
44 }
45 }
46 });
47}Sourcepub fn start_op(&self) -> Option<Op>
pub fn start_op(&self) -> Option<Op>
Examples found in repository?
19fn main() {
20 let mut perl = Perl::new();
21 perl.parse_env_args(env::args(), env::vars());
22
23 let sv0 = perl.get_sv("0", 0).expect("$0 is always set");
24 let main_file = String::from_utf8_lossy(sv0.pv(&perl)).into_owned();
25 println!("$0 = {main_file:?}");
26
27 let mut walker = StashWalker::new(&perl);
28 walker.walk("main", &mut |e| {
29 if e.cv.file().as_deref() != Some(main_file.as_str()) {
30 return;
31 }
32 let qual = e
33 .cv
34 .names(&perl)
35 .map(|(full, _)| full)
36 .unwrap_or_else(|| format!("{}::{}", e.package, e.name));
37 let line = e.cv.first_cop(&perl).map(|c| c.line());
38 println!("sub {qual} (first statement at line {line:?})");
39
40 let lexicals: Vec<String> = e
41 .cv
42 .pad_names()
43 .flatten() // skip unnamed slots
44 .filter_map(|pn| {
45 // Target/temporary slots have a non-null but empty PV;
46 // only real `my`/`our` names are interesting here.
47 let pv = pn.pv().filter(|s| !s.is_empty())?;
48 Some(match pn.type_stash_name() {
49 Some(t) => format!("{pv}: {t}"),
50 None => pv,
51 })
52 })
53 .collect();
54 println!(" lexicals: {lexicals:?}");
55
56 let ops: Vec<&str> = e
57 .cv
58 .start_op()
59 .into_iter()
60 .flat_map(|s| s.next_iter())
61 .take(20)
62 .map(|o| o.name().unwrap_or("<custom>"))
63 .collect();
64 println!(" ops (execution order, first 20): {}", ops.join(" "));
65 });
66}Sourcepub fn gv(&self, perl: &Perl) -> Option<Gv>
pub fn gv(&self, perl: &Perl) -> Option<Gv>
The GV the sub was defined through (CvGV), if any. Gives
access to the sub’s package-qualified name and the glob’s
file / line.
Sourcepub fn names(&self, perl: &Perl) -> Option<(String, String)>
pub fn names(&self, perl: &Perl) -> Option<(String, String)>
The sub’s (qualified, unqualified) name pair
(("Foo::bar", "bar")), resolved via Cv::gv. None for
nameless subs.
Examples found in repository?
19fn main() {
20 let mut perl = Perl::new();
21 perl.parse_env_args(env::args(), env::vars());
22
23 let sv0 = perl.get_sv("0", 0).expect("$0 is always set");
24 let main_file = String::from_utf8_lossy(sv0.pv(&perl)).into_owned();
25 println!("$0 = {main_file:?}");
26
27 let mut walker = StashWalker::new(&perl);
28 walker.walk("main", &mut |e| {
29 if e.cv.file().as_deref() != Some(main_file.as_str()) {
30 return;
31 }
32 let qual = e
33 .cv
34 .names(&perl)
35 .map(|(full, _)| full)
36 .unwrap_or_else(|| format!("{}::{}", e.package, e.name));
37 let line = e.cv.first_cop(&perl).map(|c| c.line());
38 println!("sub {qual} (first statement at line {line:?})");
39
40 let lexicals: Vec<String> = e
41 .cv
42 .pad_names()
43 .flatten() // skip unnamed slots
44 .filter_map(|pn| {
45 // Target/temporary slots have a non-null but empty PV;
46 // only real `my`/`our` names are interesting here.
47 let pv = pn.pv().filter(|s| !s.is_empty())?;
48 Some(match pn.type_stash_name() {
49 Some(t) => format!("{pv}: {t}"),
50 None => pv,
51 })
52 })
53 .collect();
54 println!(" lexicals: {lexicals:?}");
55
56 let ops: Vec<&str> = e
57 .cv
58 .start_op()
59 .into_iter()
60 .flat_map(|s| s.next_iter())
61 .take(20)
62 .map(|o| o.name().unwrap_or("<custom>"))
63 .collect();
64 println!(" ops (execution order, first 20): {}", ops.join(" "));
65 });
66}Sourcepub fn first_cop(&self, perl: &Perl) -> Option<Cop>
pub fn first_cop(&self, perl: &Perl) -> Option<Cop>
The first COP (nextstate) in the sub’s OP tree, in tree
order — i.e. the sub’s first statement, whose
line / file locate the sub body
in its source. None for XSUBs and bodiless subs.
Walks tree order (preorder), not the op_next chain, so loop
back-edges cannot cycle the search.
Examples found in repository?
19fn main() {
20 let mut perl = Perl::new();
21 perl.parse_env_args(env::args(), env::vars());
22
23 let sv0 = perl.get_sv("0", 0).expect("$0 is always set");
24 let main_file = String::from_utf8_lossy(sv0.pv(&perl)).into_owned();
25 println!("$0 = {main_file:?}");
26
27 let mut walker = StashWalker::new(&perl);
28 walker.walk("main", &mut |e| {
29 if e.cv.file().as_deref() != Some(main_file.as_str()) {
30 return;
31 }
32 let qual = e
33 .cv
34 .names(&perl)
35 .map(|(full, _)| full)
36 .unwrap_or_else(|| format!("{}::{}", e.package, e.name));
37 let line = e.cv.first_cop(&perl).map(|c| c.line());
38 println!("sub {qual} (first statement at line {line:?})");
39
40 let lexicals: Vec<String> = e
41 .cv
42 .pad_names()
43 .flatten() // skip unnamed slots
44 .filter_map(|pn| {
45 // Target/temporary slots have a non-null but empty PV;
46 // only real `my`/`our` names are interesting here.
47 let pv = pn.pv().filter(|s| !s.is_empty())?;
48 Some(match pn.type_stash_name() {
49 Some(t) => format!("{pv}: {t}"),
50 None => pv,
51 })
52 })
53 .collect();
54 println!(" lexicals: {lexicals:?}");
55
56 let ops: Vec<&str> = e
57 .cv
58 .start_op()
59 .into_iter()
60 .flat_map(|s| s.next_iter())
61 .take(20)
62 .map(|o| o.name().unwrap_or("<custom>"))
63 .collect();
64 println!(" ops (execution order, first 20): {}", ops.join(" "));
65 });
66}Sourcepub fn pad_names(&self) -> PadNames ⓘ
pub fn pad_names(&self) -> PadNames ⓘ
Iterate the sub’s lexical-name slots (pad names), in pad-offset
order starting at offset 0. Empty for XSUBs. See
PadNames.
Examples found in repository?
19fn main() {
20 let mut perl = Perl::new();
21 perl.parse_env_args(env::args(), env::vars());
22
23 let sv0 = perl.get_sv("0", 0).expect("$0 is always set");
24 let main_file = String::from_utf8_lossy(sv0.pv(&perl)).into_owned();
25 println!("$0 = {main_file:?}");
26
27 let mut walker = StashWalker::new(&perl);
28 walker.walk("main", &mut |e| {
29 if e.cv.file().as_deref() != Some(main_file.as_str()) {
30 return;
31 }
32 let qual = e
33 .cv
34 .names(&perl)
35 .map(|(full, _)| full)
36 .unwrap_or_else(|| format!("{}::{}", e.package, e.name));
37 let line = e.cv.first_cop(&perl).map(|c| c.line());
38 println!("sub {qual} (first statement at line {line:?})");
39
40 let lexicals: Vec<String> = e
41 .cv
42 .pad_names()
43 .flatten() // skip unnamed slots
44 .filter_map(|pn| {
45 // Target/temporary slots have a non-null but empty PV;
46 // only real `my`/`our` names are interesting here.
47 let pv = pn.pv().filter(|s| !s.is_empty())?;
48 Some(match pn.type_stash_name() {
49 Some(t) => format!("{pv}: {t}"),
50 None => pv,
51 })
52 })
53 .collect();
54 println!(" lexicals: {lexicals:?}");
55
56 let ops: Vec<&str> = e
57 .cv
58 .start_op()
59 .into_iter()
60 .flat_map(|s| s.next_iter())
61 .take(20)
62 .map(|o| o.name().unwrap_or("<custom>"))
63 .collect();
64 println!(" ops (execution order, first 20): {}", ops.join(" "));
65 });
66}