Skip to content

Commit c69b43d

Browse files
committed
Add frozenset class, callable function and enumerate function.
1 parent ce5bb72 commit c69b43d

File tree

6 files changed

+103
-11
lines changed

6 files changed

+103
-11
lines changed

tests/snippets/builtins.py

+8
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,11 @@
55
x = sum(map(int, a))
66
assert x == 6
77

8+
assert callable(type)
9+
# TODO:
10+
# assert callable(callable)
11+
12+
assert list(enumerate(['a', 'b', 'c'])) == [(0, 'a'), (1, 'b'), (2, 'c')]
13+
14+
assert type(frozenset) is type
15+

vm/src/builtins.rs

+63-8
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,13 @@ fn builtin_bin(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
100100
}
101101

102102
// builtin_breakpoint
103-
// builtin_callable
103+
104+
fn builtin_callable(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
105+
arg_check!(vm, args, required = [(obj, None)]);
106+
// TODO: is this a sufficiently thorough check?
107+
let is_callable = obj.has_attr("__call__");
108+
Ok(vm.new_bool(is_callable))
109+
}
104110

105111
fn builtin_chr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
106112
arg_check!(vm, args, required = [(i, Some(vm.ctx.int_type()))]);
@@ -116,12 +122,35 @@ fn builtin_chr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
116122
}
117123

118124
fn builtin_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
119-
arg_check!(vm, args, required = [(source, None)]);
120-
// TODO:
121-
let mode = compile::Mode::Eval;
122-
let source = source.borrow().str();
125+
arg_check!(
126+
vm,
127+
args,
128+
required = [
129+
(source, None),
130+
(filename, Some(vm.ctx.str_type())),
131+
(mode, Some(vm.ctx.str_type()))
132+
]
133+
);
134+
let source = objstr::get_value(source);
135+
136+
let mode = {
137+
let mode = objstr::get_value(mode);
138+
if mode == String::from("exec") {
139+
compile::Mode::Exec
140+
} else if mode == "eval".to_string() {
141+
compile::Mode::Eval
142+
} else if mode == "single".to_string() {
143+
compile::Mode::Single
144+
} else {
145+
return Err(
146+
vm.new_value_error("compile() mode must be 'exec', 'eval' or single'".to_string())
147+
);
148+
}
149+
};
123150

124-
compile::compile(vm, &source, mode, None)
151+
let filename = objstr::get_value(filename);
152+
153+
compile::compile(vm, &source, mode, Some(filename))
125154
}
126155

127156
fn builtin_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -150,7 +179,28 @@ fn builtin_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
150179
}
151180
}
152181

153-
// builtin_enumerate
182+
fn builtin_enumerate(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
183+
arg_check!(
184+
vm,
185+
args,
186+
required = [(iterable, None)],
187+
optional = [(start, None)]
188+
);
189+
let items = vm.extract_elements(iterable)?;
190+
let start = if let Some(start) = start {
191+
objint::get_value(start)
192+
} else {
193+
Zero::zero()
194+
};
195+
let mut new_items = vec![];
196+
for (i, item) in items.into_iter().enumerate() {
197+
let element = vm
198+
.ctx
199+
.new_tuple(vec![vm.ctx.new_int(i.to_bigint().unwrap() + &start), item]);
200+
new_items.push(element);
201+
}
202+
Ok(vm.ctx.new_list(new_items))
203+
}
154204

