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)))
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)))
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_keep(coord)), fp.Single.zero) return vartypes.pack_int(value) elif mode == 1: _, value = screen.drawing.get_window_physical( fp.Single.zero, fp.unpack(vartypes.pass_single_keep(coord))) return vartypes.pack_int(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)
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)
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))) )
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))))
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))))
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
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
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))))
def value_rnd(ins): """ RND: get pseudorandom value. """ if util.skip_white(ins) == '(': return rnd.get_random( fp.unpack(vartypes.pass_single_keep(parse_bracket(ins)))) else: return rnd.get_random_int(1)
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)
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_keep(coord)), fp.Single.zero) return vartypes.pack_int(value) elif mode == 1: _, value = screen.drawing.get_window_physical(fp.Single.zero, fp.unpack(vartypes.pass_single_keep(coord))) return vartypes.pack_int(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)
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))) )
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))) )
def value_mks(ins): """ MKS$: return the byte representation of a single. """ return vartypes.pack_string( vartypes.pass_single_keep(parse_bracket(ins))[1])
def value_rnd(ins): """ RND: get pseudorandom value. """ if util.skip_white(ins) == '(': return rnd.get_random(fp.unpack(vartypes.pass_single_keep(parse_bracket(ins)))) else: return rnd.get_random_int(1)
def value_csng(ins): """ CSNG: convert a number to single. """ return vartypes.pass_single_keep(parse_bracket(ins))
def value_mks(ins): """ MKS$: return the byte representation of a single. """ return vartypes.pack_string(vartypes.pass_single_keep(parse_bracket(ins))[1])