109_scan_subs_intro1/
109_scan_subs_intro1.rs

1#[cfg(perlapi_ver26)]
2use std::env;
3
4#[cfg(perlapi_ver26)]
5use libperl_rs::*;
6
7#[cfg(perlapi_ver26)]
8use libperl_sys::opcode;
9
10#[cfg(perlapi_ver26)]
11mod eg;
12#[cfg(perlapi_ver26)]
13use eg::{op1::*,sv0::*,cv0::*,stash_walker0::*};
14
15#[cfg(perlapi_ver26)]
16fn match_param_list(op: &Op) -> Vec<PadNameType> {
17    let mut res: Vec<PadNameType> = Vec::new();
18    if let Op::UNOP(opcode::OP_NULL, _,
19                    Op::OP(opcode::OP_PUSHMARK, _, _, ref args_op), _) = op {
20        let mut args_op = args_op;
21        while let Op::OP(_, _, Some(arg), rest) = args_op {
22            res.push(arg.clone());
23            if let Op::NULL = rest {
24                break
25            }
26            args_op = rest;
27        }
28    }
29    res
30}
31
32#[cfg(perlapi_ver26)]
33fn my_test() {
34    let mut perl = Perl::new();
35    perl.parse_env_args(env::args(), env::vars());
36    
37    let op_extractor = OpExtractor::new(&perl);
38
39    let main_file = sv_extract_pv(perl.get_sv("0", 0)).unwrap();
40    println!("$0 = {:?}", main_file);
41    
42    let filter = |cv| CvFILE(cv).map_or(false, |s| s == main_file);
43
44    let mut emitter = |name: &String, cv: *const libperl_sys::cv| {
45        println!("sub {:?}", name);
46        let ast = op_extractor.extract(cv, CvROOT(cv));
47        
48        match ast {
49            Op::UNOP(opcode::OP_LEAVESUB, _
50                     , Op::LISTOP(opcode::OP_LINESEQ, _
51                                  , Op::COP(opcode::OP_NEXTSTATE, body), _), _) => {
52                println!("preamble!");
53                match body {
54                    Op::BINOP(opcode::OP_AASSIGN, _
55                              , Op::UNOP(opcode::OP_NULL, _
56                                         , Op::OP(opcode::OP_PADRANGE, _, _
57                                                  , Op::UNOP(opcode::OP_RV2AV, _
58                                                             , Op::PADOP(opcode::OP_GV, _
59                                                                         , Sv::GLOB { name: ref nm, .. })
60                                                             , _))
61                                         , lvalue)
62                              , _) if nm == "_" => {
63                        println!("first array assignment from @_, lvalue = {:?}"
64                                 , match_param_list(lvalue));
65                        
66                    }
67                    _ => {
68                        println!("first statement is not an array assignment");
69                    }
70                }
71            }
72            _ => {
73                println!("doesn't match")
74            }
75        }
76
77        println!("");
78    };
79
80    let mut nswalker = StashWalker::new(&perl, Some(&filter), &mut emitter);
81
82    nswalker.walk("");
83}
84
85#[cfg(not(perlapi_ver26))]
86fn my_test() {
87    println!("Requires perl >= 5.26");
88}
89
90fn main() {
91    my_test();
92}