From 1b259d5d611bc6877edc166715a5ebc0a819f2ae Mon Sep 17 00:00:00 2001 From: Daniel Watkins Date: Tue, 7 Aug 2018 23:21:50 -0400 Subject: [PATCH 1/2] Implement 0-size dict literal --- parser/src/ast.rs | 3 +++ parser/src/python.lalrpop | 3 +++ tests/snippets/builtin_dict.py | 1 + vm/src/compile.rs | 3 +++ vm/src/vm.rs | 12 +++++++++--- 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index ee85faa90..b4757271e 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -124,6 +124,9 @@ pub enum Expression { Tuple { elements: Vec, }, + Dict { + elements: Vec<(Expression, Expression)>, + }, Slice { elements: Vec, }, diff --git a/parser/src/python.lalrpop b/parser/src/python.lalrpop index 3105f77f2..725549017 100644 --- a/parser/src/python.lalrpop +++ b/parser/src/python.lalrpop @@ -323,6 +323,7 @@ Atom: ast::Expression = { } } }, + "{" "}" => ast::Expression::Dict { elements: Vec::new() }, "True" => ast::Expression::True, "False" => ast::Expression::False, "None" => ast::Expression::None, @@ -385,6 +386,8 @@ extern { ")" => lexer::Tok::Rpar, "[" => lexer::Tok::Lsqb, "]" => lexer::Tok::Rsqb, + "{" => lexer::Tok::Lbrace, + "}" => lexer::Tok::Rbrace, "=" => lexer::Tok::Equal, "+=" => lexer::Tok::PlusEqual, "-=" => lexer::Tok::MinusEqual, diff --git a/tests/snippets/builtin_dict.py b/tests/snippets/builtin_dict.py index 8fe70d51a..a69c10307 100644 --- a/tests/snippets/builtin_dict.py +++ b/tests/snippets/builtin_dict.py @@ -1 +1,2 @@ assert len(dict()) == 0 +assert len({}) == 0 diff --git a/vm/src/compile.rs b/vm/src/compile.rs index b4af32964..3bfa5822d 100644 --- a/vm/src/compile.rs +++ b/vm/src/compile.rs @@ -465,6 +465,9 @@ impl Compiler { } self.emit(Instruction::BuildTuple { size: size }); } + ast::Expression::Dict { elements } => { + self.emit(Instruction::BuildMap { size: 0 }); + } ast::Expression::Slice { elements } => { let size = elements.len(); for element in elements { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 3b11cbdd9..23384b096 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -5,6 +5,7 @@ */ use std::cell::RefMut; +use std::collections::hash_map::HashMap; use std::ops::Deref; use super::builtins; @@ -568,9 +569,14 @@ impl VirtualMachine { let obj = self.pop_value(); elements.push((key, obj)); } - panic!("To be implemented!") - //let list_obj = PyObject::Tuple { elements: elements }.into_ref(); - //frame.stack.push(list_obj); + let map_obj = PyObject::new( + PyObjectKind::Dict { + elements: HashMap::new(), + }, + self.get_type(), + ); + self.push_value(map_obj); + None } bytecode::Instruction::BuildSlice { size } => { assert!(*size == 2 || *size == 3); From d1acf5e7dbf62ffdbb34be5c018d1707de550db6 Mon Sep 17 00:00:00 2001 From: Daniel Watkins Date: Tue, 7 Aug 2018 23:47:19 -0400 Subject: [PATCH 2/2] Implement simple dict literals --- parser/src/python.lalrpop | 14 +++++++++++++- tests/snippets/builtin_dict.py | 4 ++++ vm/src/compile.rs | 7 ++++++- vm/src/vm.rs | 23 ++++++++++++++--------- 4 files changed, 37 insertions(+), 11 deletions(-) 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 }