| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent edf6471 commit eb3771e
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -59,10 +59,19 @@ bitflags! { | |||
| 59 | 59 | pub type Label = usize; | |
| 60 | 60 | ||
| 61 | 61 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | |
| 62 | + /// An indication where the name must be accessed. | ||
| 62 | 63 | pub enum NameScope { | |
| 64 | + /// The name will be in the local scope. | ||
| 63 | 65 | Local, | |
| 66 | + | ||
| 67 | + /// The name will be located in scope surrounding the current scope. | ||
| 64 | 68 | NonLocal, | |
| 69 | + | ||
| 70 | + /// The name will be in global scope. | ||
| 65 | 71 | Global, | |
| 72 | + | ||
| 73 | + /// The name will be located in any scope between the current scope and the top scope. | ||
| 74 | + Free, | ||
| 66 | 75 | } | |
| 67 | 76 | ||
| 68 | 77 | /// Transforms a value prior to formatting it. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -282,8 +282,8 @@ impl<O: OutputStream> Compiler<O> { | |||
| 282 | 282 | match symbol.scope { | |
| 283 | 283 | SymbolScope::Global => bytecode::NameScope::Global, | |
| 284 | 284 | SymbolScope::Nonlocal => bytecode::NameScope::NonLocal, | |
| 285 | - SymbolScope::Unknown => bytecode::NameScope::Local, | ||
| 286 | - SymbolScope::Local => bytecode::NameScope::Local, | ||
| 285 | + SymbolScope::Unknown => bytecode::NameScope::Free, | ||
| 286 | + SymbolScope::Local => bytecode::NameScope::Free, | ||
| 287 | 287 | } | |
| 288 | 288 | } | |
| 289 | 289 | ||
@@ -500,7 +500,7 @@ impl<O: OutputStream> Compiler<O> { | |||
| 500 | 500 | self.compile_jump_if(test, true, end_label)?; | |
| 501 | 501 | self.emit(Instruction::LoadName { | |
| 502 | 502 | name: String::from("AssertionError"), | |
| 503 | - scope: bytecode::NameScope::Local, | ||
| 503 | + scope: bytecode::NameScope::Global, | ||
| 504 | 504 | }); | |
| 505 | 505 | match msg { | |
| 506 | 506 | Some(e) => { | |
@@ -736,7 +736,7 @@ impl<O: OutputStream> Compiler<O> { | |||
| 736 | 736 | // Check exception type: | |
| 737 | 737 | self.emit(Instruction::LoadName { | |
| 738 | 738 | name: String::from("isinstance"), | |
| 739 | - scope: bytecode::NameScope::Local, | ||
| 739 | + scope: bytecode::NameScope::Global, | ||
| 740 | 740 | }); | |
| 741 | 741 | self.emit(Instruction::Rotate { amount: 2 }); | |
| 742 | 742 | self.compile_expression(exc_type)?; | |
@@ -931,11 +931,11 @@ impl<O: OutputStream> Compiler<O> { | |||
| 931 | 931 | ||
| 932 | 932 | self.emit(Instruction::LoadName { | |
| 933 | 933 | name: "__name__".to_string(), | |
| 934 | - scope: bytecode::NameScope::Local, | ||
| 934 | + scope: bytecode::NameScope::Free, | ||
| 935 | 935 | }); | |
| 936 | 936 | self.emit(Instruction::StoreName { | |
| 937 | 937 | name: "__module__".to_string(), | |
| 938 | - scope: bytecode::NameScope::Local, | ||
| 938 | + scope: bytecode::NameScope::Free, | ||
| 939 | 939 | }); | |
| 940 | 940 | self.compile_statements(new_body)?; | |
| 941 | 941 | self.emit(Instruction::LoadConst { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -213,21 +213,21 @@ impl SymbolTableAnalyzer { | |||
| 213 | 213 | if symbol.is_assigned || symbol.is_parameter { | |
| 214 | 214 | symbol.scope = SymbolScope::Local; | |
| 215 | 215 | } else { | |
| 216 | - // TODO: comment this out and make it work properly: | ||
| 217 | - /* | ||
| 218 | - */ | ||
| 219 | - let found_in_outer_scope = self | ||
| 220 | - .tables | ||
| 221 | - .iter() | ||
| 222 | - .skip(1) | ||
| 223 | - .any(|t| t.symbols.contains_key(&symbol.name)); | ||
| 216 | + // Interesting stuff about the __class__ variable: | ||
| 217 | + // https://docs.python.org/3/reference/datamodel.html?highlight=__class__#creating-the-class-object | ||
| 218 | + let found_in_outer_scope = (symbol.name == "__class__") | ||
| 219 | + || self | ||
| 220 | + .tables | ||
| 221 | + .iter() | ||
| 222 | + .skip(1) | ||
| 223 | + .any(|t| t.symbols.contains_key(&symbol.name)); | ||
| 224 | 224 | ||
| 225 | 225 | if found_in_outer_scope { | |
| 226 | 226 | // Symbol is in some outer scope. | |
| 227 | 227 | symbol.is_free = true; | |
| 228 | 228 | } else { | |
| 229 | 229 | // Well, it must be a global then :) | |
| 230 | - // symbol.scope = SymbolScope::Global; | ||
| 230 | + symbol.scope = SymbolScope::Global; | ||
| 231 | 231 | } | |
| 232 | 232 | } | |
| 233 | 233 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -73,4 +73,4 @@ def print_table(table, indent=0): | |||
| 73 | 73 | print('======== dis.dis ========') | |
| 74 | 74 | print() | |
| 75 | 75 | co = compile(source, filename, 'exec') | |
| 76 | - print(dis.dis(co)) | ||
| 76 | + dis.dis(co) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -907,6 +907,9 @@ impl Frame { | |||
| 907 | 907 | bytecode::NameScope::Local => { | |
| 908 | 908 | self.scope.store_name(vm, name, obj); | |
| 909 | 909 | } | |
| 910 | + bytecode::NameScope::Free => { | ||
| 911 | + self.scope.store_name(vm, name, obj); | ||
| 912 | + } | ||
| 910 | 913 | } | |
| 911 | 914 | Ok(None) | |
| 912 | 915 | } | |
@@ -928,7 +931,8 @@ impl Frame { | |||
| 928 | 931 | let optional_value = match name_scope { | |
| 929 | 932 | bytecode::NameScope::Global => self.scope.load_global(vm, name), | |
| 930 | 933 | bytecode::NameScope::NonLocal => self.scope.load_cell(vm, name), | |
| 931 | - bytecode::NameScope::Local => self.scope.load_name(&vm, name), | ||
| 934 | + bytecode::NameScope::Local => self.scope.load_local(&vm, name), | ||
| 935 | + bytecode::NameScope::Free => self.scope.load_name(&vm, name), | ||
| 932 | 936 | }; | |
| 933 | 937 | ||
| 934 | 938 | let value = match optional_value { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -312,6 +312,8 @@ fn type_dict_setter(_instance: PyClassRef, _value: PyObjectRef, vm: &VirtualMach | |||
| 312 | 312 | ||
| 313 | 313 | /// This is the internal get_attr implementation for fast lookup on a class. | |
| 314 | 314 | pub fn class_get_attr(class: &PyClassRef, attr_name: &str) -> Option<PyObjectRef> { | |
| 315 | + flame_guard!(format!("class_get_attr({:?})", attr_name)); | ||
| 316 | + | ||
| 315 | 317 | if let Some(item) = class.attributes.borrow().get(attr_name).cloned() { | |
| 316 | 318 | return Some(item); | |
| 317 | 319 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -123,6 +123,7 @@ pub trait NameProtocol { | |||
| 123 | 123 | fn load_name(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef>; | |
| 124 | 124 | fn store_name(&self, vm: &VirtualMachine, name: &str, value: PyObjectRef); | |
| 125 | 125 | fn delete_name(&self, vm: &VirtualMachine, name: &str) -> PyResult; | |
| 126 | + fn load_local(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef>; | ||
| 126 | 127 | fn load_cell(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef>; | |
| 127 | 128 | fn store_cell(&self, vm: &VirtualMachine, name: &str, value: PyObjectRef); | |
| 128 | 129 | fn load_global(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef>; | |
@@ -142,6 +143,12 @@ impl NameProtocol for Scope { | |||
| 142 | 143 | self.load_global(vm, name) | |
| 143 | 144 | } | |
| 144 | 145 | ||
| 146 | + #[cfg_attr(feature = "flame-it", flame("Scope"))] | ||
| 147 | + /// Load a local name. Only check the local dictionary for the given name. | ||
| 148 | + fn load_local(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef> { | ||
| 149 | + self.get_locals().get_item_option(name, vm).unwrap() | ||
| 150 | + } | ||
| 151 | + | ||
| 145 | 152 | #[cfg_attr(feature = "flame-it", flame("Scope"))] | |
| 146 | 153 | fn load_cell(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef> { | |
| 147 | 154 | for dict in self.locals.iter().skip(1) { | |
@@ -170,7 +177,17 @@ impl NameProtocol for Scope { | |||
| 170 | 177 | } | |
| 171 | 178 | ||
| 172 | 179 | #[cfg_attr(feature = "flame-it", flame("Scope"))] | |
| 180 | + /// Load a global name. | ||
| 173 | 181 | fn load_global(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef> { | |
| 182 | + // First, take a look in the outmost local scope (the scope at top level) | ||
| 183 | + let last_local_dict = self.locals.iter().last(); | ||
| 184 | + if let Some(local_dict) = last_local_dict { | ||
| 185 | + if let Some(value) = local_dict.get_item_option(name, vm).unwrap() { | ||
| 186 | + return Some(value); | ||
| 187 | + } | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + // Now, take a look at the globals or builtins. | ||
| 174 | 191 | if let Some(value) = self.globals.get_item_option(name, vm).unwrap() { | |
| 175 | 192 | Some(value) | |
| 176 | 193 | } else { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -527,6 +527,8 @@ impl VirtualMachine { | |||
| 527 | 527 | where | |
| 528 | 528 | T: Into<PyFuncArgs>, | |
| 529 | 529 | { | |
| 530 | + flame_guard!(format!("call_method({:?})", method_name)); | ||
| 531 | + | ||
| 530 | 532 | // This is only used in the vm for magic methods, which use a greatly simplified attribute lookup. | |
| 531 | 533 | let cls = obj.class(); | |
| 532 | 534 | match objtype::class_get_attr(&cls, method_name) { | |
@@ -545,7 +547,6 @@ impl VirtualMachine { | |||
| 545 | 547 | } | |
| 546 | 548 | } | |
| 547 | 549 | ||
| 548 | - #[cfg_attr(feature = "flame-it", flame("VirtualMachine"))] | ||
| 549 | 550 | fn _invoke(&self, func_ref: &PyObjectRef, args: PyFuncArgs) -> PyResult { | |
| 550 | 551 | vm_trace!("Invoke: {:?} {:?}", func_ref, args); | |
| 551 | 552 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments