Add load and store of global to name protocol.

This commit is contained in:
Windel Bouwman
2019-04-13 11:55:10 +02:00
parent 76c597f2af
commit 83ea419c63
2 changed files with 50 additions and 15 deletions

View File

@@ -129,6 +129,8 @@ pub trait NameProtocol {
fn store_name(&self, vm: &VirtualMachine, name: &str, value: PyObjectRef);
fn delete_name(&self, vm: &VirtualMachine, name: &str);
fn load_cell(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef>;
fn load_global(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef>;
fn store_global(&self, vm: &VirtualMachine, name: &str, value: PyObjectRef);
}
impl NameProtocol for Scope {
@@ -162,6 +164,14 @@ impl NameProtocol for Scope {
fn delete_name(&self, vm: &VirtualMachine, key: &str) {
self.get_locals().del_item(key, vm).unwrap();
}
fn load_global(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef> {
self.globals.get_item_option(name, vm).unwrap()
}
fn store_global(&self, vm: &VirtualMachine, name: &str, value: PyObjectRef) {
self.globals.set_item(name, value, vm).unwrap();
}
}
#[derive(Clone, Debug)]
@@ -994,12 +1004,12 @@ impl Frame {
&self,
vm: &VirtualMachine,
name: &str,
scope: &bytecode::NameScope,
name_scope: &bytecode::NameScope,
) -> FrameResult {
let obj = self.pop_value();
match scope {
match name_scope {
bytecode::NameScope::Global => {
self.scope.globals.set_item(name, obj, vm)?;
self.scope.store_global(vm, name, obj);
}
bytecode::NameScope::Local => {
self.scope.store_name(&vm, name, obj);
@@ -1017,19 +1027,21 @@ impl Frame {
&self,
vm: &VirtualMachine,
name: &str,
scope: &bytecode::NameScope,
name_scope: &bytecode::NameScope,
) -> FrameResult {
let value = match scope {
bytecode::NameScope::Global => self.scope.globals.get_item(name, vm)?,
bytecode::NameScope::Local => match self.scope.load_name(&vm, name) {
Some(value) => value,
None => {
let name_error_type = vm.ctx.exceptions.name_error.clone();
let msg = format!("name '{}' is not defined", name);
let name_error = vm.new_exception(name_error_type, msg);
return Err(name_error);
}
},
let optional_value = match name_scope {
bytecode::NameScope::Global => self.scope.load_global(vm, name),
bytecode::NameScope::Local => self.scope.load_name(&vm, name),
};
let value = match optional_value {
Some(value) => value,
None => {
let name_error_type = vm.ctx.exceptions.name_error.clone();
let msg = format!("name '{}' is not defined", name);
let name_error = vm.new_exception(name_error_type, msg);
return Err(name_error);
}
};
self.push_value(value);

View File

@@ -111,6 +111,17 @@ impl SymbolTableBuilder {
}
fn scan_parameter(&mut self, parameter: &ast::Parameter) -> SymbolTableResult {
self.register_name(&parameter.arg, SymbolRole::Assigned)
}
fn scan_parameters_annotations(&mut self, parameters: &[ast::Parameter]) -> SymbolTableResult {
for parameter in parameters {
self.scan_parameter_annotation(parameter)?;
}
Ok(())
}
fn scan_parameter_annotation(&mut self, parameter: &ast::Parameter) -> SymbolTableResult {
if let Some(annotation) = &parameter.annotation {
self.scan_expression(&annotation)?;
}
@@ -394,7 +405,19 @@ impl SymbolTableBuilder {
}
}
// Annotations are scanned in outer scope:
self.scan_parameters_annotations(&args.args)?;
self.scan_parameters_annotations(&args.kwonlyargs)?;
if let ast::Varargs::Named(name) = &args.vararg {
self.scan_parameter_annotation(name)?;
}
if let ast::Varargs::Named(name) = &args.kwarg {
self.scan_parameter_annotation(name)?;
}
self.enter_scope();
// Fill scope with parameter names:
self.scan_parameters(&args.args)?;
self.scan_parameters(&args.kwonlyargs)?;
if let ast::Varargs::Named(name) = &args.vararg {