Instruction:
Can you tell what is the following Python 3 function doing
def is_SYMBOL(token, *symbols):
    from symbols.symbol_ import Symbol
    assert all(isinstance(x, Symbol) for x in symbols)
    for sym in symbols:
        if sym.token != token:
            return False

    return True

Response: Returns True if all of the given argument are AST nodes of the given token.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def is_const(*p):
    return is_SYMBOL('VAR', *p) and all(x.class_ == CLASS.const for x in p)

Response: A constant in the program.


Instruction:
Write a Python 3 script for
returning True if ALL of the arguments are AST nodes containing NUMBER or numeric CONSTANTS

Response:
def is_number(*p):
    """ Returns True if ALL of the arguments are AST nodes
    containing NUMBER or numeric CONSTANTS
    """
    try:
        for i in p:
            if i.token != 'NUMBER' and (i.token != 'ID' or i.class_ != CLASS.const):
                return False

        return True
    except:
        pass

    return False


Instruction:
Make a summary of the following Python 3 code
def is_unsigned(*p):
    from symbols.type_ import Type

    try:
        for i in p:
            if not i.type_.is_basic or not Type.is_unsigned(i.type_):
                return False

        return True
    except:
        pass

    return False

Response: Returns true if all types in p are unsigned


Instruction:
Here you have a function in Python 3, explain what it does
def is_type(type_, *p):
    try:
        for i in p:
            if i.type_ != type_:
                return False

        return True
    except:
        pass

    return False

Response: True if all args have the same type


Instruction:
Can you write a function in Python 3 where it
trues if all args are dynamic

Response:
def is_dynamic(*p):  # TODO: Explain this better
    """ True if all args are dynamic (e.g. Strings, dynamic arrays, etc)
    The use a ptr (ref) and it might change during runtime.
    """
    from symbols.type_ import Type

    try:
        for i in p:
            if i.scope == SCOPE.global_ and i.is_basic and \
                    i.type_ != Type.string:
                return False

        return True
    except:
        pass

    return False


Instruction:
How would you code a function in Python 3 to
true if all the args are functions and / or subroutines.

Response:
def is_callable(*p):
    """ True if all the args are functions and / or subroutines
    """
    import symbols
    return all(isinstance(x, symbols.FUNCTION) for x in p)


Instruction:
Can you create a Python 3 function that
returns True if a block is accessed.

Response:
def is_block_accessed(block):
    """ Returns True if a block is "accessed". A block of code is accessed if
    it has a LABEL and it is used in a GOTO, GO SUB or @address access
    :param block: A block of code (AST node)
    :return: True / False depending if it has labels accessed or not
    """
    if is_LABEL(block) and block.accessed:
        return True

    for child in block.children:
        if not is_callable(child) and is_block_accessed(child):
            return True

    return False


Instruction:
How would you explain what the following Python 3 function does
def common_type(a, b):
    from symbols.type_ import SymbolBASICTYPE as BASICTYPE
    from symbols.type_ import Type as TYPE
    from symbols.type_ import SymbolTYPE

    if a is None or b is None:
        return None

    if not isinstance(a, SymbolTYPE):
        a = a.type_

    if not isinstance(b, SymbolTYPE):
        b = b.type_

    if a == b:  # Both types are the same?
        return a  # Returns it

    if a == TYPE.unknown and b == TYPE.unknown:
        return BASICTYPE(global_.DEFAULT_TYPE)

    if a == TYPE.unknown:
        return b

    if b == TYPE.unknown:
        return a

    # TODO: This will removed / expanded in the future
    assert a.is_basic
    assert b.is_basic

    types = (a, b)

    if TYPE.float_ in types:
        return TYPE.float_

    if TYPE.fixed in types:
        return TYPE.fixed

    if TYPE.string in types:  # TODO: Check this ??
        return TYPE.unknown

    result = a if a.size > b.size else b

    if not TYPE.is_unsigned(a) or not TYPE.is_unsigned(b):
        result = TYPE.to_signed(result)

    return result

Response: Returns a type which is common for both a and b types.


Instruction:
Write a Python 3 script to
filter the output removing useless preprocessor directives and writes it to the given file or to the screen.

