Specify metaclass and create class with correct type.

This commit is contained in:
Adam Kelly
2018-10-30 22:18:52 +00:00
parent 89cfdbe3dd
commit c8e842eaab
3 changed files with 44 additions and 11 deletions

View File

@@ -644,14 +644,10 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
pub fn builtin_build_class_(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
let function = args.shift();
let name_arg = args.shift();
let name_arg_ref = name_arg.borrow();
let name = match name_arg_ref.kind {
PyObjectKind::String { ref value } => value,
_ => panic!("Class name must by a string!"),
};
let mut bases = args.args.clone();
let metaclass = args.get_kwarg("metaclass", vm.get_type());
bases.push(vm.context().object());
let metaclass = vm.get_type();
let namespace = vm.new_dict();
&vm.invoke(
function,
@@ -660,5 +656,8 @@ pub fn builtin_build_class_(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> Py
kwargs: vec![],
},
);
objtype::new(metaclass, name, bases, namespace)
let bases = vm.context().new_tuple(bases);
vm.call_method(&metaclass, "__new__", vec![name_arg, bases, namespace])
}

View File

@@ -436,7 +436,7 @@ impl Compiler {
name,
body,
bases,
keywords: _,
keywords,
decorator_list,
} => {
self.prepare_decorators(decorator_list)?;
@@ -483,9 +483,34 @@ impl Compiler {
for base in bases {
self.compile_expression(base)?;
}
self.emit(Instruction::CallFunction {
typ: CallType::Positional(2 + bases.len()),
});
if keywords.len() > 0 {
let mut kwarg_names = vec![];
for keyword in keywords {
if let Some(name) = &keyword.name {
kwarg_names.push(bytecode::Constant::String {
value: name.to_string(),
});
} else {
// This means **kwargs!
panic!("name must be set");
}
self.compile_expression(&keyword.value)?;
}
self.emit(Instruction::LoadConst {
value: bytecode::Constant::Tuple {
elements: kwarg_names,
},
});
self.emit(Instruction::CallFunction {
typ: CallType::Keyword(2 + keywords.len() + bases.len()),
});
} else {
self.emit(Instruction::CallFunction {
typ: CallType::Positional(2 + bases.len()),
});
}
self.apply_decorators(decorator_list);

View File

@@ -634,6 +634,15 @@ impl PyFuncArgs {
pub fn shift(&mut self) -> PyObjectRef {
self.args.remove(0)
}
pub fn get_kwarg(&self, key: &str, default: PyObjectRef) -> PyObjectRef {
for (arg_name, arg_value) in self.kwargs.iter() {
if arg_name == key {
return arg_value.clone();
}
}
default.clone()
}
}
type RustPyFunc = fn(vm: &mut VirtualMachine, PyFuncArgs) -> PyResult;