mirror of
https://github.com/nineties/planckforth
synced 2025-01-13 08:01:10 +01:00
Reimplement python version
This commit is contained in:
parent
b49d6d85c6
commit
2318cbf711
1 changed files with 108 additions and 149 deletions
257
others/planck.py
257
others/planck.py
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
|
||||
import sys
|
||||
import operator
|
||||
CELL = 4
|
||||
MEMORY_SIZE = 0x08000000
|
||||
STACK_SIZE = 0x400
|
||||
|
@ -15,11 +16,14 @@ memory = bytearray(MEMORY_SIZE)
|
|||
sp = MEMORY_SIZE
|
||||
rp = MEMORY_SIZE - STACK_SIZE
|
||||
ip = 0
|
||||
pc = 0
|
||||
np = 0
|
||||
|
||||
def aligned(n):
|
||||
return (n + CELL - 1) & ~(CELL - 1)
|
||||
|
||||
def align():
|
||||
write(HERE_CELL, aligned(read(HERE_CELL)))
|
||||
|
||||
def read(addr):
|
||||
return int.from_bytes(
|
||||
memory[addr:addr+CELL], 'little', signed=True)
|
||||
|
@ -27,28 +31,27 @@ def read(addr):
|
|||
def write(addr, v):
|
||||
memory[addr:addr+CELL] = v.to_bytes(4, 'little', signed=True)
|
||||
|
||||
def comma(v):
|
||||
here = read(HERE_CELL)
|
||||
write(here, v)
|
||||
write(HERE_CELL, here + CELL)
|
||||
|
||||
def read_byte(addr):
|
||||
return memory[addr]
|
||||
|
||||
def write_byte(addr, v):
|
||||
memory[addr] = v
|
||||
|
||||
next_builtin_id = 1
|
||||
def add_builtin(c):
|
||||
global next_builtin_id
|
||||
builtin_id = next_builtin_id
|
||||
next_builtin_id += 1
|
||||
|
||||
def comma_byte(v):
|
||||
here = read(HERE_CELL)
|
||||
latest = read(LATEST_CELL)
|
||||
write(here, latest)
|
||||
write_byte(here + CELL, 1)
|
||||
write_byte(here + CELL + 1, ord(c))
|
||||
write(here + 2*CELL, builtin_id)
|
||||
memory[here] = v
|
||||
write(HERE_CELL, here + 1)
|
||||
|
||||
write(HERE_CELL, here + 3*CELL)
|
||||
write(LATEST_CELL, here)
|
||||
return builtin_id
|
||||
def comma_string(s):
|
||||
n = len(s)
|
||||
here = read(HERE_CELL)
|
||||
memory[here:here+n+1] = bytes(s+'\0', 'ascii')
|
||||
write(HERE_CELL, here+n+1)
|
||||
|
||||
def find(c):
|
||||
it = read(LATEST_CELL)
|
||||
|
@ -82,143 +85,99 @@ def rpop():
|
|||
rp += CELL
|
||||
return v
|
||||
|
||||
operators = []
|
||||
def add_operator(name, func):
|
||||
funcid = len(operators)
|
||||
here = read(HERE_CELL)
|
||||
latest = read(LATEST_CELL)
|
||||
write(LATEST_CELL, here)
|
||||
|
||||
comma(latest)
|
||||
comma_byte(len(name))
|
||||
comma_string(name)
|
||||
align()
|
||||
comma(funcid)
|
||||
|
||||
operators.append(func)
|
||||
return funcid
|
||||
|
||||
def next(np):
|
||||
return read(np), np + CELL
|
||||
|
||||
def add_simple_operator(name, func):
|
||||
def func_(ip, np):
|
||||
func()
|
||||
return next(np)
|
||||
return add_operator(name, func_)
|
||||
|
||||
def add_binary_operator(name, op):
|
||||
def func():
|
||||
b = pop()
|
||||
push(op(pop(), b))
|
||||
return add_simple_operator(name, func)
|
||||
|
||||
write(HERE_CELL, 2*CELL)
|
||||
write(LATEST_CELL, 0)
|
||||
|
||||
DOCOL_ = 0
|
||||
QUIT = add_builtin('Q')
|
||||
CELLSIZE = add_builtin('C')
|
||||
HERE = add_builtin('h')
|
||||
LATEST = add_builtin('l')
|
||||
KEY = add_builtin('k')
|
||||
EMIT = add_builtin('t')
|
||||
JUMP = add_builtin('j')
|
||||
JUMP0 = add_builtin('J')
|
||||
FIND = add_builtin('f')
|
||||
EXECUTE = add_builtin('x')
|
||||
FETCH = add_builtin('@')
|
||||
STORE = add_builtin('!')
|
||||
CFETCH = add_builtin('?')
|
||||
CSTORE = add_builtin('$')
|
||||
DFETCH = add_builtin('d')
|
||||
DSTORE = add_builtin('D')
|
||||
RFETCH = add_builtin('r')
|
||||
RSTORE = add_builtin('R')
|
||||
DOCOL = add_builtin('i')
|
||||
EXIT = add_builtin('e')
|
||||
LIT = add_builtin('L')
|
||||
LITSTRING = add_builtin('S')
|
||||
ADD = add_builtin('+')
|
||||
SUB = add_builtin('-')
|
||||
MUL = add_builtin('*')
|
||||
DIV = add_builtin('/')
|
||||
MOD = add_builtin('%')
|
||||
AND = add_builtin('&')
|
||||
OR = add_builtin('|')
|
||||
XOR = add_builtin('^')
|
||||
LESS = add_builtin('<')
|
||||
EQUAL = add_builtin('=')
|
||||
def docol(ip, np):
|
||||
rpush(np)
|
||||
return next(ip + CELL)
|
||||
DOCOL_ID = add_operator('', docol)
|
||||
add_simple_operator('Q', lambda: exit(0))
|
||||
add_simple_operator('C', lambda: push(CELL))
|
||||
add_simple_operator('h', lambda: push(HERE_CELL))
|
||||
add_simple_operator('l', lambda: push(LATEST_CELL))
|
||||
add_simple_operator('k', lambda: push(ord(sys.stdin.read(1))))
|
||||
add_simple_operator('t', lambda: sys.stdout.write(chr(pop())))
|
||||
add_operator('j', lambda ip,np: next(np + read(np)))
|
||||
add_operator('J', lambda ip,np: next(np + (CELL if pop() else read(np))))
|
||||
add_simple_operator('f', lambda: push(find(chr(pop()))))
|
||||
add_operator('x', lambda ip,np: (pop(), np))
|
||||
add_simple_operator('@', lambda: push(read(pop())))
|
||||
|
||||
here = read(HERE_CELL)
|
||||
write(here, find('k'))
|
||||
write(here + CELL, find('f'))
|
||||
write(here + 2*CELL, find('x'))
|
||||
write(here + 3*CELL, find('j'))
|
||||
write(here + 4*CELL, -4*CELL)
|
||||
write(HERE_CELL, here + 5*CELL)
|
||||
# NB: Python evaluates expressions from left to right
|
||||
# https://docs.python.org/3/reference/expressions.html#evaluation-order
|
||||
add_simple_operator('!', lambda: write(pop(), pop()))
|
||||
add_simple_operator('?', lambda: push(read_byte(pop())))
|
||||
add_simple_operator('$', lambda: write_byte(pop(), pop()))
|
||||
add_simple_operator('d', lambda: push(sp))
|
||||
def set_sp():
|
||||
global sp
|
||||
sp = pop()
|
||||
add_simple_operator('D', set_sp)
|
||||
add_simple_operator('r', lambda: push(rp))
|
||||
def set_rp():
|
||||
global rp
|
||||
rp = pop()
|
||||
add_simple_operator('R', set_rp)
|
||||
add_simple_operator('i', lambda: push(DOCOL_ID))
|
||||
add_operator('e', lambda ip,np: next(rpop()))
|
||||
def lit(ip, np):
|
||||
push(read(np))
|
||||
return next(np + CELL)
|
||||
add_operator('L', lit)
|
||||
def litstring(ip, np):
|
||||
push(np + CELL)
|
||||
return next(aligned(np + CELL + read(np)))
|
||||
add_operator('S', litstring)
|
||||
add_binary_operator('+', operator.add)
|
||||
add_binary_operator('-', operator.sub)
|
||||
add_binary_operator('*', operator.mul)
|
||||
add_binary_operator('/', operator.floordiv)
|
||||
add_binary_operator('%', operator.mod)
|
||||
add_binary_operator('&', operator.and_)
|
||||
add_binary_operator('|', operator.or_)
|
||||
add_binary_operator('^', operator.xor)
|
||||
add_binary_operator('<', operator.lt)
|
||||
add_binary_operator('=', operator.eq)
|
||||
|
||||
pc = here
|
||||
ip = read(pc)
|
||||
pc += CELL
|
||||
start = read(HERE_CELL)
|
||||
comma(find('k'))
|
||||
comma(find('f'))
|
||||
comma(find('x'))
|
||||
comma(find('j'))
|
||||
comma(-4*CELL)
|
||||
|
||||
ip, np = next(start)
|
||||
while True:
|
||||
code = read(ip)
|
||||
if code == DOCOL_:
|
||||
rpush(pc)
|
||||
pc = ip + CELL
|
||||
elif code == QUIT:
|
||||
exit(0)
|
||||
elif code == CELLSIZE:
|
||||
push(CELL)
|
||||
elif code == HERE:
|
||||
push(HERE_CELL)
|
||||
elif code == LATEST:
|
||||
push(LATEST_CELL)
|
||||
elif code == KEY:
|
||||
push(ord(sys.stdin.read(1)))
|
||||
elif code == EMIT:
|
||||
sys.stdout.write(chr(pop()))
|
||||
elif code == JUMP:
|
||||
pc += read(pc)
|
||||
elif code == JUMP0:
|
||||
if pop() == 0:
|
||||
pc += read(pc)
|
||||
else:
|
||||
pc += CELL
|
||||
elif code == FIND:
|
||||
push(find(chr(pop())))
|
||||
elif code == EXECUTE:
|
||||
ip = pop()
|
||||
continue
|
||||
elif code == FETCH:
|
||||
push(read(pop()))
|
||||
elif code == STORE:
|
||||
addr = pop()
|
||||
write(addr, pop())
|
||||
elif code == CFETCH:
|
||||
push(read_byte(pop()))
|
||||
elif code == CSTORE:
|
||||
addr = pop()
|
||||
write_byte(addr, pop())
|
||||
elif code == DFETCH:
|
||||
push(sp)
|
||||
elif code == DSTORE:
|
||||
sp = pop()
|
||||
elif code == RFETCH:
|
||||
push(rp)
|
||||
elif code == RSTORE:
|
||||
rp = pop()
|
||||
elif code == DOCOL:
|
||||
push(DOCOL_)
|
||||
elif code == EXIT:
|
||||
pc = rpop()
|
||||
elif code == LIT:
|
||||
push(read(pc))
|
||||
pc += CELL
|
||||
elif code == LITSTRING:
|
||||
n = read(pc)
|
||||
push(pc + CELL)
|
||||
pc = aligned(pc + CELL + n)
|
||||
elif code == ADD:
|
||||
b = pop()
|
||||
push(pop() + b)
|
||||
elif code == SUB:
|
||||
b = pop()
|
||||
push(pop() - b)
|
||||
elif code == MUL:
|
||||
b = pop()
|
||||
push(pop() * b)
|
||||
elif code == DIV:
|
||||
b = pop()
|
||||
push(pop() // b)
|
||||
elif code == MOD:
|
||||
b = pop()
|
||||
push(pop() % b)
|
||||
elif code == AND:
|
||||
b = pop()
|
||||
push(pop() & b)
|
||||
elif code == OR:
|
||||
b = pop()
|
||||
push(pop() | b)
|
||||
elif code == XOR:
|
||||
b = pop()
|
||||
push(pop() ^ b)
|
||||
elif code == LESS:
|
||||
b = pop()
|
||||
push(pop() < b)
|
||||
elif code == EQUAL:
|
||||
b = pop()
|
||||
push(pop() == b)
|
||||
else:
|
||||
raise Exception('Invalid Code Pointer: {}'.format(code))
|
||||
ip = read(pc)
|
||||
pc += CELL
|
||||
ip, np = operators[read(ip)](ip, np)
|
||||
|
|
Loading…
Reference in a new issue