Merge pull request #47 from OddBloke/dict

Implement simple dict literals
This commit is contained in:
Windel Bouwman
2018-08-08 14:28:50 +02:00
committed by GitHub
5 changed files with 48 additions and 6 deletions

View File

@@ -124,6 +124,9 @@ pub enum Expression {
Tuple {
elements: Vec<Expression>,
},
Dict {
elements: Vec<(Expression, Expression)>,
},
Slice {
elements: Vec<Expression>,
},

View File

@@ -323,11 +323,24 @@ Atom: ast::Expression = {
}
}
},
"{" <e:TestDict?> "}" => 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)> = {
<e1:DictEntry> <e2:("," DictEntry)*> => {
let mut d = vec![e1];
d.extend(e2.into_iter().map(|x| x.1));
d
}
};
DictEntry: (ast::Expression, ast::Expression) = {
<e1: Test> ":" <e2: Test> => (e1, e2),
};
ExpressionList: Vec<ast::Expression> = {
<e: Comma<Expression>> => e,
};
@@ -385,6 +398,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,

View File

@@ -1 +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

View File

@@ -465,6 +465,14 @@ impl Compiler {
}
self.emit(Instruction::BuildTuple { size: size });
}
ast::Expression::Dict { elements } => {
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();
for element in elements {

View File

@@ -5,6 +5,7 @@
*/
use std::cell::RefMut;
use std::collections::hash_map::HashMap;
use std::ops::Deref;
use super::builtins;
@@ -562,15 +563,25 @@ 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);
}
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: elements }, self.get_type());
self.push_value(map_obj);
None
}
bytecode::Instruction::BuildSlice { size } => {
assert!(*size == 2 || *size == 3);