Skip to content

Commit 5802d06

Browse files
committed
Extend AST python module. Add idea for scope detection.
1 parent 49ed782 commit 5802d06

File tree

3 files changed

+65
-13
lines changed

3 files changed

+65
-13
lines changed

compiler/src/symboltable.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,25 @@ impl SymbolTableAnalyzer {
204204
// all is well
205205
}
206206
SymbolScope::Unknown => {
207-
if symbol.is_assigned {
207+
// Try hard to figure out what the scope of this symbol is.
208+
209+
if symbol.is_assigned || symbol.is_parameter {
208210
symbol.scope = SymbolScope::Local;
211+
} else {
212+
// TODO: comment this out and make it work properly:
213+
/*
214+
let found_in_outer_scope = self
215+
.tables
216+
.iter()
217+
.any(|t| t.symbols.contains_key(&symbol.name));
218+
if found_in_outer_scope {
219+
// Symbol is in some outer scope.
220+
221+
} else {
222+
// Well, it must be a global then :)
223+
// symbol.scope = SymbolScope::Global;
224+
}
225+
*/
209226
}
210227
}
211228
}
@@ -710,7 +727,10 @@ impl SymbolTableBuilder {
710727
});
711728
}
712729
}
713-
SymbolUsage::Parameter | SymbolUsage::Assigned => {
730+
SymbolUsage::Parameter => {
731+
symbol.is_parameter = true;
732+
}
733+
SymbolUsage::Assigned => {
714734
symbol.is_assigned = true;
715735
}
716736
SymbolUsage::Global => {

vm/src/scope.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,8 @@ impl NameProtocol for Scope {
138138
}
139139
}
140140

141-
if let Some(value) = self.globals.get_item_option(name, vm).unwrap() {
142-
return Some(value);
143-
}
144-
145-
vm.get_attribute(vm.builtins.clone(), name).ok()
141+
// Fall back to loading a global after all scopes have been searched!
142+
self.load_global(vm, name)
146143
}
147144

148145
#[cfg_attr(feature = "flame-it", flame("Scope"))]
@@ -174,7 +171,11 @@ impl NameProtocol for Scope {
174171

175172
#[cfg_attr(feature = "flame-it", flame("Scope"))]
176173
fn load_global(&self, vm: &VirtualMachine, name: &str) -> Option<PyObjectRef> {
177-
self.globals.get_item_option(name, vm).unwrap()
174+
if let Some(value) = self.globals.get_item_option(name, vm).unwrap() {
175+
Some(value)
176+
} else {
177+
vm.get_attribute(vm.builtins.clone(), name).ok()
178+
}
178179
}
179180

180181
fn store_global(&self, vm: &VirtualMachine, name: &str, value: PyObjectRef) {

vm/src/stdlib/ast.rs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ fn optional_statements_to_ast(
252252
let statements = if let Some(statements) = statements {
253253
statements_to_ast(vm, statements)?.into_object()
254254
} else {
255-
vm.ctx.none()
255+
vm.ctx.new_list(vec![])
256256
};
257257
Ok(statements)
258258
}
@@ -283,6 +283,17 @@ fn make_string_list(vm: &VirtualMachine, names: &[String]) -> PyObjectRef {
283283
)
284284
}
285285

286+
fn optional_expressions_to_ast(
287+
vm: &VirtualMachine,
288+
expressions: &[Option<ast::Expression>],
289+
) -> PyResult<PyListRef> {
290+
let py_expression_nodes: PyResult<_> = expressions
291+
.iter()
292+
.map(|expression| Ok(optional_expression_to_ast(vm, expression)?))
293+
.collect();
294+
Ok(vm.ctx.new_list(py_expression_nodes?).downcast().unwrap())
295+
}
296+
286297
fn optional_expression_to_ast(vm: &VirtualMachine, value: &Option<ast::Expression>) -> PyResult {
287298
let value = if let Some(value) = value {
288299
expression_to_ast(vm, value)?.into_object()
@@ -526,8 +537,23 @@ fn operator_string(op: &ast::Operator) -> String {
526537
}
527538

528539
fn parameters_to_ast(vm: &VirtualMachine, args: &ast::Parameters) -> PyResult<AstNodeRef> {
529-
let args = map_ast(parameter_to_ast, vm, &args.args)?;
530-
Ok(node!(vm, arguments, { args => args }))
540+
Ok(node!(vm, arguments, {
541+
args => map_ast(parameter_to_ast, vm, &args.args)?,
542+
vararg => vararg_to_ast(vm, &args.vararg)?,
543+
kwonlyargs => map_ast(parameter_to_ast, vm, &args.kwonlyargs)?,
544+
kw_defaults => optional_expressions_to_ast(vm, &args.kw_defaults)?,
545+
kwarg => vararg_to_ast(vm, &args.kwarg)?,
546+
defaults => expressions_to_ast(vm, &args.defaults)?
547+
}))
548+
}
549+
550+
fn vararg_to_ast(vm: &VirtualMachine, vararg: &ast::Varargs) -> PyResult {
551+
let py_node = match vararg {
552+
ast::Varargs::None => vm.get_none(),
553+
ast::Varargs::Unnamed => vm.get_none(),
554+
ast::Varargs::Named(parameter) => parameter_to_ast(vm, parameter)?.into_object(),
555+
};
556+
Ok(py_node)
531557
}
532558

533559
fn parameter_to_ast(vm: &VirtualMachine, parameter: &ast::Parameter) -> PyResult<AstNodeRef> {
@@ -537,10 +563,15 @@ fn parameter_to_ast(vm: &VirtualMachine, parameter: &ast::Parameter) -> PyResult
537563
vm.ctx.none()
538564
};
539565

540-
Ok(node!(vm, arg, {
566+
let py_node = node!(vm, arg, {
541567
arg => vm.ctx.new_str(parameter.arg.to_string()),
542568
annotation => py_annotation
543-
}))
569+
});
570+
571+
let lineno = vm.ctx.new_int(parameter.location.row());
572+
vm.set_attr(py_node.as_object(), "lineno", lineno)?;
573+
574+
Ok(py_node)
544575
}
545576

546577
fn optional_string_to_py_obj(vm: &VirtualMachine, name: &Option<String>) -> PyObjectRef {

0 commit comments

Comments
 (0)