예제 #1
0
def number_add(left, right):
    """ Add two numbers. """
    left, right = pass_most_precise_keep(left, right)
    if left[0] in ('#', '!'):
        return fp.pack(fp.unpack(left).iadd(fp.unpack(right)))
    else:
        return pack_int(unpack_int(left) + unpack_int(right))
예제 #2
0
def value_point(ins):
    """ POINT: get pixel attribute at screen location. """
    util.require_read(ins, ('(',))
    lst = parse_expr_list(ins, 2, err=error.STX)
    util.require_read(ins, (')',))
    if not lst[0]:
        raise error.RunError(error.STX)
    screen = state.console_state.screen
    if not lst[1]:
        # single-argument version
        try:
            x, y = screen.drawing.last_point
            fn = vartypes.pass_int_unpack(lst[0])
            if fn == 0:
                return vartypes.pack_int(x)
            elif fn == 1:
                return vartypes.pack_int(y)
            elif fn == 2:
                fx, _ = screen.drawing.get_window_logical(x, y)
                return fp.pack(fx)
            elif fn == 3:
                _, fy = screen.drawing.get_window_logical(x, y)
                return fp.pack(fy)
        except AttributeError:
            return vartypes.null['%']
    else:
        # two-argument mode
        if screen.mode.is_text_mode:
            raise error.RunError(error.IFC)
        return vartypes.pack_int(screen.drawing.point(
                        (fp.unpack(vartypes.pass_single_keep(lst[0])),
                         fp.unpack(vartypes.pass_single_keep(lst[1])), False)))
예제 #3
0
def value_point(ins):
    """ POINT: get pixel attribute at screen location. """
    util.require_read(ins, ('(', ))
    lst = parse_expr_list(ins, 2, err=error.STX)
    util.require_read(ins, (')', ))
    if not lst[0]:
        raise error.RunError(error.STX)
    screen = state.console_state.screen
    if not lst[1]:
        # single-argument version
        try:
            x, y = screen.drawing.last_point
            fn = vartypes.pass_int_unpack(lst[0])
            if fn == 0:
                return vartypes.pack_int(x)
            elif fn == 1:
                return vartypes.pack_int(y)
            elif fn == 2:
                fx, _ = screen.drawing.get_window_logical(x, y)
                return fp.pack(fx)
            elif fn == 3:
                _, fy = screen.drawing.get_window_logical(x, y)
                return fp.pack(fy)
        except AttributeError:
            return vartypes.null['%']
    else:
        # two-argument mode
        if screen.mode.is_text_mode:
            raise error.RunError(error.IFC)
        return vartypes.pack_int(
            screen.drawing.point(
                (fp.unpack(vartypes.pass_single_keep(lst[0])),
                 fp.unpack(vartypes.pass_single_keep(lst[1])), False)))
예제 #4
0
def value_point(ins):
    """ POINT: get pixel attribute at screen location. """
    util.require_read(ins, ('(', ))
    arg0 = parse_expression(ins)
    screen = state.console_state.screen
    if util.skip_white_read_if(ins, (',', )):
        # two-argument mode
        arg1 = parse_expression(ins)
        util.require_read(ins, (')', ))
        if screen.mode.is_text_mode:
            raise error.RunError(error.IFC)
        return vartypes.int_to_integer_signed(
            screen.drawing.point(
                (fp.unpack(vartypes.pass_single(arg0)),
                 fp.unpack(vartypes.pass_single(arg1)), False)))
    else:
        # single-argument mode
        util.require_read(ins, (')', ))
        try:
            x, y = screen.drawing.last_point
            fn = vartypes.pass_int_unpack(arg0)
            if fn == 0:
                return vartypes.int_to_integer_signed(x)
            elif fn == 1:
                return vartypes.int_to_integer_signed(y)
            elif fn == 2:
                fx, _ = screen.drawing.get_window_logical(x, y)
                return fp.pack(fx)
            elif fn == 3:
                _, fy = screen.drawing.get_window_logical(x, y)
                return fp.pack(fy)
        except AttributeError:
            return vartypes.null('%')
예제 #5
0
def value_pmap(ins):
    """ PMAP: convert between logical and physical coordinates. """
    util.require_read(ins, ('(', ))
    coord = parse_expression(ins)
    util.require_read(ins, (',', ))
    mode = vartypes.pass_int_unpack(parse_expression(ins))
    util.require_read(ins, (')', ))
    util.range_check(0, 3, mode)
    screen = state.console_state.screen
    if screen.mode.is_text_mode:
        return vartypes.null('%')
    if mode == 0:
        value, _ = screen.drawing.get_window_physical(
            fp.unpack(vartypes.pass_single(coord)), fp.Single.zero)
        return vartypes.int_to_integer_signed(value)
    elif mode == 1:
        _, value = screen.drawing.get_window_physical(
            fp.Single.zero, fp.unpack(vartypes.pass_single(coord)))
        return vartypes.int_to_integer_signed(value)
    elif mode == 2:
        value, _ = screen.drawing.get_window_logical(
            vartypes.pass_int_unpack(coord), 0)
        return fp.pack(value)
    elif mode == 3:
        _, value = screen.drawing.get_window_logical(
            0, vartypes.pass_int_unpack(coord))
        return fp.pack(value)
