Skip to content

Commit ebedf5c

Browse files
committed
bug fix: track use of global variables
1 parent 24d22c8 commit ebedf5c

File tree

5 files changed

+42
-28
lines changed

5 files changed

+42
-28
lines changed

mrpython/typechecking/translate.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ def set_translator_locale(locale_key):
9898
, "Forbidden use of parameter '{}' as iteration variable" : { 'fr' : "Le paramètre de nom `{}` ne peut être utilisé comme variable d'itération" }
9999
, "Forbidden use of parameter '{}' as comprehension variable" : { 'fr' : "Le paramètre de nom `{}` ne peut être utilisé comme variable de compréhension" }
100100
, "Forbidden use of a \"dead\" variable name '{}' (Python101 rule)" : { 'fr' : "Il n'est pas autorisé en Python101 d'utiliser cette variable car le nom '{}' est déjà utilisé dans la fonction." }
101-
, "Forbidden use of variable '{}' that is not in scope (Python101 scoping rule)" : { 'fr' : "La variable '{}' ne peut-être utilisée ici (règle de portée de Python101)." }
101+
, "Forbidden use of variable '{}' that is not in scope (Python101 scoping rule)" : { 'fr' : "La variable '{}' ne peut être utilisée ici (règle de portée de Python101)." }
102+
, "Forbidden use of global variable '{}' (Python101 rule)" : { 'fr' : "La variable '{}' est globale et ne peut être utilisée dans une fonction (règle Python101)."}
102103
, "Type name error" : { 'fr' : "Erreur de type nommé" }
103104
, "I don't find any definition for the type: {}" : { 'fr' : "Je ne trouve pas de définition pour le type: {}" }
104105
, "Bad iterator" : { 'fr' : "Problème d'itération" }

mrpython/typechecking/typechecker.py

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -323,30 +323,6 @@ def type_check_Program(prog):
323323
else:
324324
ctx.register_function(fun_name, fun_type, fun_def)
325325

326-
### XXX : old code for annotations
327-
# else:
328-
# #print(repr(signature))
329-
# #print(fun_def.docstring)
330-
# signature = function_type_parser(fun_def.docstring)
331-
# if signature.iserror:
332-
# ctx.add_type_error(SignatureParseError(fun_name, fun_def, signature))
333-
# else: # HACK: trailing non-whistespace characters at the end of the signature
334-
# #parsed = fun_def.docstring[0:signature.end_pos.offset:]
335-
# #print("parsed = '{}'".format(parsed))
336-
# remaining = fun_def.docstring[signature.end_pos.offset:]
337-
# #print("remaining = '{}'".format(remaining))
338-
# if not fun_def.docstring[signature.end_pos.offset-1].isspace() and remaining and not remaining[0].isspace():
339-
# ctx.add_type_error(SignatureTrailingError(fun_name, fun_def, remaining))
340-
# # XXX: Not fatal ?
341-
# else:
342-
# fun_type, unknown_alias = signature.content.unalias(ctx.type_defs)
343-
# if fun_type is None:
344-
# # position is a little bit ad-hoc
345-
# ctx.add_type_error(UnknownTypeAliasError(signature.content, unknown_alias, fun_def.ast.lineno+ 1, fun_def.ast.col_offset + 7))
346-
# return ctx
347-
# else:
348-
# ctx.register_function(fun_name, fun_type, fun_def)
349-
350326
# fourth step : type-check each function
351327
for (fun_name, fun_def) in ctx.functions.items():
352328
fun_def.type_check(ctx)
@@ -1060,7 +1036,7 @@ def ContainerAssign_type_check(cassign, ctx):
10601036
if isinstance(container_type, DictType):
10611037
if container_type.key_type is None:
10621038
ctx.add_type_error(ContainerAssignEmptyError(cassign))
1063-
return False
1039+
return False
10641040
key_type = container_type.key_type
10651041
val_type = container_type.val_type
10661042
elif isinstance(container_type, ListType):
@@ -1421,6 +1397,13 @@ def type_infer_EVar(var, ctx):
14211397
if var.name in ctx.global_env:
14221398
return ctx.global_env[var.name]
14231399

1400+
# or, is it a global variable ?
1401+
for global_var in ctx.prog.global_vars:
1402+
if isinstance(global_var, DeclareVar) and isinstance(global_var.target, LHSVar):
1403+
if var.name == global_var.target.var_name:
1404+
ctx.add_type_error(GlobalVariableUseError(var.name, var))
1405+
return None
1406+
14241407
# or the variable is unknown
14251408
ctx.add_type_error(UnknownVariableError(ctx.function_def, var))
14261409
return None
@@ -3124,6 +3107,21 @@ def report(self, report):
31243107
report.add_convention_error('error', tr("Bad variable"), self.node.ast.lineno, self.node.ast.col_offset
31253108
, tr("Forbidden use of a \"dead\" variable name '{}' (Python101 rule)").format(self.var_name))
31263109

3110+
class GlobalVariableUseError(TypeError):
3111+
def __init__(self, var_name, node):
3112+
self.var_name = var_name
3113+
self.node = node
3114+
3115+
def is_fatal(self):
3116+
return True
3117+
3118+
def fail_string(self):
3119+
return "GlobalVariableUseError[{}]@{}:{}".format(self.var_name, self.node.ast.lineno, self.node.ast.col_offset)
3120+
3121+
def report(self, report):
3122+
report.add_convention_error('error', tr("Bad variable"), self.node.ast.lineno, self.node.ast.col_offset
3123+
, tr("Forbidden use of global variable '{}' (Python101 rule)").format(self.var_name))
3124+
31273125
class VariableTypeError(TypeError):
31283126
def __init__(self, target, var, declared_type, var_type):
31293127
self.target = target

mrpython/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MRPYTHON_VERSION_MAJOR = 5
22
MRPYTHON_VERSION_MINOR = 1
3-
MRPYTHON_VERSION_PATCH = 5
3+
MRPYTHON_VERSION_PATCH = 6
44
MRPYTHON_VERSION_TAG = "beta"
55

66

test/progs/46_dict_assign_OK.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
def incrementer(d : Dict[str,int]) -> None:
3-
"""Incrémente tous les éléments du dictionnaire d.
3+
"""***Procedure***
4+
Incrémente tous les éléments du dictionnaire d.
45
"""
56
e : str
67
for e in d:

test/progs/54_glob_ref_KO.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
##!FAIL: GlobalVariableUseError[glob]@12:18
2+
3+
glob : Dict[str,int] = {"test": 1}
4+
assert glob["test"] == 1
5+
6+
def f(lst:List[str])-> Dict[str,float]:
7+
"""..."""
8+
l : int = len(lst)
9+
dic : Dict[str,float] = dict()
10+
e:str
11+
for e in lst:
12+
dic[e] = (glob[e]/l)
13+
return dic
14+

0 commit comments

Comments
 (0)