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

global and local syntax error

parent 551d925d
...@@ -218,6 +218,7 @@ struct ScopingAnalysis::ScopeNameUsage { ...@@ -218,6 +218,7 @@ struct ScopingAnalysis::ScopeNameUsage {
StrSet read; StrSet read;
StrSet written; StrSet written;
StrSet forced_globals; StrSet forced_globals;
StrSet params;
std::vector<AST_Name*> del_name_nodes; std::vector<AST_Name*> del_name_nodes;
// Properties determined by looking at other scopes as well: // Properties determined by looking at other scopes as well:
...@@ -439,14 +440,24 @@ private: ...@@ -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 { class NameCollectorVisitor : public ASTVisitor {
private: private:
AST* orig_node; AST* orig_node;
ScopingAnalysis::NameUsageMap* map; ScopingAnalysis::NameUsageMap* map;
ScopingAnalysis::ScopeNameUsage* cur; ScopingAnalysis::ScopeNameUsage* cur;
ScopingAnalysis* scoping; ScopingAnalysis* scoping;
bool currently_visiting_functiondef_args;
NameCollectorVisitor(AST* node, ScopingAnalysis::NameUsageMap* map, ScopingAnalysis* scoping) 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); assert(map);
cur = (*map)[node]; cur = (*map)[node];
assert(cur); assert(cur);
...@@ -457,6 +468,9 @@ public: ...@@ -457,6 +468,9 @@ public:
assert(name == mangleName(name, cur->private_name, scoping->getInternedStrings())); assert(name == mangleName(name, cur->private_name, scoping->getInternedStrings()));
cur->read.insert(name); cur->read.insert(name);
cur->written.insert(name); cur->written.insert(name);
if (this->currently_visiting_functiondef_args) {
cur->params.insert(name);
}
} }
void doRead(InternedString name) { void doRead(InternedString name) {
...@@ -549,6 +563,10 @@ public: ...@@ -549,6 +563,10 @@ public:
bool visit_global(AST_Global* node) override { bool visit_global(AST_Global* node) override {
for (int i = 0; i < node->names.size(); i++) { for (int i = 0; i < node->names.size(); i++) {
mangleNameInPlace(node->names[i], cur->private_name, scoping->getInternedStrings()); 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]); cur->forced_globals.insert(node->names[i]);
} }
return true; return true;
...@@ -577,6 +595,8 @@ public: ...@@ -577,6 +595,8 @@ public:
bool visit_functiondef(AST_FunctionDef* node) override { bool visit_functiondef(AST_FunctionDef* node) override {
if (node == orig_node) { if (node == orig_node) {
this->currently_visiting_functiondef_args = true;
int counter = 0; int counter = 0;
for (AST_expr* e : node->args->args) { for (AST_expr* e : node->args->args) {
if (e->type == AST_TYPE::Tuple) { if (e->type == AST_TYPE::Tuple) {
...@@ -594,6 +614,9 @@ public: ...@@ -594,6 +614,9 @@ public:
mangleNameInPlace(node->args->kwarg, cur->private_name, scoping->getInternedStrings()); mangleNameInPlace(node->args->kwarg, cur->private_name, scoping->getInternedStrings());
doWrite(node->args->kwarg); doWrite(node->args->kwarg);
} }
this->currently_visiting_functiondef_args = false;
for (AST_stmt* s : node->body) for (AST_stmt* s : node->body)
s->accept(this); s->accept(this);
return true; return true;
......
# expected: fail
# - this particular check isn't implemented yet # - 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" # 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 x = 1
def f(x): def f(x):
global x global x
...@@ -12,3 +11,56 @@ def f(x): ...@@ -12,3 +11,56 @@ def f(x):
print "calling" print "calling"
f(2) f(2)
print x 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