예제 #6
0
def value_to_str_keep(inp,
                      screen=False,
                      write=False,
                      allow_empty_expression=False):
    """ Convert BASIC number to BASIC string. """
    # screen=False means in a program listing
    # screen=True is used for screen, str$ and sequential files
    if not inp:
        if allow_empty_expression:
            return ('$', '')
        else:
            raise error.RunError(error.STX)
    typechar = inp[0]
    if typechar == '$':
        return ('$', inp[1])
    elif typechar == '%':
        if screen and not write and vartypes.unpack_int(inp) >= 0:
            return ('$', ' ' + str(vartypes.unpack_int(inp)))
        else:
            return ('$', str(vartypes.unpack_int(inp)))
    elif typechar == '!':
        return ('$', float_to_str(fp.unpack(inp), screen, write))
    elif typechar == '#':
        return ('$', float_to_str(fp.unpack(inp), screen, write))
    else:
        raise error.RunError(error.STX)
예제 #7
0
def value_point(ins):
    """ POINT: get pixel attribute at screen location. """
    util.require_read(ins, ('(',))
    arg0 = parse_expression(ins)
    screen = state.console_state.screen
    if util.skip_white_read_if(ins, (',',)):
        # two-argument mode
        arg1 = parse_expression(ins)
        util.require_read(ins, (')',))
        if screen.mode.is_text_mode:
            raise error.RunError(error.IFC)
        return vartypes.int_to_integer_signed(screen.drawing.point(
                        (fp.unpack(vartypes.pass_single(arg0)),
                         fp.unpack(vartypes.pass_single(arg1)), False)))
    else:
        # single-argument mode
        util.require_read(ins, (')',))
        try:
            x, y = screen.drawing.last_point
            fn = vartypes.pass_int_unpack(arg0)
            if fn == 0:
                return vartypes.int_to_integer_signed(x)
            elif fn == 1:
                return vartypes.int_to_integer_signed(y)
            elif fn == 2:
                fx, _ = screen.drawing.get_window_logical(x, y)
                return fp.pack(fx)
            elif fn == 3:
                _, fy = screen.drawing.get_window_logical(x, y)
                return fp.pack(fy)
        except AttributeError:
            return vartypes.null('%')
예제 #8
0
def value_operator(op, left, right):
    """ Get value of binary operator expression. """
    if op == tk.O_CARET:
        return vcaret(left, right)
    elif op == tk.O_TIMES:
        return vtimes(left, right)
    elif op == tk.O_DIV:
        return vdiv(left, right)
    elif op == tk.O_INTDIV:
        return fp.pack(
            fp.div(
                fp.unpack(vartypes.pass_single_keep(left)).ifloor(),
                fp.unpack(vartypes.pass_single_keep(
                    right)).ifloor()).apply_carry().ifloor())
    elif op == tk.MOD:
        numerator = vartypes.pass_int_unpack(right)
        if numerator == 0:
            # simulate division by zero
            return fp.pack(
                fp.div(
                    fp.unpack(vartypes.pass_single_keep(left)).ifloor(),
                    fp.unpack(
                        vartypes.pass_single_keep(right)).ifloor()).ifloor())
        return vartypes.pack_int(vartypes.pass_int_unpack(left) % numerator)
    elif op == tk.O_PLUS:
        return vplus(left, right)
    elif op == tk.O_MINUS:
        return vartypes.number_add(left, vartypes.number_neg(right))
    elif op == tk.O_GT:
        return vartypes.bool_to_int_keep(vartypes.gt(left, right))
    elif op == tk.O_EQ:
        return vartypes.bool_to_int_keep(vartypes.equals(left, right))
    elif op == tk.O_LT:
        return vartypes.bool_to_int_keep(not (
            vartypes.gt(left, right) or vartypes.equals(left, right)))
    elif op == tk.O_GT + tk.O_EQ:
        return vartypes.bool_to_int_keep(
            vartypes.gt(left, right) or vartypes.equals(left, right))
    elif op == tk.O_LT + tk.O_EQ:
        return vartypes.bool_to_int_keep(not vartypes.gt(left, right))
    elif op == tk.O_LT + tk.O_GT:
        return vartypes.bool_to_int_keep(not vartypes.equals(left, right))
    elif op == tk.AND:
        return vartypes.twoscomp_to_int(
            vartypes.pass_twoscomp(left) & vartypes.pass_twoscomp(right))
    elif op == tk.OR:
        return vartypes.twoscomp_to_int(
            vartypes.pass_twoscomp(left) | vartypes.pass_twoscomp(right))
    elif op == tk.XOR:
        return vartypes.twoscomp_to_int(
            vartypes.pass_twoscomp(left) ^ vartypes.pass_twoscomp(right))
    elif op == tk.EQV:
        return vartypes.twoscomp_to_int(~(vartypes.pass_twoscomp(left)
                                          ^ vartypes.pass_twoscomp(right)))
    elif op == tk.IMP:
        return vartypes.twoscomp_to_int((~vartypes.pass_twoscomp(left))
                                        | vartypes.pass_twoscomp(right))
    else:
        raise error.RunError(error.STX)
