# Path: javadecompiler/Krakatau/ssa/objtypes.py
# def isSubtype(env, x, y):
# def commonSupertype(env, tts):
# def verifierToSynthetic_seq(vtypes):
# def verifierToSynthetic(vtype):
# def declTypeToActual(env, decltype):


import itertools, math
from ..ssa import objtypes
from .stringescape import escapeString

#############################################################################################################################################
_assignable_sprims = '.byte','.short','.char'
_assignable_lprims = '.int','.long','.float','.double'

def isObject(tt):
    return tt == objtypes.NullTT or tt[1] > 0 or not tt[0][0].startswith('.')

def isPrimativeAssignable(fromt, to):
    x, y = fromt[0], to[0]
    assert(fromt[1] == to[1] == 0)

    if x == y or (x in _assignable_sprims and y in _assignable_lprims):
        return True
    elif (x in _assignable_lprims and y in _assignable_lprims):
        return _assignable_lprims.index(x) <= _assignable_lprims.index(y)
    else:
        return x == '.byte' and y == '.short'

def isJavaAssignable(env, fromt, to):
    if fromt is None or to is None: #this should never happen, except during debugging
        return True

    if isObject(to):
        assert(isObject(fromt))
        #todo - make it check interfaces too
        return objtypes.isSubtype(env, fromt, to)
    else: #allowed if numeric conversion is widening
        return isPrimativeAssignable(fromt, to)


# Path: javadecompiler/Krakatau/ssa/objtypes.py
# def isSubtype(env, x, y):
# def commonSupertype(env, tts):
# def verifierToSynthetic_seq(vtypes):
# def verifierToSynthetic(vtype):
# def declTypeToActual(env, decltype):


# Path: javadecompiler/Krakatau/java/ast.py
import itertools, math
from ..ssa import objtypes
from .stringescape import escapeString


#############################################################################################################################################
_assignable_sprims = '.byte','.short','.char'
_assignable_lprims = '.int','.long','.float','.double'

def isObject(tt):
    return tt == objtypes.NullTT or tt[1] > 0 or not tt[0][0].startswith('.')

def isPrimativeAssignable(fromt, to):
    x, y = fromt[0], to[0]
    assert(fromt[1] == to[1] == 0)

    if x == y or (x in _assignable_sprims and y in _assignable_lprims):
        return True
    elif (x in _assignable_lprims and y in _assignable_lprims):
        return _assignable_lprims.index(x) <= _assignable_lprims.index(y)
    else:
        return x == '.byte' and y == '.short'

def isJavaAssignable(env, fromt, to):
    if fromt is None or to is None: #this should never happen, except during debugging
        return True

    if isObject(to):
        assert(isObject(fromt))
        #todo - make it check interfaces too
        return objtypes.isSubtype(env, fromt, to)
    else: #allowed if numeric conversion is widening
        return isPrimativeAssignable(fromt, to)


_int_tts = objtypes.LongTT, objtypes.IntTT, objtypes.ShortTT, objtypes.CharTT, objtypes.ByteTT