Commit 1d6a39fa authored by Travis Hance's avatar Travis Hance

global and local syntax error

parent 551d925d
......@@ -218,6 +218,7 @@ struct ScopingAnalysis::ScopeNameUsage {
StrSet read;
StrSet written;
StrSet forced_globals;
StrSet params;
std::vector<AST_Name*> del_name_nodes;
// Properties determined by looking at other scopes as well:
......@@ -439,14 +440,24 @@ private:
};
};
static void raiseGlobalAndLocalException(InternedString name, AST* node) {
assert(node->type == AST_TYPE::FunctionDef);
AST_FunctionDef* funcNode = ast_cast<AST_FunctionDef>(node);
char buf[1024];
snprintf(buf, sizeof(buf), "name '%s' is local and global", name.c_str());
raiseSyntaxError(buf, funcNode->lineno, funcNode->col_offset, "" /* file?? */, funcNode->name.str());
}
class NameCollectorVisitor : public ASTVisitor {
private:
AST* orig_node;
ScopingAnalysis::NameUsageMap* map;
ScopingAnalysis::ScopeNameUsage* cur;
ScopingAnalysis* scoping;
bool currently_visiting_functiondef_args;
NameCollectorVisitor(AST* node, ScopingAnalysis::NameUsageMap* map, ScopingAnalysis* scoping)
: orig_node(node), map(map), scoping(scoping) {
: orig_node(node), map(map), scoping(scoping), currently_visiting_functiondef_args(false) {
assert(map);
cur = (*map)[node];
assert(cur);
......@@ -457,6 +468,9 @@ public:
assert(name == mangleName(name, cur->private_name, scoping->getInternedStrings()));
cur->read.insert(name);
cur->written.insert(name);
if (this->currently_visiting_functiondef_args) {
cur->params.insert(name);
}
}
void doRead(InternedString name) {
......@@ -549,6 +563,10 @@ public:
bool visit_global(AST_Global* node) override {
for (int i = 0; i < node->names.size(); i++) {
mangleNameInPlace(node->names[i], cur->private_name, scoping->getInternedStrings());
if (cur->params.find(node->names[i]) != cur->params.end()) {
// Throw an exception if a name is both declared global and a parameter
raiseGlobalAndLocalException(node->names[i], this->orig_node);
}
cur->forced_globals.insert(node->names[i]);
}
return true;
......@@ -577,6 +595,8 @@ public:
bool visit_functiondef(AST_FunctionDef* node) override {
if (node == orig_node) {
this->currently_visiting_functiondef_args = true;
int counter = 0;
for (AST_expr* e : node->args->args) {
if (e->type == AST_TYPE::Tuple) {
......@@ -594,6 +614,9 @@ public:
mangleNameInPlace(node->args->kwarg, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->kwarg);
}
this->currently_visiting_functiondef_args = false;
for (AST_stmt* s : node->body)
s->accept(this);
return true;
......
# expected: fail
# - this particular check isn't implemented yet
# I would have expected this to be valid, but cPython and pypy err out saying "name 'x' is local and global"
print "first"
try:
exec """
x = 1
def f(x):
global x
......@@ -12,3 +11,56 @@ def f(x):
print "calling"
f(2)
print x
"""
except SyntaxError as e:
print e.message
try:
exec """
x = 1
def f((x, y)):
global x
print "calling"
f(2)
print x
"""
except SyntaxError as e:
print e.message
try:
exec """
def f(*args):
global args
print "calling"
f(2)
print x
"""
except SyntaxError as e:
print e.message
try:
exec """
def f(*kwargs):
global kwargs
print "calling"
f(d=2)
print x
"""
except SyntaxError as e:
print e.message
try:
exec """
class C(object):
def f(__a):
global __a
print "calling"
f(d=2)
print x
"""
except SyntaxError as e:
print e.message
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment