Ejemplo n.º 1
0
def number_inc_gt(typechar, loopvar, stop, step, sgn):
    """ Increase number and check if it exceeds a limit. """
    if sgn == 0:
        return False
    if typechar in ('#', '!'):
        fp_left = fp.from_bytes(loopvar).iadd(step)
        loopvar[:] = fp_left.to_bytes()
        return fp_left.gt(stop) if sgn > 0 else stop.gt(fp_left)
    else:
        int_left = vartypes.sint_to_value(loopvar) + step
        loopvar[:] = vartypes.value_to_sint(int_left)
        return int_left > stop if sgn > 0 else stop > int_left
Ejemplo n.º 2
0
def value_oct(ins):
    """ OCT$: octal representation of int. """
    # allow range -32768 to 65535
    val = vartypes.pass_int_unpack(parse_bracket(ins), 0xffff)
    return vartypes.pack_string(representation.oct_to_str(vartypes.value_to_sint(val))[2:])
Ejemplo n.º 3
0
def value_hex(ins):
    """ HEX$: hexadecimal representation of int. """
    # allow range -32768 to 65535
    val = vartypes.pass_int_unpack(parse_bracket(ins), 0xffff)
    return vartypes.pack_string(representation.hex_to_str(vartypes.value_to_sint(val))[2:])
Ejemplo n.º 4
0
def tokenise_dec(ins, outs):
    """ Convert decimal expression in Python string to number token. """
    have_exp = False
    have_point = False
    word = ''
    kill = False
    while True:
        c = ins.read(1).upper()
        if not c:
            break
        elif c in '\x1c\x1d\x1f':
            # ASCII separator chars invariably lead to zero result
            kill = True
        elif c == '.' and not have_point and not have_exp:
            have_point = True
            word += c
        elif c in 'ED' and not have_exp:
            have_exp = True
            # there's a special exception for number followed by EL or EQ
            # presumably meant to protect ELSE and maybe EQV ?
            if c == 'E' and util.peek(ins).upper() in ('L', 'Q'):
                ins.seek(-1, 1)
                break
            else:
                word += c
        elif c in '-+' and (not word or word[-1] in 'ED'):
            # must be first token or in exponent
            word += c
        elif c in ascii_digits:
            word += c
        elif c in ascii_whitespace:
            # we'll remove this later but need to keep it for now
            # so we can reposition the stream on removing trailing whitespace
            word += c
        elif c in '!#' and not have_exp:
            word += c
            break
        elif c == '%':
            # swallow a %, but break parsing
            break
        else:
            ins.seek(-1, 1)
            break
    # ascii separators encountered: zero output
    if kill:
        word = '0'
    # don't claim trailing whitespace
    while len(word) > 0 and (word[-1] in ascii_whitespace):
        word = word[:-1]
        ins.seek(-1, 1)  # even if c==''
    # remove all internal whitespace
    trimword = ''
    for c in word:
        if c not in ascii_whitespace:
            trimword += c
    word = trimword
    # write out the numbers
    if len(word) == 1 and word in ascii_digits:
        # digit
        outs.write(chr(0x11 + int(word)))
    elif (not (have_exp or have_point or word[-1] in '!#')
          and int(word) <= 0x7fff and int(word) >= -0x8000):
        if int(word) <= 0xff and int(word) >= 0:
            # one-byte constant
            outs.write(tk.T_BYTE + chr(int(word)))
        else:
            # two-byte constant
            outs.write(tk.T_INT + str(vartypes.value_to_sint(int(word))))
    else:
        mbf = str(str_to_float(word).to_bytes())
        if len(mbf) == 4:
            outs.write(tk.T_SINGLE + mbf)
        else:
            outs.write(tk.T_DOUBLE + mbf)
Ejemplo n.º 5
0
def value_mki(ins):
    """ MKI$: return the byte representation of an int. """
    return vartypes.pack_string(vartypes.value_to_sint(vartypes.pass_int_unpack(parse_bracket(ins))))