Response:
def output(memory, ofile=None):
    """ Filters the output removing useless preprocessor #directives
    and writes it to the given file or to the screen if no file is passed
    """
    for m in memory:
        m = m.rstrip('\r\n\t ')  # Ensures no trailing newlines (might with upon includes)
        if m and m[0] == '#':  # Preprocessor directive?
            if ofile is None:
                print(m)
            else:
                ofile.write('%s\n' % m)
            continue

        # Prints a 4 spaces "tab" for non labels
        if m and ':' not in m:
            if ofile is None:
                print('    '),
            else:
                ofile.write('\t')

        if ofile is None:
            print(m)
        else:
            ofile.write('%s\n' % m)


Instruction:
Here you have a function in Python 3, explain what it does
def _16bit_oper(op1, op2=None, reversed=False):
    ''' Returns pop sequence for 16 bits operands
    1st operand in HL, 2nd operand in DE

    For subtraction, division, etc. you can swap operators extraction order
    by setting reversed to True
    '''
    output = []

    if op1 is not None:
        op1 = str(op1)  # always to str

    if op2 is not None:
        op2 = str(op2)  # always to str

    if op2 is not None and reversed:
        op1, op2 = op2, op1

    op = op1
    indirect = (op[0] == '*')
    if indirect:
        op = op[1:]

    immediate = (op[0] == '#')
    if immediate:
        op = op[1:]

    if is_int(op):
        op = int(op)

        if indirect:
            output.append('ld hl, (%i)' % op)
        else:
            output.append('ld hl, %i' % int16(op))
    else:
        if immediate:
            if indirect:
                output.append('ld hl, (%s)' % op)
            else:
                output.append('ld hl, %s' % op)
        else:
            if op[0] == '_':
                output.append('ld hl, (%s)' % op)
            else:
                output.append('pop hl')

            if indirect:
                output.append('ld a, (hl)')
                output.append('inc hl')
                output.append('ld h, (hl)')
                output.append('ld l, a')

    if op2 is None:
        return output

    if not reversed:
        tmp = output
        output = []

    op = op2
    indirect = (op[0] == '*')
    if indirect:
        op = op[1:]

    immediate = (op[0] == '#')
    if immediate:
        op = op[1:]

    if is_int(op):
        op = int(op)

        if indirect:
            output.append('ld de, (%i)' % op)
        else:
            output.append('ld de, %i' % int16(op))
    else:
        if immediate:
            output.append('ld de, %s' % op)
        else:
            if op[0] == '_':
                output.append('ld de, (%s)' % op)
            else:
                output.append('pop de')

            if indirect:
                output.append('call __LOAD_DE_DE')  # DE = (DE)
                REQUIRES.add('lddede.asm')

    if not reversed:
        output.extend(tmp)

    return output

Response: Returns pop sequence for 16 bits operands in HL 2nd operand in DE


Instruction:
Can you implement a function in Python 3 that
adds the last 2 bytes of the stack and adds them to the stack.

Response:
def _add16(ins):
    ''' Pops last 2 bytes from the stack and adds them.
    Then push the result onto the stack.

    Optimizations:
      * If any of the operands is ZERO,
        then do NOTHING: A + 0 = 0 + A = A

      * If any of the operands is < 4, then
        INC is used

      * If any of the operands is > (65531) (-4), then
        DEC is used
    '''
    op1, op2 = tuple(ins.quad[2:])
    if _int_ops(op1, op2) is not None:
        op1, op2 = _int_ops(op1, op2)
        op2 = int16(op2)
        output = _16bit_oper(op1)

        if op2 == 0:
            output.append('push hl')
            return output  # ADD HL, 0 => NOTHING

        if op2 < 4:
            output.extend(['inc hl'] * op2)  # ADD HL, 2 ==> inc hl; inc hl
            output.append('push hl')
            return output

        if op2 > 65531:  # (between -4 and 0)
            output.extend(['dec hl'] * (0x10000 - op2))
            output.append('push hl')
            return output

        output.append('ld de, %i' % op2)
        output.append('add hl, de')
        output.append('push hl')
        return output

    if op2[0] == '_':  # stack optimization
        op1, op2 = op2, op1

    output = _16bit_oper(op1, op2)
    output.append('add hl, de')
    output.append('push hl')
    return output


