diff --git a/parser/src/python.lalrpop b/parser/src/python.lalrpop index 725549017..fd4d7bdc5 100644 --- a/parser/src/python.lalrpop +++ b/parser/src/python.lalrpop @@ -323,12 +323,24 @@ Atom: ast::Expression = { } } }, - "{" "}" => ast::Expression::Dict { elements: Vec::new() }, + "{" "}" => ast::Expression::Dict { elements: e.unwrap_or(Vec::new()) }, "True" => ast::Expression::True, "False" => ast::Expression::False, "None" => ast::Expression::None, }; +TestDict: Vec<(ast::Expression, ast::Expression)> = { + => { + let mut d = vec![e1]; + d.extend(e2.into_iter().map(|x| x.1)); + d + } +}; + +DictEntry: (ast::Expression, ast::Expression) = { + ":" => (e1, e2), +}; + ExpressionList: Vec = { > => e, }; diff --git a/tests/snippets/builtin_dict.py b/tests/snippets/builtin_dict.py index a69c10307..d401aabca 100644 --- a/tests/snippets/builtin_dict.py +++ b/tests/snippets/builtin_dict.py @@ -1,2 +1,6 @@ assert len(dict()) == 0 + assert len({}) == 0 +assert len({"a": "b"}) == 1 +assert len({"a": "b", "b": 1}) == 2 +assert len({"a": "b", "b": 1, "a" + "b": 2*2}) == 3 diff --git a/vm/src/compile.rs b/vm/src/compile.rs index 3bfa5822d..9162f9fab 100644 --- a/vm/src/compile.rs +++ b/vm/src/compile.rs @@ -466,7 +466,12 @@ impl Compiler { self.emit(Instruction::BuildTuple { size: size }); } ast::Expression::Dict { elements } => { - self.emit(Instruction::BuildMap { size: 0 }); + let size = elements.len(); + for (key, value) in elements { + self.compile_expression(key); + self.compile_expression(value); + } + self.emit(Instruction::BuildMap { size: size }); } ast::Expression::Slice { elements } => { let size = elements.len(); diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 23384b096..98dd1dffa 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -563,18 +563,23 @@ impl VirtualMachine { None } bytecode::Instruction::BuildMap { size } => { - let mut elements = Vec::new(); + let mut elements = HashMap::new(); for _x in 0..*size { - let key = self.pop_value(); let obj = self.pop_value(); - elements.push((key, obj)); + // XXX: Currently, we only support String keys, so we have to unwrap the + // PyObject (and ensure it is a String). + let key_pyobj = self.pop_value(); + let key = match key_pyobj.borrow().kind { + PyObjectKind::String { ref value } => value.clone(), + ref kind => unimplemented!( + "Only strings can be used as dict keys, we saw: {:?}", + kind + ), + }; + elements.insert(key, obj); } - let map_obj = PyObject::new( - PyObjectKind::Dict { - elements: HashMap::new(), - }, - self.get_type(), - ); + let map_obj = + PyObject::new(PyObjectKind::Dict { elements: elements }, self.get_type()); self.push_value(map_obj); None }