Add /deps.sh, in /linapple remove full-screen mode to make it run properly on recent...
[applesoft_basic.git] / data_types.py
1 import math
2 import re
3
4 # note: python 3 returns int type from math.floor(), I don't really
5 # like this, but I rely on it below to avoid needing explicit int()
6
7 def cint(value):
8   # should check for illegal quantity error here?
9   # real applesoft seems to allow up to 63999, but it's not really
10   # clear under what circumstances it should be treated as unsigned
11   assert isinstance(value, float)
12   return ((math.floor(value) + 0x8000) & 0xffff) - 0x8000
13
14 def str_dollar(context, value):
15   assert isinstance(value, float)
16   sign = ''
17   if value < 0.:
18     sign = '-'
19     value = -value
20
21   if value == 0.:
22     value = '0.'
23     exponent = ''
24   else:
25     exponent = math.floor(math.log10(value))
26     if exponent < -99:
27       value = '0.'
28       exponent = ''
29     else:
30       if exponent >= 100:
31         raise Exception(
32           f'?OVERFLOW ERROR IN {context.line_number():d}'
33         )
34       value *= 10. ** (8 - exponent)
35
36       int_value = int(round(value))
37       assert int_value >= 100000000
38       if int_value >= 1000000000:
39         value /= 10.
40         exponent += 1
41         if exponent >= 100:
42           raise Exception(
43             f'?OVERFLOW ERROR IN {context.line_number():d}'
44           )
45         int_value = int(round(value))
46         assert int_value >= 100000000 and int_value < 1000000000
47
48       value = str(int_value)
49       if exponent >= -2 and exponent < 9:
50         exponent += 1
51         if exponent < 0:
52           value = '0' * -exponent + value
53           exponent = 0
54         value = value[:exponent] + '.' + value[exponent:]
55         exponent = ''
56       else:
57         value = value[:1] + '.' + value[1:]
58         exponent_sign = '+'
59         if exponent < 0:
60           exponent_sign = '-'
61           exponent = -exponent
62         exponent = 'E' + exponent_sign + ('0' + str(exponent))[-2:]
63
64   i = len(value) - 1
65   while value[i] == '0':
66     i -= 1
67   if value[i] != '.':
68     i += 1
69   return sign + value[:i] + exponent
70
71 # (\ *[+-])?            1
72 # (                     2
73 #   (                   3
74 #     (\ *[0-9]*)*      4
75 #   )
76 #   \ *\.
77 #   (                   5
78 #     (\ *[0-9])*       6
79 #   )
80 #   |
81 #   (                   7
82 #     (\ *[0-9])+       8
83 #   )
84 # )
85 # (                     9
86 #   \ *E
87 #   (\ *[+-])?          10
88 #   \ *
89 #   (                   11
90 #     (\ *[0-9])+       12
91 #   )
92 # )?
93 re_val = re.compile(
94   '(\ *[+-])?(((\ *[0-9]*)*)\ *\.((\ *[0-9])*)|((\ *[0-9])+))(\ *E(\ *[+-])?\ *((\ *[0-9])+))?'
95 )
96 def val(value):
97   match = re_val.match(value)
98   if match is None:
99     return 0, 0.
100   sign = (match.group(1) or '').replace(' ', '')
101   integer = (match.group(3) or match.group(7) or '').replace(' ', '')
102   fraction = (match.group(5) or '').replace(' ', '')
103   exp = 0
104   if match.group(9) is not None:
105     exp_sign = (match.group(10) or '').replace(' ', '')
106     exp = int(match.group(11).replace(' ', ''))
107     if exp_sign == '-':
108       exp = -exp
109   result = int(integer + fraction) * 10. ** (exp - len(fraction))
110   if sign == '-':
111     result = -result
112   return len(match.group(0)), result