155205
fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
156206
arg_check!(
@@ -219,7 +269,6 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
219269

220270
// builtin_filter
221271
// builtin_format
222-
// builtin_frozenset
223272

224273
fn builtin_getattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
225274
arg_check!(
@@ -550,6 +599,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
550599
dict.insert(String::from("bool"), ctx.bool_type());
551600
dict.insert(String::from("bytearray"), ctx.bytearray_type());
552601
dict.insert(String::from("bytes"), ctx.bytes_type());
602+
dict.insert(String::from("callable"), ctx.new_rustfunc(builtin_callable));
553603
dict.insert(String::from("chr"), ctx.new_rustfunc(builtin_chr));
554604
dict.insert(String::from("classmethod"), ctx.classmethod_type());
555605
dict.insert(String::from("compile"), ctx.new_rustfunc(builtin_compile));
@@ -558,9 +608,14 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
558608
dict.insert(String::from("dict"), ctx.dict_type());
559609
dict.insert(String::from("divmod"), ctx.new_rustfunc(builtin_divmod));
560610
dict.insert(String::from("dir"), ctx.new_rustfunc(builtin_dir));
611+
dict.insert(
612+
String::from("enumerate"),
613+
ctx.new_rustfunc(builtin_enumerate),
614+
);
561615
dict.insert(String::from("eval"), ctx.new_rustfunc(builtin_eval));
562616
dict.insert(String::from("exec"), ctx.new_rustfunc(builtin_exec));
563617
dict.insert(String::from("float"), ctx.float_type());
618+
dict.insert(String::from("frozenset"), ctx.frozenset_type());
564619
dict.insert(String::from("getattr"), ctx.new_rustfunc(builtin_getattr));
565620
dict.insert(String::from("hasattr"), ctx.new_rustfunc(builtin_hasattr));
566621
dict.insert(String::from("hash"), ctx.new_rustfunc(builtin_hash));

vm/src/frame.rs

-2
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,12 @@ enum Block {
3838
}
3939

4040
pub struct Frame {
41-
// TODO: We are using Option<i32> in stack for handline None return value
4241
pub code: bytecode::CodeObject,
4342
// We need 1 stack per frame
4443
stack: Vec<PyObjectRef>, // The main data frame of the stack machine
4544
blocks: Vec<Block>, // Block frames, for controling loops and exceptions
4645
pub locals: PyObjectRef, // Variables
4746
pub lasti: usize, // index of last instruction ran
48-
// cmp_op: Vec<&'a Fn(NativeType, NativeType) -> bool>, // TODO: change compare to a function list
4947
}
5048

5149
pub fn copy_code(code_obj: PyObjectRef) -> bytecode::CodeObject {

vm/src/obj/objset.rs

+23
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,34 @@ pub fn set_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
132132
Ok(vm.new_bool(false))
133133
}
134134

135+
fn frozenset_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
136+
arg_check!(vm, args, required = [(o, Some(vm.ctx.frozenset_type()))]);
137+
138+
let elements = get_elements(o);
139+
let s = if elements.len() == 0 {
140+
"frozenset()".to_string()
141+
} else {
142+
let mut str_parts = vec![];
143+
for elem in elements.values() {
144+
let part = vm.to_repr(elem)?;
145+
str_parts.push(objstr::get_value(&part));
146+
}
147+
148+
format!("frozenset({{{}}})", str_parts.join(", "))
149+
};
150+
Ok(vm.new_str(s))
151+
}
152+
135153
pub fn init(context: &PyContext) {
136154
let ref set_type = context.set_type;
137155
set_type.set_attr("__contains__", context.new_rustfunc(set_contains));
138156
set_type.set_attr("__len__", context.new_rustfunc(set_len));
139157
set_type.set_attr("__new__", context.new_rustfunc(set_new));
140158
set_type.set_attr("__repr__", context.new_rustfunc(set_repr));
141159
set_type.set_attr("add", context.new_rustfunc(set_add));
160+
161+
let ref frozenset_type = context.set_type;
162+
frozenset_type.set_attr("__contains__", context.new_rustfunc(set_contains));
163+
frozenset_type.set_attr("__len__", context.new_rustfunc(set_len));
164+
frozenset_type.set_attr("__repr__", context.new_rustfunc(frozenset_repr));
142165
}

vm/src/obj/objsuper.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ fn super_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
3131
ty.clone()
3232
} else {
3333
// TODO: implement complex logic here....
34-
vm.get_none()
34+
unimplemented!("TODO: get frame and determine instance and class?");
35+
// vm.get_none()
3536
};
3637

3738
// Check type argument:

vm/src/pyobject.rs

+7
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ pub struct PyContext {
8888
pub list_type: PyObjectRef,
8989
pub tuple_type: PyObjectRef,
9090
pub set_type: PyObjectRef,
91+
pub frozenset_type: PyObjectRef,
9192
pub iter_type: PyObjectRef,
9293
pub super_type: PyObjectRef,
9394
pub str_type: PyObjectRef,
@@ -158,6 +159,7 @@ impl PyContext {
158159
let str_type = create_type("str", &type_type, &object_type, &dict_type);
159160
let list_type = create_type("list", &type_type, &object_type, &dict_type);
160161
let set_type = create_type("set", &type_type, &object_type, &dict_type);
162+
let frozenset_type = create_type("frozenset", &type_type, &object_type, &dict_type);
161163
let int_type = create_type("int", &type_type, &object_type, &dict_type);
162164
let float_type = create_type("float", &type_type, &object_type, &dict_type);
163165
let complex_type = create_type("complex", &type_type, &object_type, &dict_type);
@@ -193,6 +195,7 @@ impl PyContext {
193195
bytearray_type: bytearray_type,
194196
list_type: list_type,
195197
set_type: set_type,
198+
frozenset_type: frozenset_type,
196199
bool_type: bool_type,
197200
true_value: true_value,
198201
false_value: false_value,
@@ -263,6 +266,10 @@ impl PyContext {
263266
self.set_type.clone()
264267
}
265268

269+
pub fn frozenset_type(&self) -> PyObjectRef {
270+
self.frozenset_type.clone()
271+
}
272+
266273
pub fn bool_type(&self) -> PyObjectRef {
267274
self.bool_type.clone()
268275
}

0 commit comments

Comments
 (0)