Skip to content

Commit f914b48

Browse files
committed
Add two asserts to the ast snippets to check attributes of ast nodes.
1 parent 6293117 commit f914b48

File tree

3 files changed

+105
-16
lines changed

3 files changed

+105
-16
lines changed

tests/snippets/ast_snippet.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,10 @@ def foo():
77
"""
88
n = ast.parse(source)
99
print(n)
10+
print(n.body)
11+
print(n.body[0].name)
12+
assert n.body[0].name == 'foo'
13+
print(n.body[0].body)
14+
print(n.body[0].body[0])
15+
print(n.body[0].body[0].value.func.id)
16+
assert n.body[0].body[0].value.func.id == 'print'

vm/src/pyobject.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@ impl PyContext {
213213
self.object.clone()
214214
}
215215

216+
pub fn new_object(&self) -> PyObjectRef {
217+
PyObject::new(
218+
PyObjectKind::Instance {
219+
dict: self.new_dict(),
220+
},
221+
self.object(),
222+
)
223+
}
224+
216225
pub fn new_int(&self, i: i32) -> PyObjectRef {
217226
PyObject::new(PyObjectKind::Integer { value: i }, self.int_type())
218227
}

vm/src/stdlib/ast.rs

Lines changed: 89 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88
extern crate rustpython_parser;
99

1010
use self::rustpython_parser::{ast, parser};
11-
use super::super::obj::{objdict, objfloat, objint, objlist, objstr, objtuple, objtype};
12-
use super::super::objbool;
11+
use super::super::obj::{objstr, objtype};
1312
use super::super::pyobject::{
14-
DictProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol,
13+
AttributeProtocol, DictProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
1514
};
1615
use super::super::VirtualMachine;
1716

@@ -20,31 +19,92 @@ fn program_to_ast(ctx: &PyContext, program: &ast::Program) -> PyObjectRef {
2019
for statement in &program.statements {
2120
body.push(statement_to_ast(ctx, statement));
2221
}
23-
// TODO: create Module node and set attributes:
24-
let ast_node = ctx.new_list(body);
22+
// TODO: create Module node:
23+
// let ast_node = ctx.new_instance(this.Module);
24+
let ast_node = ctx.new_object();
25+
let py_body = ctx.new_list(body);
26+
ast_node.set_attr("body", py_body);
2527
ast_node
2628
}
2729

2830
fn statement_to_ast(ctx: &PyContext, statement: &ast::LocatedStatement) -> PyObjectRef {
29-
match &statement.node {
30-
ast::Statement::FunctionDef { name, args, body } => {
31-
// TODO: create ast.FunctionDef object and set attributes
32-
// let node = ctx.new_object();
31+
let node = match &statement.node {
32+
ast::Statement::FunctionDef {
33+
name,
34+
args: _,
35+
body,
36+
} => {
37+
// TODO: create ast.FunctionDef object:
38+
let node = ctx.new_object();
39+
40+
// Set name:
41+
node.set_attr("name", ctx.new_str(name.to_string()));
42+
43+
// Set body:
3344
let mut py_body = vec![];
34-
py_body.push(ctx.new_str(format!("{:?}", name)));
35-
// node.set_attr("name", new_str(name));
3645
for statement in body {
3746
py_body.push(statement_to_ast(ctx, statement));
3847
}
3948

40-
ctx.new_list(py_body)
41-
},
42-
_ => {
43-
ctx.new_str(format!("{:?}", statement))
49+
node.set_attr("body", ctx.new_list(py_body));
50+
node
4451
}
45-
}
52+
ast::Statement::Expression { expression } => {
53+
let value = expression_to_ast(ctx, expression);
54+
// TODO: create proper class:
55+
let node = ctx.new_object();
56+
node.set_attr("value", value);
57+
node
58+
}
59+
x => {
60+
unimplemented!("{:?}", x);
61+
}
62+
};
63+
64+
// set lineno on node:
65+
let lineno = ctx.new_int(statement.location.get_row() as i32);
66+
node.set_attr("lineno", lineno);
67+
68+
node
69+
}
70+
71+
fn expression_to_ast(ctx: &PyContext, expression: &ast::Expression) -> PyObjectRef {
72+
let node = match &expression {
73+
ast::Expression::Call { function, args } => {
74+
// TODO: create ast.Call instance
75+
let node = ctx.new_object();
76+
77+
let py_func_ast = expression_to_ast(ctx, function);
78+
node.set_attr("func", py_func_ast);
79+
80+
let mut py_args = vec![];
81+
for arg in args {
82+
py_args.push(expression_to_ast(ctx, &arg.1));
83+
}
84+
let py_args = ctx.new_list(py_args);
85+
node.set_attr("args", py_args);
86+
87+
node
88+
}
89+
ast::Expression::Identifier { name } => {
90+
// TODO: create ast.Identifier instance
91+
let node = ctx.new_object();
92+
let py_name = ctx.new_str(name.clone());
93+
node.set_attr("id", py_name);
94+
node
95+
}
96+
ast::Expression::String { value } => {
97+
let node = ctx.new_object();
98+
node.set_attr("s", ctx.new_str(value.clone()));
99+
node
100+
}
101+
n => {
102+
unimplemented!("{:?}", n);
103+
}
104+
};
46105

47106
// TODO: set lineno on object
107+
node
48108
}
49109

50110
fn ast_parse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -66,5 +126,18 @@ fn ast_parse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
66126
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
67127
let ast_mod = ctx.new_module(&"ast".to_string(), ctx.new_scope(None));
68128
ast_mod.set_item("parse", ctx.new_rustfunc(ast_parse));
129+
ast_mod.set_item(
130+
"Module",
131+
ctx.new_class(&"_ast.Module".to_string(), ctx.object()),
132+
);
133+
// TODO: maybe we can use some clever macro to generate this?
134+
ast_mod.set_item(
135+
"FunctionDef",
136+
ctx.new_class(&"_ast.FunctionDef".to_string(), ctx.object()),
137+
);
138+
ast_mod.set_item(
139+
"Call",
140+
ctx.new_class(&"_ast.Call".to_string(), ctx.object()),
141+
);
69142
ast_mod
70143
}

0 commit comments

Comments
 (0)