Exemple #1
0
def vplus(left, right):
    """ Left+right. """
    if left[0] == '$':
        return vartypes.pack_string(
            vartypes.pass_string_unpack(left) +
            vartypes.pass_string_unpack(right))
    else:
        return vartypes.number_add(left, right)
Exemple #2
0
def ml_parse_string(gmls):
    """ Parse a string value in a macro-language string. """
    c = util.skip(gmls, ml_whitepace)
    if len(c) == 0:
        raise error.RunError(error.IFC)
    elif ord(c) > 8:
        name = util.get_var_name(gmls)
        indices = ml_parse_indices(gmls)
        sub = var.get_var_or_array(name, indices)
        util.require_read(gmls, (';',), err=error.IFC)
        return vartypes.pass_string_unpack(sub, err=error.IFC)
    else:
        # varptr$
        return vartypes.pass_string_unpack(get_value_for_varptrstr(gmls.read(3)))
Exemple #3
0
def ml_parse_string(gmls):
    """ Parse a string value in a macro-language string. """
    c = util.skip(gmls, ml_whitepace)
    if len(c) == 0:
        raise error.RunError(error.IFC)
    elif ord(c) > 8:
        name = util.get_var_name(gmls, err=error.IFC)
        indices = ml_parse_indices(gmls)
        sub = var.get_var_or_array(name, indices)
        util.require_read(gmls, (';',), err=error.IFC)
        return vartypes.pass_string_unpack(sub, err=error.IFC)
    else:
        # varptr$
        return vartypes.pass_string_unpack(get_value_for_varptrstr(gmls.read(3)))
Exemple #4
0
def value_instr(ins):
    """ INSTR: find substring in string. """
    util.require_read(ins, ('(',))
    big, small, n = '', '', 1
    s = parse_expression(ins, empty_err=error.STX)
    if s[0] != '$':
        n = vartypes.pass_int_unpack(s)
        util.range_check(1, 255, n)
        util.require_read(ins, (',',))
        big = vartypes.pass_string_unpack(parse_expression(ins, allow_empty=True))
    else:
        big = vartypes.pass_string_unpack(s)
    util.require_read(ins, (',',))
    small = vartypes.pass_string_unpack(parse_expression(ins, allow_empty=True))
    util.require_read(ins, (')',))
    return vartypes.str_instr(big, small, n)
Exemple #5
0
def set_var(name, value):
    """ Assign a value to a variable. """
    name = vartypes.complete_name(name)
    type_char = name[-1]
    # check if garbage needs collecting before allocating mem
    size = (max(3, len(name)) + 1 + byte_size[type_char])
    if type_char == '$':
        unpacked = vartypes.pass_string_unpack(value) 
        size += len(unpacked)
    if fre() <= size:
        # TODO: GARBTEST difference is because string literal is currently stored in string space, whereas GW stores it in code space.
        collect_garbage()
        if fre() <= size:
            raise error.RunError(7)
    # assign variables
    if type_char == '$':
        # every assignment to string leads to new pointer being allocated
        # TODO: string literals in programs have the var ptr point to program space.
        state.basic_state.variables[name] = state.basic_state.strings.store(bytearray(unpacked[:]))
    else:
        # make a copy of the value in case we want to use POKE on it - we would change both values otherwise
        # NOTE: this is an in-place copy - crucial for FOR!
        try:
            state.basic_state.variables[name][:] = vartypes.pass_type_keep(name[-1], value)[1][:]
        except KeyError:
            state.basic_state.variables[name] = vartypes.pass_type_keep(name[-1], value)[1][:]
    # update memory model
    # first two bytes: chars of name or 0 if name is one byte long
    if name not in state.basic_state.var_memory:
        name_ptr = state.basic_state.var_current
        var_ptr = name_ptr + max(3, len(name)) + 1 # byte_size first_letter second_letter_or_nul remaining_length_or_nul 
        state.basic_state.var_current += max(3, len(name)) + 1 + byte_size[name[-1]]
        state.basic_state.var_memory[name] = (name_ptr, var_ptr)
Exemple #6
0
def value_instr(ins):
    """ INSTR: find substring in string. """
    util.require_read(ins, ('(', ))
    big, small, n = '', '', 1
    s = parse_expression(ins, empty_err=error.STX)
    if s[0] != '$':
        n = vartypes.pass_int_unpack(s)
        util.range_check(1, 255, n)
        util.require_read(ins, (',', ))
        big = vartypes.pass_string_unpack(
            parse_expression(ins, allow_empty=True))
    else:
        big = vartypes.pass_string_unpack(s)
    util.require_read(ins, (',', ))
    small = vartypes.pass_string_unpack(parse_expression(ins,
                                                         allow_empty=True))
    util.require_read(ins, (')', ))
    return vartypes.str_instr(big, small, n)
