Skip to content

Commit 6e58fb3

Browse files
committed
Add second-pass objects and translation.
1 parent 3bae404 commit 6e58fb3

File tree

5 files changed

+176
-20
lines changed

5 files changed

+176
-20
lines changed

src/lib.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
11
mod marshal;
2-
mod processor;
2+
mod objects;
3+
//mod processor;
34

5+
use std::fmt;
6+
use std::io;
7+
8+
#[derive(Debug)]
9+
pub enum InterpreterError {
10+
Io(io::Error),
11+
Unmarshal(marshal::decode::UnmarshalError),
12+
}
13+
14+
impl fmt::Display for InterpreterError {
15+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16+
match *self {
17+
InterpreterError::Io(ref e) => write!(f, "I/O error:").and_then(|_| e.fmt(f)),
18+
InterpreterError::Unmarshal(ref e) => write!(f, "Unmarshal error:").and_then(|_| e.fmt(f)),
19+
}
20+
}
21+
}
22+
23+
pub fn run_module<R: io::Read>(reader: &mut R) -> Result<(), InterpreterError> {
24+
let mut buf = [0; 12];
25+
try!(reader.read_exact(&mut buf).map_err(InterpreterError::Io));
26+
// TODO: do something with the content of the buffer
27+
let mut store = objects::ObjectStore::new();
28+
let module = try!(marshal::read_object(reader, &mut store).map_err(InterpreterError::Unmarshal));
29+
//processor::run_code_object(module, &mut references);
30+
Ok(())
31+
}
32+
33+
#[test]
34+
fn test_hello_world() {
35+
let mut reader: &[u8] = b"\xee\x0c\r\n\x15j\nW\x15\x00\x00\x00\xe3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00@\x00\x00\x00s\x0e\x00\x00\x00e\x00\x00d\x00\x00\x83\x01\x00\x01d\x01\x00S)\x02z\x0bHello worldN)\x01\xda\x05print\xa9\x00r\x02\x00\x00\x00r\x02\x00\x00\x00\xfa\x0b/tmp/foo.py\xda\x08<module>\x01\x00\x00\x00s\x00\x00\x00\x00";
36+
run_module(&mut reader);
37+
}

src/marshal/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub struct Code {
1919
pub lnotab: Object,
2020
}
2121

22+
/// Temporary object used only during the unmarshalling pass
2223
#[derive(PartialEq)]
2324
#[derive(Debug)]
2425
pub enum Object {

src/marshal/unmarshal.rs renamed to src/marshal/decode.rs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,39 +73,40 @@ fn read_unicode_string<R: io::Read>(reader: &mut R, size: usize) -> Result<Strin
7373
}
7474

