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, pub kwonlyargcount: u32, pub nlocals: u32, pub stacksize: u32, pub flags: u32,
18 pub code: Vec<opcode::Opcode>, pub consts: RefCell<TupleObject>, pub names: Box<RefCell<Object>>, 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}