Exemple #7
0
 def type_converter(self, v_val):
     if (v_val[0] == '%'):
         return vartypes.pass_int_unpack(v_val)
     elif (v_val[0] == '!'):
         return fp.Single.from_bytes(v_val[1]).to_value()
     elif (v_val[0] == '#'):
         return fp.Double.from_bytes(v_val[1]).to_value()
     elif (v_val[0] == '$'):
         return str(vartypes.pass_string_unpack(v_val))
     else:
         raise error.RunError(error.TYPE_MISMATCH)
Exemple #8
0
def value_right(ins):
    """ RIGHT$: get substring at the end of string. """
    util.require_read(ins, ('(',))
    s = vartypes.pass_string_unpack(parse_expression(ins))
    util.require_read(ins, (',',))
    stop = vartypes.pass_int_unpack(parse_expression(ins))
    util.require_read(ins, (')',))
    util.range_check(0, 255, stop)
    if stop == 0:
        return vartypes.null['$']
    stop = min(stop, len(s))
    return vartypes.pack_string(s[-stop:])
Exemple #9
0
def value_right(ins):
    """ RIGHT$: get substring at the end of string. """
    util.require_read(ins, ('(', ))
    s = vartypes.pass_string_unpack(parse_expression(ins))
    util.require_read(ins, (',', ))
    stop = vartypes.pass_int_unpack(parse_expression(ins))
    util.require_read(ins, (')', ))
    util.range_check(0, 255, stop)
    if stop == 0:
        return vartypes.null['$']
    stop = min(stop, len(s))
    return vartypes.pack_string(s[-stop:])
Exemple #10
0
def str_to_value_keep(strval, allow_nonnum=True):
    """ Convert BASIC string to BASIC value. """
    if strval == ('$', ''):
        return vartypes.null['%']
    strval = str(vartypes.pass_string_unpack(strval))
    ins = StringIO(strval)
    outs = StringIO()
    # skip spaces and line feeds (but not NUL).
    util.skip(ins, (' ', '\n'))
    tokenise_number(ins, outs)    
    outs.seek(0)
    value = util.parse_value(outs)
    if not allow_nonnum:
        if util.skip_white(ins) != '':
            # not everything has been parsed - error
            return None    
    return value
Exemple #11
0
def value_mid(ins):
    """ MID$: get substring. """
    util.require_read(ins, ('(',))
    s = vartypes.pass_string_unpack(parse_expression(ins))
    util.require_read(ins, (',',))
    start = vartypes.pass_int_unpack(parse_expression(ins))
    if util.skip_white_read_if(ins, (',',)):
        num = vartypes.pass_int_unpack(parse_expression(ins))
    else:
        num = len(s)
    util.require_read(ins, (')',))
    util.range_check(1, 255, start)
    util.range_check(0, 255, num)
    if num == 0 or start > len(s):
        return vartypes.null['$']
    start -= 1
    stop = start + num
    stop = min(stop, len(s))
    return vartypes.pack_string(s[start:stop])
Exemple #12
0
def value_mid(ins):
    """ MID$: get substring. """
    util.require_read(ins, ('(', ))
    s = vartypes.pass_string_unpack(parse_expression(ins))
    util.require_read(ins, (',', ))
    start = vartypes.pass_int_unpack(parse_expression(ins))
    if util.skip_white_read_if(ins, (',', )):
        num = vartypes.pass_int_unpack(parse_expression(ins))
    else:
        num = len(s)
    util.require_read(ins, (')', ))
    util.range_check(1, 255, start)
    util.range_check(0, 255, num)
    if num == 0 or start > len(s):
        return vartypes.null['$']
    start -= 1
    stop = start + num
    stop = min(stop, len(s))
    return vartypes.pack_string(s[start:stop])
Exemple #13
0
def str_to_value_keep(strval, allow_nonnum=True):
    """ Convert BASIC string to BASIC value (VAL). """
    if strval == ('$', ''):
        if allow_nonnum:
            return vartypes.null['%']
        else:
            return None
    strval = str(vartypes.pass_string_unpack(strval))
    ins = StringIO(strval)
    outs = StringIO()
    # skip spaces and line feeds (but not NUL).
    util.skip(ins, (' ', '\n'))
    tokenise_number(ins, outs)
    outs.seek(0)
    value = parse_value(outs)
    if not allow_nonnum:
        if util.skip_white(ins) != '':
            # not everything has been parsed - error
            return None
    return value
