mirror of
https://github.com/nineties/planckforth
synced 2025-01-14 08:01:27 +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 sys
|
||||||
|
import operator
|
||||||
CELL = 4
|
CELL = 4
|
||||||
MEMORY_SIZE = 0x08000000
|
MEMORY_SIZE = 0x08000000
|
||||||
STACK_SIZE = 0x400
|
STACK_SIZE = 0x400
|
||||||
|
@ -15,11 +16,14 @@ memory = bytearray(MEMORY_SIZE)
|
||||||
sp = MEMORY_SIZE
|
sp = MEMORY_SIZE
|
||||||
rp = MEMORY_SIZE - STACK_SIZE
|
rp = MEMORY_SIZE - STACK_SIZE
|
||||||
ip = 0
|
ip = 0
|
||||||
pc = 0
|
np = 0
|
||||||
|
|
||||||
def aligned(n):
|
def aligned(n):
|
||||||
return (n + CELL - 1) & ~(CELL - 1)
|
return (n + CELL - 1) & ~(CELL - 1)
|
||||||
|
|
||||||
|
def align():
|
||||||
|
write(HERE_CELL, aligned(read(HERE_CELL)))
|
||||||
|
|
||||||
def read(addr):
|
def read(addr):
|
||||||
return int.from_bytes(
|
return int.from_bytes(
|
||||||
memory[addr:addr+CELL], 'little', signed=True)
|
memory[addr:addr+CELL], 'little', signed=True)
|
||||||
|
@ -27,28 +31,27 @@ def read(addr):
|
||||||
def write(addr, v):
|
def write(addr, v):
|
||||||
memory[addr:addr+CELL] = v.to_bytes(4, 'little', signed=True)
|
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):
|
def read_byte(addr):
|
||||||
return memory[addr]
|
return memory[addr]
|
||||||
|
|
||||||
def write_byte(addr, v):
|
def write_byte(addr, v):
|
||||||
memory[addr] = v
|
memory[addr] = v
|
||||||
|
|
||||||
next_builtin_id = 1
|
def comma_byte(v):
|
||||||
def add_builtin(c):
|
|
||||||
global next_builtin_id
|
|
||||||
builtin_id = next_builtin_id
|
|
||||||
next_builtin_id += 1
|
|
||||||
|
|
||||||
here = read(HERE_CELL)
|
here = read(HERE_CELL)
|
||||||
latest = read(LATEST_CELL)
|
memory[here] = v
|
||||||
write(here, latest)
|
write(HERE_CELL, here + 1)
|
||||||
write_byte(here + CELL, 1)
|
|
||||||
write_byte(here + CELL + 1, ord(c))
|
|
||||||
write(here + 2*CELL, builtin_id)
|
|
||||||
|
|
||||||
write(HERE_CELL, here + 3*CELL)
|
def comma_string(s):
|
||||||
write(LATEST_CELL, here)
|
n = len(s)
|
||||||
return builtin_id
|
here = read(HERE_CELL)
|
||||||
|
memory[here:here+n+1] = bytes(s+'\0', 'ascii')
|
||||||
|
write(HERE_CELL, here+n+1)
|
||||||
|
|
||||||
def find(c):
|
def find(c):
|
||||||
it = read(LATEST_CELL)
|
it = read(LATEST_CELL)
|
||||||
|
@ -82,143 +85,99 @@ def rpop():
|
||||||
rp += CELL
|
rp += CELL
|
||||||
return v
|
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(HERE_CELL, 2*CELL)
|
||||||
write(LATEST_CELL, 0)
|
write(LATEST_CELL, 0)
|
||||||
|
|
||||||
DOCOL_ = 0
|
def docol(ip, np):
|
||||||
QUIT = add_builtin('Q')
|
rpush(np)
|
||||||
CELLSIZE = add_builtin('C')
|
return next(ip + CELL)
|
||||||
HERE = add_builtin('h')
|
DOCOL_ID = add_operator('', docol)
|
||||||
LATEST = add_builtin('l')
|
add_simple_operator('Q', lambda: exit(0))
|
||||||
KEY = add_builtin('k')
|
add_simple_operator('C', lambda: push(CELL))
|
||||||
EMIT = add_builtin('t')
|
add_simple_operator('h', lambda: push(HERE_CELL))
|
||||||
JUMP = add_builtin('j')
|
add_simple_operator('l', lambda: push(LATEST_CELL))
|
||||||
JUMP0 = add_builtin('J')
|
add_simple_operator('k', lambda: push(ord(sys.stdin.read(1))))
|
||||||
FIND = add_builtin('f')
|
add_simple_operator('t', lambda: sys.stdout.write(chr(pop())))
|
||||||
EXECUTE = add_builtin('x')
|
add_operator('j', lambda ip,np: next(np + read(np)))
|
||||||
FETCH = add_builtin('@')
|
add_operator('J', lambda ip,np: next(np + (CELL if pop() else read(np))))
|
||||||
STORE = add_builtin('!')
|
add_simple_operator('f', lambda: push(find(chr(pop()))))
|
||||||
CFETCH = add_builtin('?')
|
add_operator('x', lambda ip,np: (pop(), np))
|
||||||
CSTORE = add_builtin('$')
|
add_simple_operator('@', lambda: push(read(pop())))
|
||||||
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('=')
|
|
||||||
|
|
||||||
here = read(HERE_CELL)
|
# NB: Python evaluates expressions from left to right
|
||||||
write(here, find('k'))
|
# https://docs.python.org/3/reference/expressions.html#evaluation-order
|
||||||
write(here + CELL, find('f'))
|
add_simple_operator('!', lambda: write(pop(), pop()))
|
||||||
write(here + 2*CELL, find('x'))
|
add_simple_operator('?', lambda: push(read_byte(pop())))
|
||||||
write(here + 3*CELL, find('j'))
|
add_simple_operator('$', lambda: write_byte(pop(), pop()))
|
||||||
write(here + 4*CELL, -4*CELL)
|
add_simple_operator('d', lambda: push(sp))
|
||||||
write(HERE_CELL, here + 5*CELL)
|
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
|
start = read(HERE_CELL)
|
||||||
ip = read(pc)
|
comma(find('k'))
|
||||||
pc += CELL
|
comma(find('f'))
|
||||||
|
comma(find('x'))
|
||||||
|
comma(find('j'))
|
||||||
|
comma(-4*CELL)
|
||||||
|
|
||||||
|
ip, np = next(start)
|
||||||
while True:
|
while True:
|
||||||
code = read(ip)
|
ip, np = operators[read(ip)](ip, np)
|
||||||
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
|
|
||||||
|
|
Loading…
Reference in a new issue