예제 #9
0
def number_power(left, right):
    """ Left^right. """
    if (left[0] == '#' or right[0] == '#') and vartypes.option_double:
        return fp.pack( fp.power(fp.unpack(vartypes.pass_double(left)), fp.unpack(vartypes.pass_double(right))) )
    else:
        if right[0] == '%':
            return fp.pack( fp.unpack(vartypes.pass_single(left)).ipow_int(vartypes.integer_to_int_signed(right)) )
        else:
            return fp.pack( fp.power(fp.unpack(vartypes.pass_single(left)), fp.unpack(vartypes.pass_single(right))) )
예제 #10
0
def vcaret(left, right):
    """ Left^right. """
    if (left[0] == '#' or right[0] == '#') and option_double:
        return fp.pack( fp.power(fp.unpack(vartypes.pass_double_keep(left)), fp.unpack(vartypes.pass_double_keep(right))) )
    else:
        if right[0] == '%':
            return fp.pack( fp.unpack(vartypes.pass_single_keep(left)).ipow_int(vartypes.unpack_int(right)) )
        else:
            return fp.pack( fp.power(fp.unpack(vartypes.pass_single_keep(left)), fp.unpack(vartypes.pass_single_keep(right))) )
예제 #11
0
def number_add(left, right):
    """ Add two numbers. """
    left, right = vartypes.pass_most_precise(left, right)
    if left[0] in ('#', '!'):
        return fp.pack(fp.unpack(left).iadd(fp.unpack(right)))
    else:
        # return Single to avoid wrapping on integer overflow
        return fp.pack(fp.Single.from_int(vartypes.integer_to_int_signed(left) +
                            vartypes.integer_to_int_signed(right)))
예제 #12
0
def value_fix(ins):
    """ FIX: round towards zero. """
    inp = vartypes.pass_number(parse_bracket(ins))
    if inp[0] == '%':
        return inp
    elif inp[0] == '!':
        # needs to be a float to avoid overflow
        return fp.pack(fp.Single.from_int(fp.unpack(inp).trunc_to_int()))
    elif inp[0] == '#':
        return fp.pack(fp.Double.from_int(fp.unpack(inp).trunc_to_int()))
예제 #13
0
def vtimes(left, right):
    """ Left*right. """
    if left[0] == '#' or right[0] == '#':
        return fp.pack(
            fp.unpack(vartypes.pass_double_keep(left)).imul(
                fp.unpack(vartypes.pass_double_keep(right))))
    else:
        return fp.pack(
            fp.unpack(vartypes.pass_single_keep(left)).imul(
                fp.unpack(vartypes.pass_single_keep(right))))
예제 #14
0
def vdiv(left, right):
    """ Left/right. """
    if left[0] == '#' or right[0] == '#':
        return fp.pack(
            fp.div(fp.unpack(vartypes.pass_double_keep(left)),
                   fp.unpack(vartypes.pass_double_keep(right))))
    else:
        return fp.pack(
            fp.div(fp.unpack(vartypes.pass_single_keep(left)),
                   fp.unpack(vartypes.pass_single_keep(right))))
예제 #15
0
def equals(left,right):
    """ Return whether two numbers are equal. """
    if left[0] == '$':
        return pass_string_unpack(left) == pass_string_unpack(right)
    else:
        left, right = pass_most_precise_keep(left, right)
        if left[0] in ('#', '!'):
            return fp.unpack(left).equals(fp.unpack(right))
        else:
            return unpack_int(left)==unpack_int(right)
예제 #16
0
def gt(left, right):
    """ Number ordering: return whether left > right. """
    if left[0] == '$':
        return str_gt(pass_string_unpack(left), pass_string_unpack(right))
    else:
        left, right = pass_most_precise_keep(left, right)
        if left[0] in ('#', '!'):
            return fp.unpack(left).gt(fp.unpack(right))
        else:
            return unpack_int(left) > unpack_int(right)
