nga-python: add decimal io device (#32)

FossilOrigin-Name: 4a0a1184f66f855840fa7229013d6b4b68026584dfc72906f3e4994fd346f3f6
This commit is contained in:
crc 2021-01-25 15:43:05 +00:00
parent 71a3eb4c31
commit 77b2ccc463
4 changed files with 227 additions and 8 deletions

100
interface/decimal.retro Normal file
View file

@ -0,0 +1,100 @@
# Decimal Numbers
~~~
{{
'DPU var
:identify
@DPU n:zero? 0; drop
#20 io:scan-for dup n:negative?
[ drop 'IO_DEVICE_TYPE_0020_NOT_FOUND s:put nl ]
[ !DPU ] choose ;
---reveal---
:decimal:operation identify @DPU io:invoke ;
}}
~~~
~~~
:n:to-decimal (n-_dec:-n) #0 decimal:operation ;
:s:to-decimal (s-_dec:-n) #1 decimal:operation ;
:dec:to-number (dec:a-__-n) #2 decimal:operation ;
:dec:to-string (dec:n-__-s) s:empty dup #3 decimal:operation ;
:dec:+ (dec:ab-c) #4 decimal:operation ;
:dec:- (dec:ab-c) #5 decimal:operation ;
:dec:* (dec:ab-c) #6 decimal:operation ;
:dec:/ (dec:ab-c) #7 decimal:operation ;
:dec:floor (dec:ab-c) #8 decimal:operation ;
:dec:ceiling (dec:f-f) #9 decimal:operation ;
:dec:sqrt (dec:f-f) #10 decimal:operation ;
:dec:eq? (dec:ab-c) #11 decimal:operation ;
:dec:-eq? (dec:ab-c) #12 decimal:operation ;
:dec:lt? (dec:ab-c) #13 decimal:operation ;
:dec:gt? (dec:ab-c) #14 decimal:operation ;
:dec:depth (-n) #15 decimal:operation ;
:dec:dup (dec:a-aa) #16 decimal:operation ;
:dec:drop (dec:a-) #17 decimal:operation ;
:dec:swap (dec:ab-ba) #18 decimal:operation ;
:dec:log (dec:ab-c) #19 decimal:operation ;
:dec:power (dec:ab-c) #20 decimal:operation ;
:dec:sin (dec:f-f) #21 decimal:operation ;
:dec:cos (dec:f-f) #22 decimal:operation ;
:dec:tan (dec:f-f) #23 decimal:operation ;
:dec:asin (dec:f-f) #24 decimal:operation ;
:dec:acos (dec:f-f) #25 decimal:operation ;
:dec:atan (dec:f-f) #26 decimal:operation ;
:dec:push (dec:f-) #27 decimal:operation ;
:dec:pop (dec:-f) #28 decimal:operation ;
:dec:adepth (-n) #29 decimal:operation ;
~~~
Above this, additional functions are defined. First are words
to aid in structuring the floating point stack.
~~~
:dec:over (dec:ab-aba) dec:push dec:dup dec:pop dec:swap ;
:dec:tuck (dec:ab-bab) dec:dup dec:push dec:swap dec:pop ;
:dec:nip (dec:ab-b) dec:swap dec:drop ;
:dec:drop-pair (dec:ab-) dec:drop dec:drop ;
:dec:dup-pair (dec:ab-abab) dec:over dec:over ;
:dec:rot (dec:abc-bca) dec:push dec:swap dec:pop dec:swap ;
~~~
Then a word to allow creation of floating point values via a
`,` prefix.
~~~
:prefix:, (s-__dec:-a)
compiling? &s:keep &s:temp choose &s:to-decimal class:word ; immediate
~~~
~~~
:dec:square (dec:n-m) dec:dup dec:* ;
:dec:positive? (-f__dec:a-) #0 n:to-decimal dec:gt? ;
:dec:negative? (-f__dec:a-) #0 n:to-decimal dec:lt? ;
:dec:negate (dec:a-b) #-1 n:to-decimal dec:* ;
:dec:abs (dec:a-b) dec:dup dec:negative? &dec:negate if ;
:dec:put (dec:a-) dec:to-string s:put ;
:dec:PI (dec:-F) ,3.141592 ;
:dec:E (dec:-F) ,2.718281 ;
:dec:NAN (dec:-n) ,0 ,0 dec:/ ;
:dec:INF (dec:-n) ,1.0 ,0 dec:/ ;
:dec:-INF (dec:-n) ,-1.0 ,0 dec:/ ;
:dec:nan? (dec:n-,-f) dec:dup dec:-eq? ;
:dec:inf? (dec:n-,-f) dec:INF dec:eq? ;
:dec:-inf? (dec:n-,-f) dec:-INF dec:eq? ;
:dec:round (-|dec:a-b)
dec:dup dec:negative?
[ ,0.5 dec:- dec:ceiling ]
[ ,0.5 dec:+ dec:floor ] choose ;
:dec:min (dec:nn-n) dec:dup-pair dec:lt? &dec:drop &dec:nip choose ;
:dec:max (dec:nn-n) dec:dup-pair dec:gt? &dec:drop &dec:nip choose ;
:dec:limit (dec:nlu-n) dec:swap dec:push dec:min dec:pop dec:max ;
:dec:between? (dec:nlu-n) dec:rot dec:dup dec:push dec:rot dec:rot dec:limit dec:pop dec:eq? ;
:dec:inc (dec:n-n) ,1 dec:+ ;
:dec:dec (dec:n-n) ,1 dec:- ;
:dec:case (dec:ff-,q-)
dec:over dec:eq? [ dec:drop call #-1 ] [ drop #0 ] choose 0; pop drop-pair ;
:dec:sign (-n|dec:a-)
dec:dup ,0 dec:eq? [ #0 dec:drop ] if;
,0 dec:gt? [ #1 ] [ #-1 ] choose ;
~~~

View file

@ -3,7 +3,7 @@
#define CELL int32_t
#endif
CELL ngaImageCells = 13846;
CELL ngaImage[] = { 1793,13757,13747,13845,202101,0,10,1,10,2,10,3,10,4,10,5,10,6,10,
CELL ngaImage[] = { 1793,13757,13747,13845,202104,0,10,1,10,2,10,3,10,4,10,5,10,6,10,
7,10,8,10,9,10,10,11,10,12,10,13,10,14,10,15,10,16,10,17,
10,18,10,19,10,20,10,21,10,22,10,23,10,24,10,25,10,68223234,1,2575,
85000450,1,656912,3211,3220,268505089,63,62,285281281,0,63,2063,10,101384453,0,9,10,2049,56,25,

View file

@ -1,7 +1,83 @@
# Stub for Decimal I/O device
from decimal import *
import decimal
class DecimalStack(object):
def __init__(self, *d):
self.data = list(d)
class Decimal:
def __init__(self):
pass
def __getitem__(self, id):
return self.data[id]
def add(self):
self.data.append(self.data.pop() + self.data.pop())
def sub(self):
self.data.append(0 - (self.data.pop() - self.data.pop()))
def mul(self):
self.data.append(self.data.pop() * self.data.pop())
def div(self):
a, b = self.data.pop(), self.data.pop()
self.data.append(b / a)
def ceil(self):
self.data.append(math.ceil(self.data.pop()))
def floor(self):
self.data.append(math.floor(self.data.pop()))
def eq(self):
return 0 - (self.data.pop() == self.data.pop())
def neq(self):
return 0 - (self.data.pop() != self.data.pop())
def gt(self):
a, b = self.data.pop(), self.data.pop()
return 0 - (b > a)
def lt(self):
a, b = self.data.pop(), self.data.pop()
return 0 - (b < a)
def depth(self):
return len(self.data)
def drop(self):
self.data.pop()
def pop(self):
return self.data.pop()
def swap(self):
a, b = self.data.pop(), self.data.pop()
self.data += [a, b]
def push(self, n):
self.data.append(n)
def log(self):
a, b = self.data.pop(), self.data.pop()
self.data.append(math.log(b, a))
def power(self):
a, b = self.data.pop(), self.data.pop()
self.data.append(math.pow(a, b))
def sin(self):
self.data.append(math.sin(self.data.pop()))
def cos(self):
self.data.append(math.cos(self.data.pop()))
def tan(self):
self.data.append(math.tan(self.data.pop()))
def asin(self):
self.data.append(math.asin(self.data.pop()))
def acos(self):
self.data.append(math.acos(self.data.pop()))
def atan(self):
self.data.append(math.atan(self.data.pop()))

View file

@ -24,13 +24,14 @@
# combine the separate files into a single one for deployment.
# -------------------------------------------------------------
import os, sys, math, time, struct, random, datetime
import os, sys, math, time, struct, random, datetime, decimal
from ClockDevice import Clock
from RNGDevice import RNG
from FileSystemDevice import FileSystem
from FloatStack import FloatStack
from DecimalDevice import DecimalStack
from IntegerStack import IntegerStack
from Memory import Memory
from InitialImage import InitialImage
@ -50,6 +51,9 @@ class Retro:
self.files = FileSystem()
self.floats = FloatStack()
self.afloats = FloatStack()
self.decimals = DecimalStack()
self.adecimals = DecimalStack()
self.Dictionary = self.populate_dictionary()
self.Cached = self.cache_words()
@ -319,7 +323,7 @@ class Retro:
self.ip = 9000000
def i_ienumerate(self):
self.stack.push(6)
self.stack.push(7)
def i_iquery(self):
device = self.stack.pop()
@ -341,6 +345,9 @@ class Retro:
if device == 5: # scripting
self.stack.push(0)
self.stack.push(9)
if device == 6: # decimal
self.stack.push(0)
self.stack.push(20)
def file_open_params(self):
mode = self.stack.pop()
@ -416,6 +423,39 @@ class Retro:
29: lambda: self.stack.push(self.afloats.depth()),
}
self.decimal_instr = {
0: lambda: self.decimals.push(decimal.Decimal(self.stack.pop())),
1: lambda: self.decimals.push(decimal.Decimal(self.extract_string(self.stack.pop()))),
2: lambda: self.stack.push(int(self.decimals.pop())),
3: lambda: self.inject_string(str(self.decimals.pop()), self.stack.pop()),
4: lambda: self.decimals.add(),
5: lambda: self.decimals.sub(),
6: lambda: self.decimals.mul(),
7: lambda: self.decimals.div(),
8: lambda: self.decimals.floor(),
9: lambda: self.decimals.ceil(),
10: lambda: self.decimals.sqrt(),
11: lambda: self.stack.push(self.decimals.eq()),
12: lambda: self.stack.push(self.decimals.neq()),
13: lambda: self.stack.push(self.decimals.lt()),
14: lambda: self.stack.push(self.decimals.gt()),
15: lambda: self.stack.push(self.decimals.depth()),
16: lambda: self.decimals.dup(),
17: lambda: self.decimals.drop(),
18: lambda: self.decimals.swap(),
19: lambda: self.decimals.log(),
20: lambda: self.decimals.pow(),
21: lambda: self.decimals.sin(),
22: lambda: self.decimals.cos(),
23: lambda: self.decimals.tan(),
24: lambda: self.decimals.asin(),
25: lambda: self.decimals.atan(),
26: lambda: self.decimals.acos(),
27: lambda: self.adecimals.push(self.decimals.pop()),
28: lambda: self.decimals.push(self.adecimals.pop()),
29: lambda: self.stack.push(self.adecimals.depth()),
}
def i_iinvoke(self):
device = self.stack.pop()
# print('dev:', device)
@ -445,6 +485,9 @@ class Retro:
if action == 3:
b = self.stack.pop()
self.stack.push(self.inject_string(sys.argv[0], b))
if device == 6:
action = self.stack.pop()
self.decimal_instr[int(action)]()
def validate_opcode(self, I0, I1, I2, I3):
if (