Instruction:
Here you have a function in Python 3, explain what it does
def _sub16(ins):
    ''' Pops last 2 words from the stack and subtract them.
    Then push the result onto the stack. Top of the stack is
    subtracted Top -1

    Optimizations:
      * If 2nd op is ZERO,
        then do NOTHING: A - 0 = A

      * If any of the operands is < 4, then
        DEC is used

      * If any of the operands is > 65531 (-4..-1), then
        INC is used
    '''
    op1, op2 = tuple(ins.quad[2:4])

    if is_int(op2):
        op = int16(op2)
        output = _16bit_oper(op1)

        if op == 0:
            output.append('push hl')
            return output

        if op < 4:
            output.extend(['dec hl'] * op)
            output.append('push hl')
            return output

        if op > 65531:
            output.extend(['inc hl'] * (0x10000 - op))
            output.append('push hl')
            return output

        output.append('ld de, -%i' % op)
        output.append('add hl, de')
        output.append('push hl')
        return output

    if op2[0] == '_':  # Optimization when 2nd operand is an id
        rev = True
        op1, op2 = op2, op1
    else:
        rev = False

    output = _16bit_oper(op1, op2, rev)
    output.append('or a')
    output.append('sbc hl, de')
    output.append('push hl')
    return output

Response: Sub16 operation for internal use only.


Instruction:
Here you have a function in Python 3, explain what it does
def _mul16(ins):
    ''' Multiplies tow last 16bit values on top of the stack and
    and returns the value on top of the stack

    Optimizations:
      * If any of the ops is ZERO,
        then do A = 0 ==> XOR A, cause A * 0 = 0 * A = 0

      * If any ot the ops is ONE, do NOTHING
        A * 1 = 1 * A = A

      * If B is 2^n and B < 16 => Shift Right n
    '''
    op1, op2 = tuple(ins.quad[2:])
    if _int_ops(op1, op2) is not None:   # If any of the operands is constant
        op1, op2 = _int_ops(op1, op2)    # put the constant one the 2nd
        output = _16bit_oper(op1)

        if op2 == 0:  # A * 0 = 0 * A = 0
            if op1[0] in ('_', '$'):
                output = []  # Optimization: Discard previous op if not from the stack
            output.append('ld hl, 0')
            output.append('push hl')
            return output

        if op2 == 1:  # A * 1 = 1 * A == A => Do nothing
            output.append('push hl')
            return output

        if op2 == 0xFFFF:  # This is the same as (-1)
            output.append('call __NEGHL')
            output.append('push hl')
            REQUIRES.add('neg16.asm')
            return output

        if is_2n(op2) and log2(op2) < 4:
            output.extend(['add hl, hl'] * int(log2(op2)))
            output.append('push hl')
            return output

        output.append('ld de, %i' % op2)
    else:
        if op2[0] == '_':  # stack optimization
            op1, op2 = op2, op1

        output = _16bit_oper(op1, op2)

    output.append('call __MUL16_FAST')  # Inmmediate
    output.append('push hl')
    REQUIRES.add('mul16.asm')
    return output

Response:
Multiplies tow last 16bit values on top of the stack and returns the value on top of the stack and
           .


Instruction:
Write a Python 3 script for
dividing 2 16bit unsigned integers. The result is pushed onto the stack.

Response:
def _divu16(ins):
    ''' Divides 2 16bit unsigned integers. The result is pushed onto the stack.

    Optimizations:
      * If 2nd op is 1 then
        do nothing

      * If 2nd op is 2 then
        Shift Right Logical
    '''
    op1, op2 = tuple(ins.quad[2:])
    if is_int(op1) and int(op1) == 0:  # 0 / A = 0
        if op2[0] in ('_', '$'):
            output = []  # Optimization: Discard previous op if not from the stack
        else:
            output = _16bit_oper(op2)  # Normalize stack

        output.append('ld hl, 0')
        output.append('push hl')
        return output

    if is_int(op2):
        op = int16(op2)
        output = _16bit_oper(op1)

        if op2 == 0:  # A * 0 = 0 * A = 0
            if op1[0] in ('_', '$'):
                output = []  # Optimization: Discard previous op if not from the stack
            output.append('ld hl, 0')
            output.append('push hl')
            return output

        if op == 1:
            output.append('push hl')
            return output

        if op == 2:
            output.append('srl h')
            output.append('rr l')
            output.append('push hl')
            return output

        output.append('ld de, %i' % op)
    else:
        if op2[0] == '_':  # Optimization when 2nd operand is an id
            rev = True
            op1, op2 = op2, op1
        else:
            rev = False
        output = _16bit_oper(op1, op2, rev)

    output.append('call __DIVU16')
    output.append('push hl')
    REQUIRES.add('div16.asm')
    return output