예제 #17
0
def value_fix(ins):
    """ FIX: round towards zero. """
    inp = vartypes.pass_number(parse_bracket(ins))
    if inp[0] == '%':
        return inp
    elif inp[0] == '!':
        # needs to be a float to avoid overflow
        return fp.pack(fp.Single.from_int(fp.unpack(inp).trunc_to_int()))
    elif inp[0] == '#':
        return fp.pack(fp.Double.from_int(fp.unpack(inp).trunc_to_int()))
예제 #18
0
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)
예제 #19
0
파일: graphics.py 프로젝트: boriel/pcbasic
 def circle(self, lcoord, r, start, stop, c, aspect):
     """ Draw a circle, ellipse, arc or sector (CIRCLE). """
     x0, y0 = self.view_coords(*self.get_window_physical(*lcoord))
     c = self.get_attr_index(c)
     if aspect == None:
         aspect = fp.div(
             fp.Single.from_int(self.screen.mode.pixel_aspect[0]),
             fp.Single.from_int(self.screen.mode.pixel_aspect[1]),
         )
     if aspect.equals(aspect.one):
         rx, _ = self.get_window_scale(r, fp.Single.zero)
         ry = rx
     elif aspect.gt(aspect.one):
         _, ry = self.get_window_scale(fp.Single.zero, r)
         rx = fp.div(r, aspect).round_to_int()
     else:
         rx, _ = self.get_window_scale(r, fp.Single.zero)
         ry = fp.mul(r, aspect).round_to_int()
     start_octant, start_coord, start_line = -1, -1, False
     if start:
         start = fp.unpack(vartypes.pass_single_keep(start))
         start_octant, start_coord, start_line = get_octant(start, rx, ry)
     stop_octant, stop_coord, stop_line = -1, -1, False
     if stop:
         stop = fp.unpack(vartypes.pass_single_keep(stop))
         stop_octant, stop_coord, stop_line = get_octant(stop, rx, ry)
     if aspect.equals(aspect.one):
         self.draw_circle(x0, y0, rx, c, start_octant, start_coord, start_line, stop_octant, stop_coord, stop_line)
     else:
         startx, starty, stopx, stopy = -1, -1, -1, -1
         if start != None:
             startx = abs(fp.mul(fp.Single.from_int(rx), fp.cos(start)).round_to_int())
             starty = abs(fp.mul(fp.Single.from_int(ry), fp.sin(start)).round_to_int())
         if stop != None:
             stopx = abs(fp.mul(fp.Single.from_int(rx), fp.cos(stop)).round_to_int())
             stopy = abs(fp.mul(fp.Single.from_int(ry), fp.sin(stop)).round_to_int())
         self.draw_ellipse(
             x0,
             y0,
             rx,
             ry,
             c,
             start_octant / 2,
             startx,
             starty,
             start_line,
             stop_octant / 2,
             stopx,
             stopy,
             stop_line,
         )
     self.last_attr = c
     self.last_point = x0, y0
예제 #20
0
파일: graphics.py 프로젝트: nony05/pcbasic
 def circle(self, lcoord, r, start, stop, c, aspect):
     """ Draw a circle, ellipse, arc or sector (CIRCLE). """
     x0, y0 = self.view_coords(*self.get_window_physical(*lcoord))
     c = self.get_attr_index(c)
     if aspect is None:
         aspect = fp.div(
             fp.Single.from_int(self.screen.mode.pixel_aspect[0]),
             fp.Single.from_int(self.screen.mode.pixel_aspect[1]))
     if aspect.equals(aspect.one):
         rx, _ = self.get_window_scale(r, fp.Single.zero)
         ry = rx
     elif aspect.gt(aspect.one):
         _, ry = self.get_window_scale(fp.Single.zero, r)
         rx = fp.div(r, aspect).round_to_int()
     else:
         rx, _ = self.get_window_scale(r, fp.Single.zero)
         ry = fp.mul(r, aspect).round_to_int()
     start_octant, start_coord, start_line = -1, -1, False
     if start:
         start = fp.unpack(vartypes.pass_single_keep(start))
         start_octant, start_coord, start_line = get_octant(start, rx, ry)
     stop_octant, stop_coord, stop_line = -1, -1, False
     if stop:
         stop = fp.unpack(vartypes.pass_single_keep(stop))
         stop_octant, stop_coord, stop_line = get_octant(stop, rx, ry)
     if aspect.equals(aspect.one):
         self.draw_circle(x0, y0, rx, c, start_octant, start_coord,
                          start_line, stop_octant, stop_coord, stop_line)
     else:
         startx, starty, stopx, stopy = -1, -1, -1, -1
         if start is not None:
             startx = abs(
                 fp.mul(fp.Single.from_int(rx),
                        fp.cos(start)).round_to_int())
             starty = abs(
                 fp.mul(fp.Single.from_int(ry),
                        fp.sin(start)).round_to_int())
         if stop is not None:
             stopx = abs(
                 fp.mul(fp.Single.from_int(rx),
                        fp.cos(stop)).round_to_int())
             stopy = abs(
                 fp.mul(fp.Single.from_int(ry),
                        fp.sin(stop)).round_to_int())
         self.draw_ellipse(x0, y0, rx, ry, c, start_octant / 2, startx,
                           starty, start_line, stop_octant / 2, stopx,
                           stopy, stop_line)
     self.last_attr = c
     self.last_point = x0, y0
