# -----------------
# First a few name resolution things
# -----------------

x = 3
if NOT_DEFINED:
    x = ''
#? 6 int()
elif x:
    pass
else:
    #? int()
    x

x = 1
try:
    x = ''
#? 8 int() str()
except x:
    #? 5 int() str()
    x
    x = 1.0
else:
    #? 5 int() str()
    x
    x = list
finally:
    #? 5 int() str() float() list
    x
    x = tuple


# -----------------
# Return checks
# -----------------

def foo(x):
    if 1.0:
        return 1
    else:
        return ''

#? int()
foo(1)


#  Exceptions are not analyzed. So check both if branches
def try_except(x):
    try:
        if 0:
            return 1
        else:
            return ''
    except AttributeError:
        return 1.0

#? float() str()
try_except(1)


#  Exceptions are not analyzed. So check both if branches
def try_except(x):
    try:
        if 0:
            return 1
        else:
            return ''
    except AttributeError:
        return 1.0

#? float() str()
try_except(1)


# -----------------
# elif
# -----------------

def elif_flows1(x):
    if False:
        return 1
    elif True:
        return 1.0
    else:
        return ''

#? float()
elif_flows1(1)


def elif_flows2(x):
    try:
        if False:
            return 1
        elif 0:
            return 1.0
        else:
            return ''
    except ValueError:
        return set

#? str() set
elif_flows2(1)


def elif_flows3(x):
    try:
        if True:
            return 1
        elif 0:
            return 1.0
        else:
            return ''
    except ValueError:
        return set

#? int() set
elif_flows3(1)

# -----------------
# mid-difficulty if statements
# -----------------
def check(a):
    if a is None:
        return 1
    return ''
    return set

#? int()
check(None)
#? str()
check('asb')

a = list
if 2 == True:
    a = set
elif 1 == True:
    a = 0

#? int()
a
if check != 1:
    a = ''
#? str()
a
if check == check:
    a = list
#? list
a
if check != check:
    a = set
else:
    a = dict
#? dict
a
if not (check is not check):
    a = 1
#? int()
a


# -----------------
# name resolution
# -----------------

a = list
def elif_name(x):
    try:
        if True:
            a = 1
        elif 0:
            a = 1.0
        else:
            return ''
    except ValueError:
        a = x
    return a

#? int() set
elif_name(set)

if 0:
    a = ''
else:
    a = int

#? int
a

# -----------------
# isinstance
# -----------------

class A(): pass

def isinst(x):
    if isinstance(x, A):
        return dict
    elif isinstance(x, int) and x == 1 or x is True:
        return set
    elif isinstance(x, (float, reversed)):
        return list
    elif not isinstance(x, str):
        return tuple
    return 1

#? dict
isinst(A())
#? set
isinst(True)
#? set
isinst(1)
#? tuple
isinst(2)
#? list
isinst(1.0)
#? tuple
isinst(False)
#? int()
isinst('')

# -----------------
# flows that are not reachable should be able to access parent scopes.
# -----------------

foobar = ''

if 0:
    within_flow = 1.0
    #? float()
    within_flow
    #? str()
    foobar
    if 0:
        nested = 1
        #? int()
        nested
        #? float()
        within_flow
        #? str()
        foobar
    #?
    nested

if False:
    in_false = 1
    #? ['in_false']
    in_false

# -----------------
# True objects like modules
# -----------------

class X():
    pass
if X:
    a = 1
else:
    a = ''
#? int()
a


# -----------------
# Recursion issues
# -----------------

def possible_recursion_error(filename):
    if filename == 'a':
        return filename
    # It seems like without the brackets there wouldn't be a RecursionError.
    elif type(filename) == str:
        return filename


if NOT_DEFINED:
    s = str()
else:
    s = str()
#? str()
possible_recursion_error(s)


# -----------------
# In combination with imports
# -----------------

from import_tree import flow_import

if 1 == flow_import.env:
    a = 1
elif 2 == flow_import.env:
    a = ''
elif 3 == flow_import.env:
    a = 1.0

#? int() str()
a
