# HG changeset patch # User Bastien Orivel # Date 1465846363 -7200 # Node ID 2d906d1cb9408e03581ad4a225e487702ea7e39e # Parent dc82a0d8f144172d4878d95526a883afe0e5a1dd Add ast.Subscript. diff --git a/src/ast_convert.rs b/src/ast_convert.rs --- a/src/ast_convert.rs +++ b/src/ast_convert.rs @@ -1,4 +1,4 @@ -use python_ast::{Module, stmt, expr, expr_context, cmpop, boolop, operator, unaryop, arguments, arg, alias, comprehension, keyword, withitem, excepthandler}; +use python_ast::{Module, stmt, expr, expr_context, cmpop, boolop, operator, unaryop, arguments, arg, alias, comprehension, keyword, withitem, excepthandler, slice}; use cpython::{Python, PyObject}; use cpython::ObjectProtocol; //for call method @@ -267,6 +267,46 @@ fn parse_excepthandler(py: Python, ast: excepthandler{type_: type_, name: name, body: body} } +fn parse_slice(py: Python, ast: PyObject) -> slice { + let builtins_module = py.import("builtins").unwrap(); + let isinstance = builtins_module.get(py, "isinstance").unwrap(); + + let is_instance = |object: &PyObject, type_: &PyObject| { + return isinstance.call(py, (object, type_), None).unwrap().is_true(py).unwrap(); + }; + + let ast_module = py.import("ast").unwrap(); + let ast_type = ast_module.get(py, "AST").unwrap(); + let index_type = ast_module.get(py, "Index").unwrap(); + let slice_type = ast_module.get(py, "Slice").unwrap(); + let ext_slice_type = ast_module.get(py, "ExtSlice").unwrap(); + + assert!(is_instance(&ast, &ast_type)); + + if is_instance(&ast, &index_type) { + let value = ast.getattr(py, "value").unwrap(); + let value = parse_expr(py, value); + + slice::Index(value) + } else if is_instance(&ast, &slice_type) { + let lower = ast.getattr(py, "lower").unwrap(); + let upper = ast.getattr(py, "upper").unwrap(); + let step = ast.getattr(py, "step").unwrap(); + + let lower = parse_optional_expr(py, lower); + let upper = parse_optional_expr(py, upper); + let step = parse_optional_expr(py, step); + slice::Slice(lower, upper, step) + } else if is_instance(&ast, &ext_slice_type) { + let dims = ast.getattr(py, "dims").unwrap(); + let dims = parse_list(py, dims, parse_slice); + + slice::ExtSlice(dims) + } else { + unreachable!() + } +} + fn parse_optional_expr(py: Python, ast: PyObject) -> Option { if ast == py.None() { None @@ -310,6 +350,7 @@ fn parse_expr(py: Python, ast: PyObject) let lambda_type = ast_module.get(py, "Lambda").unwrap(); let ifexp_type = ast_module.get(py, "IfExp").unwrap(); let dict_type = ast_module.get(py, "Dict").unwrap(); + let subscript_type = ast_module.get(py, "Subscript").unwrap(); assert!(is_instance(&ast, &ast_type)); @@ -473,6 +514,15 @@ fn parse_expr(py: Python, ast: PyObject) let values = parse_list(py, values, parse_expr); expr::Dict(keys, values) + } else if is_instance(&ast, &subscript_type) { + let value = ast.getattr(py, "value").unwrap(); + let slice = ast.getattr(py, "slice").unwrap(); + let ctx = get_ctx(py, ast); + + let value = parse_expr(py, value); + let slice = parse_slice(py, slice); + + expr::Subscript(Box::new(value), Box::new(slice), ctx) } else { println!("expr {}", ast); unreachable!() diff --git a/src/ast_dump.rs b/src/ast_dump.rs --- a/src/ast_dump.rs +++ b/src/ast_dump.rs @@ -1,4 +1,4 @@ -use python_ast::{Module, stmt, expr, boolop, operator, unaryop, cmpop, arguments, arg, keyword, comprehension, withitem, excepthandler}; +use python_ast::{Module, stmt, expr, boolop, operator, unaryop, cmpop, arguments, arg, keyword, comprehension, withitem, excepthandler, slice}; use std::iter; @@ -117,6 +117,37 @@ impl to_string_able for comprehension { } } +impl to_string_able for slice { + fn to_string(&self) -> String { + match *self { + slice::Index(ref value) => value.to_string(), + slice::Slice(ref lower, ref upper, ref step) => { + format!("{}{}{}", + match *lower { + None => String::new(), + Some(ref lower) => lower.to_string() + }, + match *upper { + None => String::new(), + Some(ref upper) => format!(":{}", upper.to_string()) + }, + match *step { + None => String::new(), + Some(ref step) => format!(":{}", step.to_string()) + }, + ) + }, + slice::ExtSlice(ref dims) => { + let mut dims_ = vec!(); + for dim in dims { + dims_.push(dim.to_string()); + } + dims_.join(", ") + } + } + } +} + impl excepthandler { fn to_string(self, indent: usize) -> String { let current_indent = make_indent(indent); @@ -214,6 +245,7 @@ impl to_string_able for expr { } ) }, + expr::Subscript(value, slice, _) => format!("{}[{}]", value.to_string(), slice.to_string()), } } } diff --git a/src/python_ast.rs b/src/python_ast.rs --- a/src/python_ast.rs +++ b/src/python_ast.rs @@ -108,7 +108,7 @@ pub enum expr { // the following expression can appear in assignment context Attribute(Box, String, expr_context), - //Subscript(Box, slice, expr_context), + Subscript(Box, Box, expr_context), //Starred(Box, expr_context), Name(String, expr_context), List(Vec, expr_context), diff --git a/tests/test_parse_files/test_subscript.py b/tests/test_parse_files/test_subscript.py new file mode 100644 --- /dev/null +++ b/tests/test_parse_files/test_subscript.py @@ -0,0 +1,4 @@ +a[5] = b +a[1:2] = c +a[1:2:4] = d +a[1:2, 3] = e