예제 #21
0
def vcaret(left, right):
    """ Left^right. """
    if (left[0] == '#' or right[0] == '#') and option_double:
        return fp.pack(
            fp.power(fp.unpack(vartypes.pass_double_keep(left)),
                     fp.unpack(vartypes.pass_double_keep(right))))
    else:
        if right[0] == '%':
            return fp.pack(
                fp.unpack(vartypes.pass_single_keep(left)).ipow_int(
                    vartypes.unpack_int(right)))
        else:
            return fp.pack(
                fp.power(fp.unpack(vartypes.pass_single_keep(left)),
                         fp.unpack(vartypes.pass_single_keep(right))))
예제 #22
0
def value_rnd(ins):
    """ RND: get pseudorandom value. """
    if util.skip_white(ins) == '(':
        return rnd.get_random(
            fp.unpack(vartypes.pass_single(parse_bracket(ins))))
    else:
        return rnd.get_random_int(1)
예제 #23
0
def value_func(ins, fn):
    """ Return value of unary math function. """
    return fp.pack(
        fn(
            fp.unpack(
                vartypes.pass_float(parse_bracket(ins),
                                    vartypes.option_double))))
예제 #24
0
def value_operator(op, left, right):
    """ Get value of binary operator expression. """
    if op == tk.O_CARET:
        return vcaret(left, right)
    elif op == tk.O_TIMES:
        return vtimes(left, right)
    elif op == tk.O_DIV:
        return vdiv(left, right)
    elif op == tk.O_INTDIV:
        return fp.pack(fp.div(fp.unpack(vartypes.pass_single_keep(left)).ifloor(),
                fp.unpack(vartypes.pass_single_keep(right)).ifloor()).apply_carry().ifloor())
    elif op == tk.MOD:
        numerator = vartypes.pass_int_unpack(right)
        if numerator == 0:
            # simulate division by zero
            return fp.pack(fp.div(fp.unpack(vartypes.pass_single_keep(left)).ifloor(),
                    fp.unpack(vartypes.pass_single_keep(right)).ifloor()).ifloor())
        return vartypes.pack_int(vartypes.pass_int_unpack(left) % numerator)
    elif op == tk.O_PLUS:
        return vplus(left, right)
    elif op == tk.O_MINUS:
        return vartypes.number_add(left, vartypes.number_neg(right))
    elif op == tk.O_GT:
        return vartypes.bool_to_int_keep(vartypes.gt(left,right))
    elif op == tk.O_EQ:
        return vartypes.bool_to_int_keep(vartypes.equals(left, right))
    elif op == tk.O_LT:
        return vartypes.bool_to_int_keep(not(vartypes.gt(left,right) or vartypes.equals(left, right)))
    elif op == tk.O_GT + tk.O_EQ:
        return vartypes.bool_to_int_keep(vartypes.gt(left,right) or vartypes.equals(left, right))
    elif op == tk.O_LT + tk.O_EQ:
        return vartypes.bool_to_int_keep(not vartypes.gt(left,right))
    elif op == tk.O_LT + tk.O_GT:
        return vartypes.bool_to_int_keep(not vartypes.equals(left, right))
    elif op == tk.AND:
        return vartypes.twoscomp_to_int( vartypes.pass_twoscomp(left) & vartypes.pass_twoscomp(right) )
    elif op == tk.OR:
        return vartypes.twoscomp_to_int( vartypes.pass_twoscomp(left) | vartypes.pass_twoscomp(right) )
    elif op == tk.XOR:
        return vartypes.twoscomp_to_int( vartypes.pass_twoscomp(left) ^ vartypes.pass_twoscomp(right) )
    elif op == tk.EQV:
        return vartypes.twoscomp_to_int( ~(vartypes.pass_twoscomp(left) ^ vartypes.pass_twoscomp(right)) )
    elif op == tk.IMP:
        return vartypes.twoscomp_to_int( (~vartypes.pass_twoscomp(left)) | vartypes.pass_twoscomp(right) )
    else:
        raise error.RunError(error.STX)