Ejemplo n.º 6
0
def tokenise_number(ins, outs):
    """ Convert Python-string number representation to number token. """
    c = util.peek(ins)
    # handle hex or oct constants
    if c == '&':
        ins.read(1)
        nxt = util.peek(ins).upper()
        if nxt == 'H': # hex constant
            ins.read(1)
            word = ''
            while True: 
                if not util.peek(ins).upper() in ascii_hexits:
                    break
                else:
                    word += ins.read(1).upper()
            val = int(word, 16) if word else 0
            outs.write('\x0C' + str(vartypes.value_to_uint(val)))
        else: # nxt == 'O': # octal constant
            if nxt == 'O':
                ins.read(1)
            word = ''    
            while True: 
                if not util.peek(ins).upper() in ascii_octits:
                    break
                else:
                    word += ins.read(1).upper()
            val = int(word, 8) if word else 0
            outs.write('\x0B' + str(vartypes.value_to_uint(val)))
    # handle other numbers
    # note GW passes signs separately as a token and only stores positive numbers in the program        
    elif (c in ascii_digits or c=='.' or c in ('+','-')):
        have_exp = False
        have_point = False
        word = ''
        while True: 
            c = ins.read(1).upper()
            if c == '.' and not have_point and not have_exp:
                have_point = True
                word += c
            elif c in ('E', 'D') and not have_exp:    
                have_exp = True
                word += c
            elif c in ('-','+') and word=='':
                # must be first token
                word += c              
            elif c in ('+', '-') and word[-1] in ('E', 'D'):
                word += c
            elif c in ascii_digits: # (c >='0' and numc <='9'):
                word += c
            elif c in whitespace:
                # we'll remove this later but need to keep it for now so we can reposition the stream on removing trainling whitespace 
                word += c
            elif c in ('!', '#') and not have_exp:
                word += c
                break
            elif c == '%':
                # swallow a %, but break parsing
                break    
            else:
                if c != '':
                    ins.seek(-1,1)
                break
        # don't claim trailing whitespace, don't end in D or E            
        while len(word)>0 and (word[-1] in whitespace + ('D', 'E')):
            if word[-1] in ('D', 'E'):
                have_exp = False
            word = word[:-1]
            ins.seek(-1,1) # even if c==''
        # remove all internal whitespace
        trimword = ''
        for c in word:
            if c not in whitespace:
                trimword += c
        word = trimword
        # write out the numbers
        if len(word) == 1 and word in ascii_digits:
            # digit
            outs.write(chr(0x11+int(word)))
        elif not (have_exp or have_point or word[-1] in ('!', '#')) and int(word) <= 0x7fff and int(word) >= -0x8000:
            if int(word) <= 0xff and int(word)>=0:
                # one-byte constant
                outs.write('\x0f'+chr(int(word)))
            else:
                # two-byte constant
                outs.write('\x1c'+str(vartypes.value_to_sint(int(word))))
        else:
            mbf = str(from_str(word).to_bytes())
            if len(mbf) == 4:
                # single
                outs.write('\x1d'+mbf)
            else:    
                # double
                outs.write('\x1f'+mbf)
    elif c!='':
        ins.seek(-1,1)
Ejemplo n.º 7
0
def value_hex(ins):
    """ HEX$: hexadecimal representation of int. """
    # allow range -32768 to 65535
    val = vartypes.pass_int_unpack(parse_bracket(ins), 0xffff)
    return vartypes.pack_string(
        representation.hex_to_str(vartypes.value_to_sint(val))[2:])
Ejemplo n.º 8
0
def value_oct(ins):
    """ OCT$: octal representation of int. """
    # allow range -32768 to 65535
    val = vartypes.pass_int_unpack(parse_bracket(ins), 0xffff)
    return vartypes.pack_string(
        representation.oct_to_str(vartypes.value_to_sint(val))[2:])
Ejemplo n.º 9
0
def value_mki(ins):
    """ MKI$: return the byte representation of an int. """
    return vartypes.pack_string(
        vartypes.value_to_sint(vartypes.pass_int_unpack(parse_bracket(ins))))
Ejemplo n.º 10
0
def tokenise_dec(ins, outs):
    """ Convert decimal expression in Python string to number token. """
    have_exp = False
    have_point = False
    word = ''
    kill = False
    while True:
        c = ins.read(1).upper()
        if not c:
            break
        elif c in '\x1c\x1d\x1f':
            # ASCII separator chars invariably lead to zero result
            kill = True
        elif c == '.' and not have_point and not have_exp:
            have_point = True
            word += c
        elif c in 'ED' and not have_exp:
            # there's a special exception for number followed by EL or EQ
            # presumably meant to protect ELSE and maybe EQV ?
            if c == 'E' and util.peek(ins).upper() in ('L', 'Q'):
                ins.seek(-1, 1)
                break
            else:
                have_exp = True
                word += c
        elif c in '-+' and (not word or word[-1] in 'ED'):
            # must be first token or in exponent
            word += c
        elif c in string.digits:
            word += c
        elif c in number_whitespace:
            # we'll remove this later but need to keep it for now
            # so we can reposition the stream on removing trailing whitespace
            word += c
        elif c in '!#' and not have_exp:
            word += c
            break
        elif c == '%':
            # swallow a %, but break parsing
            break
        else:
            ins.seek(-1, 1)
            break
    # ascii separators encountered: zero output
    if kill:
        word = '0'
    # don't claim trailing whitespace
    while len(word)>0 and (word[-1] in number_whitespace):
        word = word[:-1]
        ins.seek(-1,1) # even if c==''
    # remove all internal whitespace
    trimword = ''
    for c in word:
        if c not in number_whitespace:
            trimword += c
    word = trimword
    # write out the numbers
    if len(word) == 1 and word in string.digits:
        # digit
        outs.write(chr(0x11+int(word)))
    elif (not (have_exp or have_point or word[-1] in '!#') and
                            int(word) <= 0x7fff and int(word) >= -0x8000):
        if int(word) <= 0xff and int(word)>=0:
            # one-byte constant
            outs.write(tk.T_BYTE + chr(int(word)))
        else:
            # two-byte constant
            outs.write(tk.T_INT + str(vartypes.value_to_sint(int(word))))
    else:
        mbf = str(str_to_float(word).to_bytes())
        if len(mbf) == 4:
            outs.write(tk.T_SINGLE + mbf)
        else:
            outs.write(tk.T_DOUBLE + mbf)