7575
/// Read an arbitrary number of contiguous marshal objects
76-
fn read_objects<R: io::Read>(reader: &mut R, references: &mut Vec<Object>, size: usize) -> Result<Vec<Object>, UnmarshalError> {
76+
fn read_tmp_objects<R: io::Read>(reader: &mut R, references: &mut Vec<Object>, size: usize) -> Result<Vec<Object>, UnmarshalError> {
7777
let mut vector = Vec::<Object>::new();
7878
vector.reserve(size);
7979
for _ in 0..size {
80-
let object = try!(read_object(reader, references));
80+
let object = try!(read_tmp_object(reader, references));
8181
vector.push(object);
8282
};
8383
Ok(vector)
8484
}
8585

86-
/// Read objects and build an other object containing them.
86+
/// Read temporary marshal objects and build an other object containing them.
8787
/// If the flag is true, add this object to the vector of objects before reading its content
8888
/// (required, as the order of objects matter for references).
8989
macro_rules! build_container {
9090
( $reader:expr, $references:ident, $container:expr, $size:expr, $flag:expr) => {{
9191
if $flag {
9292
let index = $references.len() as u32; // TODO: overflow check
9393
$references.push(Object::Hole);
94-
let objects = try!(read_objects($reader, $references, $size));
94+
let objects = try!(read_tmp_objects($reader, $references, $size));
9595
$references[index as usize] = $container(objects); // TODO: overflow check
9696
(false, Object::Ref(index))
9797
}
9898
else {
99-
let objects = try!(read_objects($reader, $references, $size));
99+
let objects = try!(read_tmp_objects($reader, $references, $size));
100100
(false, $container(objects))
101101
}
102102
}}
103103
}
104104

105-
/// Read an object, whose type is known from the first byte. If it is a container, read its content too.
105+
/// Read an tmporary marshal object, whose type is known from the first byte.
106+
/// If it is a container, read its content too.
106107
/// If the first bit is 1 and the marshal protocol allows the type to be referenced,
107108
/// add it to the list of references too.
108-
pub fn read_object<R: io::Read>(reader: &mut R, references: &mut Vec<Object>) -> Result<Object, UnmarshalError> {
109+
pub fn read_tmp_object<R: io::Read>(reader: &mut R, references: &mut Vec<Object>) -> Result<Object, UnmarshalError> {
109110
let byte = read_byte!(reader);
110111
let flag = byte & 0b10000000 != 0;
111112
let opcode = byte & 0b01111111;
@@ -164,16 +165,16 @@ pub fn read_object<R: io::Read>(reader: &mut R, references: &mut Vec<Object>) ->
164165
nlocals: try!(read_long(reader)),
165166
stacksize: try!(read_long(reader)),
166167
flags: try!(read_long(reader)),
167-
code: try!(read_object(reader, references)),
168-
consts: try!(read_object(reader, references)),
169-
names: try!(read_object(reader, references)),
170-
varnames: try!(read_object(reader, references)),
171-
freevars: try!(read_object(reader, references)),
172-
cellvars: try!(read_object(reader, references)),
173-
filename: try!(read_object(reader, references)),
174-
name: try!(read_object(reader, references)),
168+
code: try!(read_tmp_object(reader, references)),
169+
consts: try!(read_tmp_object(reader, references)),
170+
names: try!(read_tmp_object(reader, references)),
171+
varnames: try!(read_tmp_object(reader, references)),
172+
freevars: try!(read_tmp_object(reader, references)),
173+
cellvars: try!(read_tmp_object(reader, references)),
174+
filename: try!(read_tmp_object(reader, references)),
175+
name: try!(read_tmp_object(reader, references)),
175176
firstlineno: try!(read_long(reader)),
176-
lnotab: try!(read_object(reader, references)), // TODO: decode this
177+
lnotab: try!(read_tmp_object(reader, references)), // TODO: decode this
177178
};
178179

179180
let object = Object::Code(Box::new(code));
@@ -195,13 +196,13 @@ macro_rules! assert_unmarshal {
195196
( $expected_obj:expr, $bytecode:expr) => {{
196197
let mut reader: &[u8] = $bytecode;
197198
let mut refs = Vec::new();
198-
let obj = read_object(&mut reader, &mut refs).unwrap();
199+
let obj = read_tmp_object(&mut reader, &mut refs).unwrap();
199200
assert_eq!($expected_obj, obj);
200201
}};
201202
( $expected_obj:expr, $expected_refs:expr, $bytecode:expr) => {{
202203
let mut reader: &[u8] = $bytecode;
203204
let mut refs = Vec::new();
204-
let obj = read_object(&mut reader, &mut refs).unwrap();
205+
let obj = read_tmp_object(&mut reader, &mut refs).unwrap();
205206
assert_eq!($expected_obj, obj);
206207
assert_eq!($expected_refs, refs);
207208
}};

src/marshal/mod.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,60 @@
11
pub mod common;
2-
pub mod unmarshal;
2+
pub mod decode;
3+
4+
use std::io;
5+
use std::collections::HashSet;
6+
use super::objects::{Code, ObjectContent, Object, ObjectRef, ObjectStore};
7+
use self::common::Object as MarshalObject;
8+
9+
macro_rules! translate_vector {
10+
( $e:expr, $map:ident, $store:ident ) => { $e.into_iter().map(|o| translate_object(o, $map, $store)).collect() }
11+
}
12+
13+
fn translate_object(marshal_object: MarshalObject, translation_map: &Vec<ObjectRef>, store: &mut ObjectStore) -> ObjectRef {
14+
match marshal_object {
15+
MarshalObject::Hole => panic!("Remaining hole."),
16+
MarshalObject::None => store.allocate(ObjectContent::None),
17+
MarshalObject::False => store.allocate(ObjectContent::False),
18+
MarshalObject::True => store.allocate(ObjectContent::True),
19+
MarshalObject::Int(i) => store.allocate(ObjectContent::Int(i)),
20+
MarshalObject::String(s) => store.allocate(ObjectContent::String(s)),
21+
MarshalObject::Bytes(v) => store.allocate(ObjectContent::Bytes(v)),
22+
MarshalObject::Tuple(v) => {
23+
let v = translate_vector!(v, translation_map, store);
24+
store.allocate(ObjectContent::Tuple(v))
25+
},
26+
MarshalObject::List(v) => {
27+
let v = translate_vector!(v, translation_map, store);
28+
store.allocate(ObjectContent::List(v))
29+
},
30+
MarshalObject::Set(v) => {
31+
let v = translate_vector!(v, translation_map, store);
32+
store.allocate(ObjectContent::Set(v))
33+
},
34+
MarshalObject::FrozenSet(v) => {
35+
let v = translate_vector!(v, translation_map, store);
36+
store.allocate(ObjectContent::FrozenSet(v))
37+
},
38+
MarshalObject::Code(c) => {
39+
let code = translate_object(c.code, translation_map, store);
40+
store.allocate(ObjectContent::Code(Code { code: code})) // TODO: more fields
41+
},
42+
MarshalObject::Ref(i) => translation_map.get(i as usize).unwrap().clone(), // TODO: overflow check
43+
}
44+
}
45+
46+
fn translate_objects(marshal_object: MarshalObject, references: Vec<MarshalObject>, store: &mut ObjectStore) -> ObjectRef {
47+
let mut translation_map = Vec::new();
48+
translation_map.reserve(references.len());
49+
for obj in references {
50+
let obj = translate_object(obj, &translation_map, store);
51+
translation_map.push(obj);
52+
}
53+
translate_object(marshal_object, &translation_map, store)
54+
}
55+
56+
pub fn read_object<R: io::Read>(reader: &mut R, store: &mut ObjectStore) -> Result<ObjectRef, decode::UnmarshalError> {
57+
let mut references = Vec::new();
58+
let marshal_object = try!(decode::read_tmp_object(reader, &mut references));
59+
Ok(translate_objects(marshal_object, references, store))
60+
}

src/objects/mod.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
2+
#[derive(Debug)]
3+
pub struct Code {/*
4+
pub argcount: u32,
5+
pub kwonlyargcount: u32,
6+
pub nlocals: u32,
7+
pub stacksize: u32,
8+
pub flags: u32,*/
9+
pub code: ObjectRef,/*
10+
pub consts: Object,
11+
pub names: Object,
12+
pub varnames: Object,
13+
pub freevars: Object,
14+
pub cellvars: Object,
15+
pub filename: Object,
16+
pub name: Object,
17+
pub firstlineno: u32,
18+
pub lnotab: Object,*/
19+
}
20+
21+
#[derive(Debug)]
22+
pub enum ObjectContent {
23+
None,
24+
True,
25+
False,
26+
Int(u32),
27+
String(::std::string::String),
28+
Tuple(Vec<ObjectRef>),
29+
List(Vec<ObjectRef>),
30+
Code(Code),
31+
Set(Vec<ObjectRef>),
32+
FrozenSet(Vec<ObjectRef>),
33+
Bytes(Vec<u8>),
34+
}
35+
36+
#[derive(Debug)]
37+
pub struct Object {
38+
content: ObjectContent,
39+
}
40+
41+
#[derive(Debug)]
42+
#[derive(Clone)]
43+
pub struct ObjectRef {
44+
index: usize,
45+
}
46+
47+
#[derive(Debug)]
48+
pub struct ObjectStore {
49+
all_objects: Vec<Object>,
50+
}
51+
52+
impl ObjectStore {
53+
pub fn new() -> ObjectStore {
54+
ObjectStore { all_objects: Vec::new() }
55+
}
56+
57+
pub fn allocate(&mut self, obj: ObjectContent) -> ObjectRef {
58+
let obj_ref = ObjectRef { index: self.all_objects.len() };
59+
self.all_objects.push(Object { content: obj });
60+
obj_ref
61+
}
62+
}

0 commit comments

Comments
 (0)