Exemple #14
0
def set_var(name, value):
    """ Assign a value to a variable. """
    name = vartypes.complete_name(name)
    type_char = name[-1]
    # check if garbage needs collecting before allocating mem
    size = (max(3, len(name)) + 1 + byte_size[type_char])
    if type_char == '$':
        unpacked = vartypes.pass_string_unpack(value)
        size += len(unpacked)
    if fre() <= size:
        # TODO: GARBTEST difference is because string literal is currently stored in string space, whereas GW stores it in code space.
        collect_garbage()
        if fre() <= size:
            raise error.RunError(error.OUT_OF_MEMORY)
    # assign variables
    if type_char == '$':
        # every assignment to string leads to new pointer being allocated
        # TODO: string literals in programs have the var ptr point to program space.
        state.basic_state.variables[name] = state.basic_state.strings.store(
            bytearray(unpacked[:]))
    else:
        # make a copy of the value in case we want to use POKE on it - we would change both values otherwise
        # NOTE: this is an in-place copy - crucial for FOR!
        try:
            state.basic_state.variables[name][:] = vartypes.pass_type_keep(
                name[-1], value)[1][:]
        except KeyError:
            state.basic_state.variables[name] = vartypes.pass_type_keep(
                name[-1], value)[1][:]
    # update memory model
    # first two bytes: chars of name or 0 if name is one byte long
    if name not in state.basic_state.var_memory:
        name_ptr = state.basic_state.var_current
        var_ptr = name_ptr + max(
            3, len(name)
        ) + 1  # byte_size first_letter second_letter_or_nul remaining_length_or_nul
        state.basic_state.var_current += max(
            3, len(name)) + 1 + byte_size[name[-1]]
        state.basic_state.var_memory[name] = (name_ptr, var_ptr)
Exemple #15
0
def value_cvs(ins):
    """ CVS: return the single-precision value of a byte representation. """
    cstr = vartypes.pass_string_unpack(parse_bracket(ins))
    if len(cstr) < 4:
        raise error.RunError(error.IFC)
    return ('!', cstr[:4])
Exemple #16
0
def vplus(left, right):
    """ Left+right. """
    if left[0] == '$':
        return vartypes.pack_string(vartypes.pass_string_unpack(left) + vartypes.pass_string_unpack(right))
    else:
        return vartypes.number_add(left, right)
Exemple #17
0
def value_cvd(ins):
    """ CVD: return the double-precision value of a byte representation. """
    cstr = vartypes.pass_string_unpack(parse_bracket(ins))
    if len(cstr) < 8:
        raise error.RunError(error.IFC)
    return ('#', cstr[:8])
Exemple #18
0
def value_asc(ins):
    """ ASC: ordinal ASCII value of a character. """
    s = vartypes.pass_string_unpack(parse_bracket(ins))
    if not s:
        raise error.RunError(error.IFC)
    return vartypes.pack_int(s[0])
Exemple #19
0
def value_cvd(ins):
    """ CVD: return the double-precision value of a byte representation. """
    cstr =  vartypes.pass_string_unpack(parse_bracket(ins))
    if len(cstr) < 8:
        raise error.RunError(error.IFC)
    return ('#', cstr[:8])
Exemple #20
0
def value_cvs(ins):
    """ CVS: return the single-precision value of a byte representation. """
    cstr =  vartypes.pass_string_unpack(parse_bracket(ins))
    if len(cstr) < 4:
        raise error.RunError(error.IFC)
    return ('!', cstr[:4])
Exemple #21
0
def value_cvi(ins):
    """ CVI: return the int value of a byte representation. """
    cstr =  vartypes.pass_string_unpack(parse_bracket(ins))
    if len(cstr) < 2:
        raise error.RunError(error.IFC)
    return vartypes.pack_int(vartypes.sint_to_value(cstr[:2]))
Exemple #22
0
def value_len(ins):
    """ LEN: length of string. """
    return vartypes.pack_int(
        len(vartypes.pass_string_unpack(parse_bracket(ins))))
Exemple #23
0
def value_cvi(ins):
    """ CVI: return the int value of a byte representation. """
    cstr = vartypes.pass_string_unpack(parse_bracket(ins))
    if len(cstr) < 2:
        raise error.RunError(error.IFC)
    return vartypes.pack_int(vartypes.sint_to_value(cstr[:2]))
Exemple #24
0
def value_len(ins):
    """ LEN: length of string. """
    return vartypes.pack_int(len(vartypes.pass_string_unpack(parse_bracket(ins))) )
Exemple #25
0
def value_asc(ins):
    """ ASC: ordinal ASCII value of a character. """
    s = vartypes.pass_string_unpack(parse_bracket(ins))
    if not s:
        raise error.RunError(error.IFC)
    return vartypes.pack_int(s[0])