def _bool_eq(left, right): """ Return true if left == right, false otherwise. """ if left[0] == '$': return var.copy_str(vartypes.pass_string(left)) == var.copy_str(vartypes.pass_string(right)) else: left, right = vartypes.pass_most_precise(left, right) if left[0] in ('#', '!'): return fp.unpack(left).equals(fp.unpack(right)) else: return vartypes.integer_to_int_signed(left) == vartypes.integer_to_int_signed(right)
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.parse_scalar(gmls, err=error.IFC) indices = ml_parse_indices(gmls) sub = var.get_variable(name, indices) util.require_read(gmls, (';',), err=error.IFC) return var.copy_str(vartypes.pass_string(sub, err=error.IFC)) else: # varptr$ return var.copy_str( vartypes.pass_string(get_value_for_varptrstr(gmls.read(3))))
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.parse_scalar(gmls, err=error.IFC) indices = ml_parse_indices(gmls) sub = var.get_variable(name, indices) util.require_read(gmls, (';', ), err=error.IFC) return var.copy_str(vartypes.pass_string(sub, err=error.IFC)) else: # varptr$ return var.copy_str( vartypes.pass_string(get_value_for_varptrstr(gmls.read(3))))
def value_right(ins): """ RIGHT$: get substring at the end of string. """ util.require_read(ins, ('(',)) s = var.copy_str(vartypes.pass_string(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 state.basic_state.strings.store(s[-stop:])
def value_right(ins): """ RIGHT$: get substring at the end of string. """ util.require_read(ins, ('(', )) s = var.copy_str(vartypes.pass_string(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 state.basic_state.strings.store(s[-stop:])
def _bool_gt(left, right): """ Ordering: return -1 if left > right, 0 otherwise. """ if left[0] == '$': left, right = var.copy_str(vartypes.pass_string(left)), var.copy_str(vartypes.pass_string(right)) shortest = min(len(left), len(right)) for i in range(shortest): if left[i] > right[i]: return True elif left[i] < right[i]: return False # the same so far... # the shorter string is said to be less than the longer, # provided they are the same up till the length of the shorter. if len(left) > len(right): return True # left is shorter, or equal strings return False else: left, right = vartypes.pass_most_precise(left, right) if left[0] in ('#', '!'): return fp.unpack(left).gt(fp.unpack(right)) else: return vartypes.integer_to_int_signed(left) > vartypes.integer_to_int_signed(right)
def value_instr(ins): """ INSTR: find substring in string. """ util.require_read(ins, ('(',)) big, small, n = '', '', 1 # followed by coma so empty will raise STX s = parse_expression(ins) if s[0] != '$': n = vartypes.pass_int_unpack(s) util.range_check(1, 255, n) util.require_read(ins, (',',)) big = vartypes.pass_string(parse_expression(ins, allow_empty=True)) else: big = vartypes.pass_string(s) util.require_read(ins, (',',)) small = vartypes.pass_string(parse_expression(ins, allow_empty=True)) util.require_read(ins, (')',)) big, small = var.copy_str(big), var.copy_str(small) if big == '' or n > len(big): return vartypes.null('%') # BASIC counts string positions from 1 find = big[n-1:].find(small) if find == -1: return vartypes.null('%') return vartypes.int_to_integer_signed(n + find)
def value_instr(ins): """ INSTR: find substring in string. """ util.require_read(ins, ('(', )) big, small, n = '', '', 1 # followed by coma so empty will raise STX s = parse_expression(ins) if s[0] != '$': n = vartypes.pass_int_unpack(s) util.range_check(1, 255, n) util.require_read(ins, (',', )) big = vartypes.pass_string(parse_expression(ins, allow_empty=True)) else: big = vartypes.pass_string(s) util.require_read(ins, (',', )) small = vartypes.pass_string(parse_expression(ins, allow_empty=True)) util.require_read(ins, (')', )) big, small = var.copy_str(big), var.copy_str(small) if big == '' or n > len(big): return vartypes.null('%') # BASIC counts string positions from 1 find = big[n - 1:].find(small) if find == -1: return vartypes.null('%') return vartypes.int_to_integer_signed(n + find)
def value_mid(ins): """ MID$: get substring. """ util.require_read(ins, ('(', )) s = var.copy_str(vartypes.pass_string(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 state.basic_state.strings.store(s[start:stop])
def value_mid(ins): """ MID$: get substring. """ util.require_read(ins, ('(',)) s = var.copy_str(vartypes.pass_string(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 state.basic_state.strings.store(s[start:stop])
def value_cvi(ins): """ CVI: return the int value of a byte representation. """ cstr = var.copy_str(vartypes.pass_string(parse_bracket(ins))) if len(cstr) < 2: raise error.RunError(error.IFC) return vartypes.bytes_to_integer(cstr[:2])
def value_cvd(ins): """ CVD: return the double-precision value of a byte representation. """ cstr = var.copy_str(vartypes.pass_string(parse_bracket(ins))) if len(cstr) < 8: raise error.RunError(error.IFC) return ('#', bytearray(cstr[:8]))
def value_len(ins): """ LEN: length of string. """ return vartypes.int_to_integer_signed( vartypes.string_length(vartypes.pass_string(parse_bracket(ins))))
def value_asc(ins): """ ASC: ordinal ASCII value of a character. """ s = var.copy_str(vartypes.pass_string(parse_bracket(ins))) if not s: raise error.RunError(error.IFC) return vartypes.int_to_integer_signed(ord(s[0]))
def value_val(ins): """ VAL: number value of a string. """ return representation.str_to_number(var.copy_str(vartypes.pass_string(parse_bracket(ins))))
def value_cvs(ins): """ CVS: return the single-precision value of a byte representation. """ cstr = var.copy_str(vartypes.pass_string(parse_bracket(ins))) if len(cstr) < 4: raise error.RunError(error.IFC) return ('!', bytearray(cstr[:4]))
def value_val(ins): """ VAL: number value of a string. """ return representation.str_to_number( var.copy_str(vartypes.pass_string(parse_bracket(ins))))
def string_concat(left, right): """ Concatenate strings. """ return state.basic_state.strings.store(var.copy_str(vartypes.pass_string(left)) + var.copy_str(vartypes.pass_string(right)))