Instruction:
How would you code a function in Python 3 to
return a 16bit unsigned integer array.

Response:
def _modu16(ins):
    ''' Reminder of div. 2 16bit unsigned integers. The result is pushed onto the stack.

        Optimizations:
         * If 2nd operand is 1 => Return 0
         * If 2nd operand = 2^n => do AND (2^n - 1)
    '''
    op1, op2 = tuple(ins.quad[2:])

    if is_int(op2):
        op2 = int16(op2)
        output = _16bit_oper(op1)

        if op2 == 1:
            if op2[0] in ('_', '$'):
                output = []  # Optimization: Discard previous op if not from the stack

            output.append('ld hl, 0')
            output.append('push hl')
            return output

        if is_2n(op2):
            k = op2 - 1
            if op2 > 255:  # only affects H
                output.append('ld a, h')
                output.append('and %i' % (k >> 8))
                output.append('ld h, a')
            else:
                output.append('ld h, 0')  # High part goes 0
                output.append('ld a, l')
                output.append('and %i' % (k % 0xFF))
                output.append('ld l, a')

            output.append('push hl')
            return output

        output.append('ld de, %i' % op2)
    else:
        output = _16bit_oper(op1, op2)

    output.append('call __MODU16')
    output.append('push hl')
    REQUIRES.add('div16.asm')
    return output


Instruction:
Here you have a function in Python 3, explain what it does
def _ltu16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand < 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        16 bit unsigned version
    '''
    output = _16bit_oper(ins.quad[2], ins.quad[3])
    output.append('or a')
    output.append('sbc hl, de')
    output.append('sbc a, a')
    output.append('push af')
    return output

Response:
Compares top 2 operands out of the stack and checks
        if the 1st operand < 2nd operand. Returns the instruction to be pushed onto the stack.


Instruction:
Create a Python 3 function for
comparing top 2 operands out of the stack and checks if the 1st operand < 2nd operand. Returns a new stack with the operands pushed onto the stack.

Response:
def _lti16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand < 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        16 bit signed version
    '''
    output = _16bit_oper(ins.quad[2], ins.quad[3])
    output.append('call __LTI16')
    output.append('push af')
    REQUIRES.add('lti16.asm')
    return output


Instruction:
Write a Python 3 function for
comparing top 2 operands out of the stack and checks if the 1st operand > 2nd operand. Returns a new string in the stack.

Response:
def _gtu16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand > 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        16 bit unsigned version
    '''
    output = _16bit_oper(ins.quad[2], ins.quad[3], reversed=True)
    output.append('or a')
    output.append('sbc hl, de')
    output.append('sbc a, a')
    output.append('push af')
    return output


Instruction:
Given the following Python 3 function, write the documentation
def _gti16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand > 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        16 bit signed version
    '''
    output = _16bit_oper(ins.quad[2], ins.quad[3], reversed=True)
    output.append('call __LTI16')
    output.append('push af')
    REQUIRES.add('lti16.asm')
    return output

Response:
Compares top 2 operands out of the stack and checks
        if the 1st operand > 2nd operand. Returns a new stack with the operands pushed onto the stack.


Instruction:
Explain what the following Python 3 code does
def _leu16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand <= 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        16 bit unsigned version
    '''
    output = _16bit_oper(ins.quad[2], ins.quad[3], reversed=True)
    output.append('or a')
    output.append('sbc hl, de')  # Carry if A > B
    output.append('ccf')  # Negates the result => Carry if A <= B
    output.append('sbc a, a')
    output.append('push af')
    return output

Response:
Compares top 2 operands out of the stack and checks
        if the 1st operand < 2nd operand. Returns a new string with the result.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _lei16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand <= 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        16 bit signed version
    '''
    output = _16bit_oper(ins.quad[2], ins.quad[3])
    output.append('call __LEI16')
    output.append('push af')
    REQUIRES.add('lei16.asm')
    return output

Response:
Compares top 2 operands out of the stack and checks
        if the 1st operand < 2nd operand. Returns the new stack.


Instruction:
Explain what the following Python 3 code does
def _geu16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand >= 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        16 bit unsigned version
    '''
    output = _16bit_oper(ins.quad[2], ins.quad[3])
    output.append('or a')
    output.append('sbc hl, de')
    output.append('ccf')
    output.append('sbc a, a')
    output.append('push af')
    return output

Response:
Compares top 2 operands out of the stack and checks
        if the 1st operand > 2nd operand. Returns a new string.


Instruction:
Can you generate the documentation for the following Python 3 function
def _eq16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand == 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        16 bit un/signed version
    '''
    output = _16bit_oper(ins.quad[2], ins.quad[3])
    output.append('call __EQ16')
    output.append('push af')
    REQUIRES.add('eq16.asm')

    return output

