Skip to content

Commit c8e842e

Browse files
committed
Specify metaclass and create class with correct type.
1 parent 89cfdbe commit c8e842e

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

vm/src/builtins.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -644,14 +644,10 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
644644
pub fn builtin_build_class_(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
645645
let function = args.shift();
646646
let name_arg = args.shift();
647-
let name_arg_ref = name_arg.borrow();
648-
let name = match name_arg_ref.kind {
649-
PyObjectKind::String { ref value } => value,
650-
_ => panic!("Class name must by a string!"),
651-
};
652647
let mut bases = args.args.clone();
648+
let metaclass = args.get_kwarg("metaclass", vm.get_type());
649+
653650
bases.push(vm.context().object());
654-
let metaclass = vm.get_type();
655651
let namespace = vm.new_dict();
656652
&vm.invoke(
657653
function,
@@ -660,5 +656,8 @@ pub fn builtin_build_class_(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> Py
660656
kwargs: vec![],
661657
},
662658
);
663-
objtype::new(metaclass, name, bases, namespace)
659+
660+
let bases = vm.context().new_tuple(bases);
661+
662+
vm.call_method(&metaclass, "__new__", vec![name_arg, bases, namespace])
664663
}

vm/src/compile.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ impl Compiler {
436436
name,
437437
body,
438438
bases,
439-
keywords: _,
439+
keywords,
440440
decorator_list,
441441
} => {
442442
self.prepare_decorators(decorator_list)?;
@@ -483,9 +483,34 @@ impl Compiler {
483483
for base in bases {
484484
self.compile_expression(base)?;
485485
}
486-
self.emit(Instruction::CallFunction {
487-
typ: CallType::Positional(2 + bases.len()),
488-
});
486+
487+
if keywords.len() > 0 {
488+
let mut kwarg_names = vec![];
489+
for keyword in keywords {
490+
if let Some(name) = &keyword.name {
491+
kwarg_names.push(bytecode::Constant::String {
492+
value: name.to_string(),
493+
});
494+
} else {
495+
// This means **kwargs!
496+
panic!("name must be set");
497+
}
498+
self.compile_expression(&keyword.value)?;
499+
}
500+
501+
self.emit(Instruction::LoadConst {
502+
value: bytecode::Constant::Tuple {
503+
elements: kwarg_names,
504+
},
505+
});
506+
self.emit(Instruction::CallFunction {
507+
typ: CallType::Keyword(2 + keywords.len() + bases.len()),
508+
});
509+
} else {
510+
self.emit(Instruction::CallFunction {
511+
typ: CallType::Positional(2 + bases.len()),
512+
});
513+
}
489514

490515
self.apply_decorators(decorator_list);
491516

vm/src/pyobject.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,15 @@ impl PyFuncArgs {
634634
pub fn shift(&mut self) -> PyObjectRef {
635635
self.args.remove(0)
636636
}
637+
638+
pub fn get_kwarg(&self, key: &str, default: PyObjectRef) -> PyObjectRef {
639+
for (arg_name, arg_value) in self.kwargs.iter() {
640+
if arg_name == key {
641+
return arg_value.clone();
642+
}
643+
}
644+
default.clone()
645+
}
637646
}
638647

639648
type RustPyFunc = fn(vm: &mut VirtualMachine, PyFuncArgs) -> PyResult;

0 commit comments

Comments
 (0)