3.7 "imports" and "or"

This commit is contained in:
rocky
2020-01-11 07:06:46 -05:00
parent 6cef42f6c7
commit c3d7ba6dad
13 changed files with 52 additions and 12 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -5,12 +5,15 @@
# RUNNABLE! # RUNNABLE!
import os.path as osp import os.path as osp
from sys import path from sys import platform
from os import sep, name from os import sep, name
import collections.abc import collections.abc
assert osp.basename("a") == "a" assert osp.basename("a") == "a"
assert path
assert isinstance(platform, str)
assert sep assert sep
assert name assert name
assert collections.abc assert collections.abc
import os.path as path
assert path

View File

@@ -8,3 +8,14 @@ def foo(n):
assert foo(95) assert foo(95)
assert not foo(94) assert not foo(94)
assert not foo(96) assert not foo(96)
# from test_buffer.py
# Bug was handling "or" inside a conditional
def rslice(a, b):
minlen = 0 if a or b else 1
return minlen
assert rslice(False, False) == 1
assert rslice(False, True) == 0
assert rslice(True, False) == 0
assert rslice(True, True) == 0

View File

@@ -454,7 +454,6 @@ case $PYVERSION in
[test_compare.py]=1 # test assert fail - investigate [test_compare.py]=1 # test assert fail - investigate
[test_compile.py]=1 [test_compile.py]=1
[test_configparser.py]=1 [test_configparser.py]=1
[test_contextlib_async.py]=1 # Investigate
[test_context.py]=1 [test_context.py]=1
[test_coroutines.py]=1 # Parse error [test_coroutines.py]=1 # Parse error
[test_crypt.py]=1 # Parse error [test_crypt.py]=1 # Parse error

View File

@@ -913,6 +913,7 @@ class Python37Parser(Python37BaseParser):
or ::= and jitop_come_from expr COME_FROM or ::= and jitop_come_from expr COME_FROM
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
or ::= expr JUMP_IF_TRUE expr COME_FROM or ::= expr JUMP_IF_TRUE expr COME_FROM
or ::= expr POP_JUMP_IF_TRUE expr POP_JUMP_IF_FALSE COME_FROM
testfalse_not_or ::= expr jmp_false expr jmp_false COME_FROM testfalse_not_or ::= expr jmp_false expr jmp_false COME_FROM
testfalse_not_and ::= and jmp_true come_froms testfalse_not_and ::= and jmp_true come_froms

View File

@@ -3,10 +3,7 @@
def or_check(self, lhs, n, rule, ast, tokens, first, last): def or_check(self, lhs, n, rule, ast, tokens, first, last):
if rule == ("or", ("expr", "jmp_true", "expr")): if rule == ("or", ("expr", "jmp_true", "expr")):
if tokens[last] in ( if tokens[last] in ("LOAD_ASSERT", "RAISE_VARARGS_1",):
"LOAD_ASSERT",
"RAISE_VARARGS_1",
):
return True return True
# The following test is be the most accurate. It prevents "or" from being # The following test is be the most accurate. It prevents "or" from being
@@ -16,7 +13,7 @@ def or_check(self, lhs, n, rule, ast, tokens, first, last):
# The below then is useful until we get better control-flow analysis. # The below then is useful until we get better control-flow analysis.
# Note it is too hard in the scanner right nowto turn the LOAD_GLOBAL into # Note it is too hard in the scanner right nowto turn the LOAD_GLOBAL into
# int LOAD_ASSERT, however in 3.9ish code generation does this by default. # int LOAD_ASSERT, however in 3.9ish code generation does this by default.
load_global = tokens[last-1] load_global = tokens[last - 1]
if load_global == "LOAD_GLOBAL" and load_global.attr == "AssertionError": if load_global == "LOAD_GLOBAL" and load_global.attr == "AssertionError":
return True return True
@@ -24,11 +21,14 @@ def or_check(self, lhs, n, rule, ast, tokens, first, last):
jmp_false = tokens[last] jmp_false = tokens[last]
# If the jmp is backwards # If the jmp is backwards
if jmp_false == "POP_JUMP_IF_FALSE": if jmp_false == "POP_JUMP_IF_FALSE":
if jmp_false.attr < jmp_false.off2int(): jmp_false_offset = jmp_false.off2int()
if jmp_false.attr < jmp_false_offset:
# For a backwards loop, well compare to the instruction *after* # For a backwards loop, well compare to the instruction *after*
# then POP_JUMP... # then POP_JUMP...
jmp_false = tokens[last+1] jmp_false = tokens[last + 1]
return not (jmp_true_target == jmp_false.off2int() or return not (
jmp_true_target < tokens[first].off2int()) (jmp_false_offset <= jmp_true_target <= jmp_false_offset + 2)
or jmp_true_target < tokens[first].off2int()
)
return False return False

View File

@@ -287,6 +287,32 @@ class TreeTransform(GenericASTTraversal, object):
n_ifelsestmtc = n_ifelsestmtl = n_ifelsestmt n_ifelsestmtc = n_ifelsestmtl = n_ifelsestmt
def n_import_from37(self, node):
importlist37 = node[3]
assert importlist37 == "importlist37"
if len(importlist37) == 1:
alias37 = importlist37[0]
store = alias37[1]
assert store == "store"
alias_name = store[0].attr
import_name_attr = node[2]
assert import_name_attr == "IMPORT_NAME_ATTR"
dotted_names = import_name_attr.attr.split(".")
if len(dotted_names) > 1:
# Simulate:
# Instead of
# import_from37 ::= LOAD_CONST LOAD_CONST IMPORT_NAME_ATTR importlist37 POP_TOP
# import_as37 ::= LOAD_CONST LOAD_CONST importlist37 store POP_TOP
# 'import_as37': ( '%|import %c as %c\n', 2, -2),
assert dotted_names[-1] == alias_name
node = SyntaxTree("import_as37",
[node[0], node[1], import_name_attr, store, node[-1]])
node.transformed_by="n_import_from37"
pass
pass
return node
def n_list_for(self, list_for_node): def n_list_for(self, list_for_node):
expr = list_for_node[0] expr = list_for_node[0]
if expr == "expr" and expr[0] == "get_iter": if expr == "expr" and expr[0] == "get_iter":