Response:
Compares top 2 operands out of the stack and checks
        if the 1st operand == 2nd operand. Returns a new stack with the operands pushed onto the stack.


Instruction:
Explain what the following Python 3 code does
def _ne16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand != 2nd operand (top of the stack).
        Pushes 0 if False, 1 if True.

        16 bit un/signed version
    '''
    output = _16bit_oper(ins.quad[2], ins.quad[3])
    output.append('or a')  # Resets carry flag
    output.append('sbc hl, de')
    output.append('ld a, h')
    output.append('or l')
    output.append('push af')

    return output

Response:
Compares top 2 operands out of the stack and checks
        16 bit unsigned version.


Instruction:
Implement a Python 3 function for
comparing 2 operands and returns either 0 if False 1 if True.

Response:
def _or16(ins):
    ''' Compares & pops top 2 operands out of the stack, and checks
        if the 1st operand OR (logical) 2nd operand (top of the stack),
        pushes 0 if False, 1 if True.

        16 bit un/signed version

        Optimizations:

        If any of the operators are constants: Returns either 0 or
        the other operand
    '''
    op1, op2 = tuple(ins.quad[2:])

    if _int_ops(op1, op2) is not None:
        op1, op2 = _int_ops(op1, op2)

        if op2 == 0:
            output = _16bit_oper(op1)
            output.append('ld a, h')
            output.append('or l')  # Convert x to Boolean
            output.append('push af')
            return output  # X or False = X

        output = _16bit_oper(op1)
        output.append('ld a, 0FFh')  # X or True = True
        output.append('push af')
        return output

    output = _16bit_oper(ins.quad[2], ins.quad[3])
    output.append('ld a, h')
    output.append('or l')
    output.append('or d')
    output.append('or e')
    output.append('push af')
    return output


Instruction:
Can you create a Python 3 function that
pops top 2 operands out of the stack, and performs 1st operand OR (bitwise) 2nd operand (top of the stack), pushes result (16 bit in HL). 16 bit un/signed version Optimizations: If any of the operators are constants: Returns either 0 or the other operand

Response:
def _bor16(ins):
    ''' Pops top 2 operands out of the stack, and performs
        1st operand OR (bitwise) 2nd operand (top of the stack),
        pushes result (16 bit in HL).

        16 bit un/signed version

        Optimizations:

        If any of the operators are constants: Returns either 0 or
        the other operand
    '''
    op1, op2 = tuple(ins.quad[2:])

    if _int_ops(op1, op2) is not None:
        op1, op2 = _int_ops(op1, op2)

        output = _16bit_oper(op1)
        if op2 == 0:  # X | 0 = X
            output.append('push hl')
            return output

        if op2 == 0xFFFF:  # X & 0xFFFF = 0xFFFF
            output.append('ld hl, 0FFFFh')
            output.append('push hl')
            return output

    output = _16bit_oper(op1, op2)
    output.append('call __BOR16')
    output.append('push hl')
    REQUIRES.add('bor16.asm')
    return output


Instruction:
Explain what the following Python 3 code does
def _not16(ins):
    ''' Negates top (Logical NOT) of the stack (16 bits in HL)
    '''
    output = _16bit_oper(ins.quad[2])
    output.append('ld a, h')
    output.append('or l')
    output.append('sub 1')
    output.append('sbc a, a')
    output.append('push af')
    return output

Response: Negates top ( Logical NOT ) of the stack


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _bnot16(ins):
    ''' Negates top (Bitwise NOT) of the stack (16 bits in HL)
    '''
    output = _16bit_oper(ins.quad[2])
    output.append('call __BNOT16')
    output.append('push hl')
    REQUIRES.add('bnot16.asm')
    return output

Response: Negates top ( Bitwise NOT of the stack


Instruction:
Can you implement a function in Python 3 that
negates top of the stack ( 16 bits in HL

Response:
def _neg16(ins):
    ''' Negates top of the stack (16 bits in HL)
    '''
    output = _16bit_oper(ins.quad[2])
    output.append('call __NEGHL')
    output.append('push hl')
    REQUIRES.add('neg16.asm')
    return output