예제 #25
0
def value_sgn(ins):
    """ SGN: get sign. """
    inp = vartypes.pass_number(parse_bracket(ins))
    if inp[0] == '%':
        inp_int = vartypes.integer_to_int_signed(inp)
        return vartypes.int_to_integer_signed(0 if inp_int==0 else (1 if inp_int > 0 else -1))
    else:
        return vartypes.int_to_integer_signed(fp.unpack(inp).sign())
예제 #26
0
def value_sgn(ins):
    """ SGN: get sign. """
    inp = vartypes.pass_number(parse_bracket(ins))
    if inp[0] == '%':
        inp_int = vartypes.integer_to_int_signed(inp)
        return vartypes.int_to_integer_signed(0 if inp_int == 0 else (
            1 if inp_int > 0 else -1))
    else:
        return vartypes.int_to_integer_signed(fp.unpack(inp).sign())
예제 #27
0
def number_to_str(inp, screen=False, write=False, allow_empty_expression=False):
    """ Convert BASIC number to Python str. """
    # screen=False means in a program listing
    # screen=True is used for screen, str$ and sequential files
    if not inp:
        if allow_empty_expression:
            return ''
        else:
            raise error.RunError(error.STX)
    typechar = inp[0]
    if typechar == '%':
        if screen and not write and vartypes.integer_to_int_signed(inp) >= 0:
            return ' ' + str(vartypes.integer_to_int_signed(inp))
        else:
            return str(vartypes.integer_to_int_signed(inp))
    elif typechar == '!':
        return float_to_str(fp.unpack(inp), screen, write)
    elif typechar == '#':
        return float_to_str(fp.unpack(inp), screen, write)
    else:
        raise ValueError('Number operation on string')
예제 #28
0
def number_sgn(inp):
    """ Return the sign of a number. """
    if inp[0] == '%':
        i = vartypes.integer_to_int_signed(inp)
        if i > 0:
            return vartypes.int_to_integer_signed(1)
        elif i < 0:
            return vartypes.int_to_integer_signed(-1)
        else:
            return vartypes.int_to_integer_signed(0)
    elif inp[0] in ('!', '#'):
        return vartypes.int_to_integer_signed(fp.unpack(inp).sign())
    return inp
예제 #29
0
def number_sgn(inp):
    """ Return the sign of a number. """
    if inp[0] == '%':
        i = unpack_int(inp)
        if i > 0:
            return pack_int(1)
        elif i < 0:
            return pack_int(-1)
        else:
            return pack_int(0)
    elif inp[0] in ('!', '#'):
        return pack_int(fp.unpack(inp).sign())
    return inp
예제 #30
0
파일: vartypes.py 프로젝트: nony05/pcbasic
def pass_single_keep(num):
    """ Check if variable is numeric, convert to Single. """
    if not num:
        raise error.RunError(error.STX)
    typechar = num[0]
    if typechar == '!':
        return num
    elif typechar == '%':
        return fp.pack(fp.Single.from_int(unpack_int(num)))
    elif typechar == '#':
        # *round* to single
        return fp.pack(fp.unpack(num).round_to_single())
    elif typechar == '$':
        raise error.RunError(error.TYPE_MISMATCH)
예제 #31
0
def value_to_str_keep(inp, screen=False, write=False, allow_empty_expression=False):
    """ Convert BASIC number to BASIC string. """
    # screen=False means in a program listing
    # screen=True is used for screen, str$ and sequential files
    if not inp:
        if allow_empty_expression:
            return ('$', '')
        else:
            raise error.RunError(2)    
    typechar = inp[0]
    if typechar == '$':
        return ('$', inp[1])
    elif typechar == '%':
        if screen and not write and vartypes.unpack_int(inp) >= 0:
            return ('$', ' '+ int_to_str(vartypes.unpack_int(inp)) )
        else:
            return ('$', int_to_str(vartypes.unpack_int(inp)))
    elif typechar == '!':
        return ('$', float_to_str(fp.unpack(inp), screen, write) )
    elif typechar == '#':
        return ('$', float_to_str(fp.unpack(inp), screen, write) )
    else:
        raise error.RunError(2)    
예제 #32
0
def pass_single(num):
    """ Check if variable is numeric, convert to Single. """
    if not num:
        raise error.RunError(error.STX)
    typechar = num[0]
    if typechar == '!':
        return num
    elif typechar == '%':
        return fp.pack(fp.Single.from_int(integer_to_int_signed(num)))
    elif typechar == '#':
        # *round* to single
        return fp.pack(fp.unpack(num).round_to_single())
    elif typechar == '$':
        raise error.RunError(error.TYPE_MISMATCH)
