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