python_object/
lib.rs

1use std::cell::RefCell;
2
3use failure::Error;
4
5pub mod opcode;
6
7pub struct Program {
8    pub funcs: Vec<CodeObject>,
9}
10
11#[derive(Debug, Clone)]
12pub struct CodeObject {
13    pub argcount: u32,       /* #arguments, except *args */
14    pub kwonlyargcount: u32, /* #keyword only arguments */
15    pub nlocals: u32,        /* #local variables */
16    pub stacksize: u32,      /* #entries needed for evaluation stack */
17    pub flags: u32,
18    pub code: Vec<opcode::Opcode>,    /* instruction opcodes */
19    pub consts: RefCell<TupleObject>, /* list (constants used) */
20    pub names: Box<RefCell<Object>>,  /* list of strings (names used) */
21    pub name: Box<RefCell<Object>>,
22    pub varnames: Box<Object>,
23}
24impl CodeObject {
25    pub fn name(&self) -> Result<String, Error> {
26        match self.name.clone().into_inner() {
27            Object::Ref(_) => failure::bail!("ref should have been removed during decoding"),
28            o => o.as_string(),
29        }
30    }
31
32    pub fn names_tuple(&self) -> Result<TupleObject, Error> {
33        match self.names.clone().into_inner() {
34            Object::Ref(_) => failure::bail!("ref should have been removed during decoding"),
35            Object::Tuple(v) => Ok(v),
36            _ => panic!(),
37        }
38    }
39
40    pub fn varnames_tuple(&self) -> Result<TupleObject, Error> {
41        match *self.varnames.clone() {
42            Object::Ref(_) => failure::bail!("ref should have been removed during decoding"),
43            Object::Tuple(v) => Ok(v),
44            _ => panic!(),
45        }
46    }
47}
48
49#[derive(Debug, Clone)]
50pub struct TupleObject {
51    pub size: u8,
52    pub data: Vec<Object>,
53}
54impl TupleObject {
55    pub fn get(&self, i: u8) -> Object {
56        self.data[i as usize].clone()
57    }
58}
59
60#[derive(Debug, Clone)]
61pub enum Object {
62    None,
63    True,
64    False,
65    Code(CodeObject),
66    Ascii(String),
67    Int(i32),
68    Chars(Vec<u8>),
69    Tuple(TupleObject),
70    Ref(u32),
71}
72
73impl Object {
74    pub fn as_string(&self) -> Result<String, Error> {
75        match self {
76            Object::Ascii(u) => Ok(u.to_string()),
77            _ => failure::bail!("could not cast `{:?}` as string", self),
78        }
79    }
80
81    pub fn is_ref(&self) -> bool {
82        match self {
83            Object::Ref(_) => true,
84            _ => false,
85        }
86    }
87    pub fn is_code(&self) -> bool {
88        match self {
89            Object::Code(_) => true,
90            _ => false,
91        }
92    }
93}
94
95pub fn dump_object(object: Object) {
96    match object {
97        Object::Code(object) => {
98            println!("dump code object");
99
100            for opcode in object.code {
101                println!("op {:?} arg {:?}", opcode::to_string(opcode.op), opcode.arg);
102            }
103            println!("consts {:?}", object.consts);
104            println!("names {:?}", object.names);
105        }
106        _ => unimplemented!(),
107    }
108}