예제 #33
0
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)
예제 #34
0
def value_pmap(ins):
    """ PMAP: convert between logical and physical coordinates. """
    util.require_read(ins, ('(',))
    coord = parse_expression(ins)
    util.require_read(ins, (',',))
    mode = vartypes.pass_int_unpack(parse_expression(ins))
    util.require_read(ins, (')',))
    util.range_check(0, 3, mode)
    screen = state.console_state.screen
    if screen.mode.is_text_mode:
        return vartypes.null('%')
    if mode == 0:
        value, _ = screen.drawing.get_window_physical(fp.unpack(vartypes.pass_single(coord)), fp.Single.zero)
        return vartypes.int_to_integer_signed(value)
    elif mode == 1:
        _, value = screen.drawing.get_window_physical(fp.Single.zero, fp.unpack(vartypes.pass_single(coord)))
        return vartypes.int_to_integer_signed(value)
    elif mode == 2:
        value, _ = screen.drawing.get_window_logical(vartypes.pass_int_unpack(coord), 0)
        return fp.pack(value)
    elif mode == 3:
        _, value = screen.drawing.get_window_logical(0, vartypes.pass_int_unpack(coord))
        return fp.pack(value)
예제 #35
0
def number_to_str(inp,
                  screen=False,
                  write=False,
                  allow_empty_expression=False):
    """ Convert BASIC number to Python str. """
    # screen=False means in a program listing
    # screen=True is used for screen, str$ and sequential files
    if not inp:
        if allow_empty_expression:
            return ''
        else:
            raise error.RunError(error.STX)
    typechar = inp[0]
    if typechar == '%':
        if screen and not write and vartypes.integer_to_int_signed(inp) >= 0:
            return ' ' + str(vartypes.integer_to_int_signed(inp))
        else:
            return str(vartypes.integer_to_int_signed(inp))
    elif typechar == '!':
        return float_to_str(fp.unpack(inp), screen, write)
    elif typechar == '#':
        return float_to_str(fp.unpack(inp), screen, write)
    else:
        raise ValueError('Number operation on string')
예제 #36
0
파일: vartypes.py 프로젝트: nony05/pcbasic
def pass_int_keep(inp, maxint=0x7fff, err=error.TYPE_MISMATCH):
    """ Check if variable is numeric, convert to Int. """
    if not inp:
        raise error.RunError(error.STX)
    typechar = inp[0]
    if typechar == '%':
        return inp
    elif typechar in ('!', '#'):
        val = fp.unpack(inp).round_to_int()
        if val > maxint or val < -0x8000:
            # overflow
            raise error.RunError(error.OVERFLOW)
        return pack_int(val)
    else:
        # type mismatch
        raise error.RunError(err)
예제 #37
0
def pass_integer(inp, maxint=0x7fff, err=error.TYPE_MISMATCH):
    """ Check if variable is numeric, convert to Int. """
    if not inp:
        raise error.RunError(error.STX)
    typechar = inp[0]
    if typechar == '%':
        return inp
    elif typechar in ('!', '#'):
        val = fp.unpack(inp).round_to_int()
        if val > maxint or val < -0x8000:
            # overflow
            raise error.RunError(error.OVERFLOW)
        return int_to_integer_unsigned(val)
    else:
        # type mismatch
        raise error.RunError(err)
예제 #38
0
def format_number(value, tokens, digits_before, decimals):
    """ Format a number to a format string. For PRINT USING. """
    # illegal function call if too many digits
    if digits_before + decimals > 24:
        raise error.RunError(error.IFC)
    # extract sign, mantissa, exponent
    value = unpack(value)
    # dollar sign, decimal point
    has_dollar, force_dot = '$' in tokens, '.' in tokens
    # leading sign, if any
    valstr, post_sign = '', ''
    if tokens[0] == '+':
        valstr += '-' if value.neg else '+'
    elif tokens[-1] == '+':
        post_sign = '-' if value.neg else '+'
    elif tokens[-1] == '-':
        post_sign = '-' if value.neg else ' '
    else:
        valstr += '-' if value.neg else ''
        # reserve space for sign in scientific notation by taking away a digit position
        if not has_dollar:
            digits_before -= 1
            if digits_before < 0:
                digits_before = 0
            # just one of those things GW does
            #if force_dot and digits_before == 0 and decimals != 0:
            #    valstr += '0'
    # take absolute value
    value.neg = False
    # currency sign, if any
    valstr += '$' if has_dollar else ''
    # format to string
    if '^' in tokens:
        valstr += format_float_scientific(value, digits_before, decimals,
                                          force_dot)
    else:
        valstr += format_float_fixed(value, decimals, force_dot)
    # trailing signs, if any
    valstr += post_sign
    if len(valstr) > len(tokens):
        valstr = '%' + valstr
    else:
        # filler
        valstr = ('*' if '*' in tokens else ' ') * (len(tokens) -
                                                    len(valstr)) + valstr
    return valstr
예제 #39
0
def format_number(value, tokens, digits_before, decimals):
    """ Format a number to a format string. For PRINT USING. """
    # illegal function call if too many digits
    if digits_before + decimals > 24:
        raise error.RunError(error.IFC)
    # extract sign, mantissa, exponent
    value = unpack(value)
    # dollar sign, decimal point
    has_dollar, force_dot = '$' in tokens, '.' in tokens
    # leading sign, if any
    valstr, post_sign = '', ''
    if tokens[0] == '+':
        valstr += '-' if value.neg else '+'
    elif tokens[-1] == '+':
        post_sign = '-' if value.neg else '+'
    elif tokens[-1] == '-':
        post_sign = '-' if value.neg else ' '
    else:
        valstr += '-' if value.neg else ''
        # reserve space for sign in scientific notation by taking away a digit position
        if not has_dollar:
            digits_before -= 1
            if digits_before < 0:
                digits_before = 0
            # just one of those things GW does
            #if force_dot and digits_before == 0 and decimals != 0:
            #    valstr += '0'
    # take absolute value
    value.neg = False
    # currency sign, if any
    valstr += '$' if has_dollar else ''
    # format to string
    if '^' in tokens:
        valstr += format_float_scientific(value, digits_before, decimals, force_dot)
    else:
        valstr += format_float_fixed(value, decimals, force_dot)
    # trailing signs, if any
    valstr += post_sign
    if len(valstr) > len(tokens):
        valstr = '%' + valstr
    else:
        # filler
        valstr = ('*' if '*' in tokens else ' ') * (len(tokens) - len(valstr)) + valstr
    return valstr
예제 #40
0
def number_divide(left, right):
    """ Left/right. """
    if left[0] == '#' or right[0] == '#':
        return fp.pack( fp.div(fp.unpack(vartypes.pass_double(left)), fp.unpack(vartypes.pass_double(right))) )
    else:
        return fp.pack( fp.div(fp.unpack(vartypes.pass_single(left)), fp.unpack(vartypes.pass_single(right))) )
예제 #41
0
def value_int(ins):
    """ INT: get floor value. """
    inp = vartypes.pass_number(parse_bracket(ins))
    return inp if inp[0] == '%' else fp.pack(fp.unpack(inp).ifloor())
예제 #42
0
def vtimes(left, right):
    """ Left*right. """
    if left[0] == '#' or right[0] == '#':
        return fp.pack( fp.unpack(vartypes.pass_double_keep(left)).imul(fp.unpack(vartypes.pass_double_keep(right))) )
    else:
        return fp.pack( fp.unpack(vartypes.pass_single_keep(left)).imul(fp.unpack(vartypes.pass_single_keep(right))) )
예제 #43
0
def value_rnd(ins):
    """ RND: get pseudorandom value. """
    if util.skip_white(ins) == '(':
        return rnd.get_random(fp.unpack(vartypes.pass_single(parse_bracket(ins))))
    else:
        return rnd.get_random_int(1)
예제 #44
0
def value_func(ins, fn):
    """ Return value of unary math function. """
    return fp.pack(fn(fp.unpack(vartypes.pass_float(parse_bracket(ins), vartypes.option_double))))
예제 #45
0
파일: flow.py 프로젝트: Yungzuck/pcbasic
def number_unpack(value):
    """ Unpack a number value. """
    if value[0] in ('#', '!'):
        return fp.unpack(value)
    else:
        return vartypes.integer_to_int_signed(value)
예제 #46
0
def vdiv(left, right):
    """ Left/right. """
    if left[0] == '#' or right[0] == '#':
        return fp.pack( fp.div(fp.unpack(vartypes.pass_double_keep(left)), fp.unpack(vartypes.pass_double_keep(right))) )
    else:
        return fp.pack( fp.div(fp.unpack(vartypes.pass_single_keep(left)), fp.unpack(vartypes.pass_single_keep(right))) )
예제 #47
0
def value_int(ins):
    """ INT: get floor value. """
    inp = vartypes.pass_number(parse_bracket(ins))
    return inp if inp[0] == '%' else fp.pack(fp.unpack(inp).ifloor())
예제 #48
0
파일: flow.py 프로젝트: Yungzuck/pcbasic
def number_unpack(value):
    """ Unpack a number value. """
    if value[0] in ('#', '!'):
        return fp.unpack(value)
    else:
        return vartypes.integer_to_int_signed(value)
예제 #49
0
파일: flow.py 프로젝트: nony05/pcbasic
def number_unpack(value):
    """ Unpack a number value. """
    if value[0] in ('#', '!'):
        return fp.unpack(value)
    else:
        return vartypes.unpack_int(value)