mirror of
https://github.com/nineties/planckforth
synced 2025-01-14 08:01:27 +01:00
Add c-version and python-version
This commit is contained in:
parent
c01cd8cc50
commit
d197737bcc
2 changed files with 354 additions and 0 deletions
133
others/planck.c
Normal file
133
others/planck.c
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
/* planck -
|
||||||
|
* Copyright (C) 2021 nineties
|
||||||
|
*/
|
||||||
|
#ifndef INCLUDE_DEFS
|
||||||
|
#define INCLUDE_DEFS
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef uintptr_t cell;
|
||||||
|
typedef void (**cfa)();
|
||||||
|
|
||||||
|
#define CELL sizeof(cell)
|
||||||
|
#define STACK_SIZE 1024
|
||||||
|
#define RSTACK_SIZE 1024
|
||||||
|
#define MEMORY_SIZE 0x100000
|
||||||
|
|
||||||
|
typedef struct builtin {
|
||||||
|
struct builtin *prev;
|
||||||
|
char len;
|
||||||
|
char name;
|
||||||
|
char padding[CELL-2];
|
||||||
|
void (*fun)();
|
||||||
|
} builtin;
|
||||||
|
|
||||||
|
static cell stack[STACK_SIZE];
|
||||||
|
static cell rstack[RSTACK_SIZE];
|
||||||
|
static cell *dsp = stack + STACK_SIZE;
|
||||||
|
static cell *rsp = rstack + RSTACK_SIZE;
|
||||||
|
|
||||||
|
static cell memory[MEMORY_SIZE];
|
||||||
|
static builtin *latest = 0;
|
||||||
|
static cell *here = memory;
|
||||||
|
static cell *pc = NULL;
|
||||||
|
static cfa ip = NULL;
|
||||||
|
|
||||||
|
#define next() (*(ip = (cfa)(*pc++)))()
|
||||||
|
|
||||||
|
static void push(cell v) { *(--dsp) = v; }
|
||||||
|
static cell pop(void) { return *dsp++; }
|
||||||
|
static void rpush(cell v) { *(--rsp) = v; }
|
||||||
|
static cell rpop(void) { return *rsp++; }
|
||||||
|
|
||||||
|
static void docol(void) {
|
||||||
|
rpush((cell) pc);
|
||||||
|
pc = (cell*)ip + 1;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
static cfa find(char c) {
|
||||||
|
for (builtin *it = latest; it; it = it->prev)
|
||||||
|
if (it->len == 1 && it->name == c)
|
||||||
|
return &it->fun;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define defcode(name, label) \
|
||||||
|
static void label()
|
||||||
|
#include "planck.c"
|
||||||
|
#undef defcode
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
#define defcode(c, label) \
|
||||||
|
memcpy(here, &(builtin){ latest, 1, c, {0}, label }, 3*CELL); \
|
||||||
|
latest = (builtin*)here; \
|
||||||
|
here += 3; \
|
||||||
|
if (0) // skip function body
|
||||||
|
#include "planck.c"
|
||||||
|
|
||||||
|
cfa start = (cfa) here;
|
||||||
|
*here++ = (cell) find('k');
|
||||||
|
*here++ = (cell) find('f');
|
||||||
|
*here++ = (cell) find('x');
|
||||||
|
*here++ = (cell) find('j');
|
||||||
|
*here++ = (cell) -4 * CELL;
|
||||||
|
pc = (cell*) start;
|
||||||
|
next();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
defcode('Q', quit) { exit(0); }
|
||||||
|
defcode('C', cell_) { push(CELL); next(); }
|
||||||
|
defcode('h', here_) { push((cell)&here); next(); }
|
||||||
|
defcode('l', latest_) { push((cell)&latest); next(); }
|
||||||
|
defcode('i', docol_) { push((cell)docol); next(); }
|
||||||
|
defcode('e', exit_) { pc = (cell*)rpop(); next(); }
|
||||||
|
defcode('@', fetch) { cell *p = (cell*)pop(); push(*p); next(); }
|
||||||
|
defcode('!', store) { cell *p = (cell*)pop(); *p = pop(); next(); }
|
||||||
|
defcode('?', cfetch) { char *p = (char*)pop(); push(*p); next(); }
|
||||||
|
defcode('$', cstore) { char *p = (char*)pop(); *p = pop(); next(); }
|
||||||
|
defcode('d', dfetch) { push((cell)dsp); next(); }
|
||||||
|
defcode('D', dstore) { dsp = (cell*) pop(); next(); }
|
||||||
|
defcode('r', rfetch) { push((cell)rsp); next(); }
|
||||||
|
defcode('R', rstore) { rsp = (cell*) pop(); next(); }
|
||||||
|
defcode('j', jump) { pc += (int)*pc/CELL; next(); }
|
||||||
|
defcode('J', jump0) { pc += (int)(pop()?1:*pc/CELL); next(); }
|
||||||
|
defcode('L', lit) { push(*pc++); next(); }
|
||||||
|
defcode('S', litstring) {
|
||||||
|
int len = *pc++;
|
||||||
|
push((cell) pc);
|
||||||
|
push(len);
|
||||||
|
pc += (len + CELL - 1)/CELL;
|
||||||
|
}
|
||||||
|
defcode('k', key) {
|
||||||
|
int c = getchar();
|
||||||
|
if (c <= 0)
|
||||||
|
exit(0);
|
||||||
|
push(c);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
defcode('t', type) { putchar(pop()); next(); }
|
||||||
|
defcode('x', exec) { (*(ip = (cfa) pop()))(); }
|
||||||
|
defcode('f', find_) { push((cell) find(pop())); next(); }
|
||||||
|
#define defbinary(c, label, op, ty) \
|
||||||
|
defcode(c, label) { \
|
||||||
|
ty b = (ty) pop(); \
|
||||||
|
*dsp = (cell)((ty) *dsp op b); \
|
||||||
|
next(); \
|
||||||
|
}
|
||||||
|
defbinary('+', add, +, intptr_t)
|
||||||
|
defbinary('-', sub, -, intptr_t)
|
||||||
|
defbinary('*', mul, *, intptr_t)
|
||||||
|
defbinary('/', div_, /, intptr_t)
|
||||||
|
defbinary('%', mod, %, intptr_t)
|
||||||
|
defbinary('&', and, &, uintptr_t)
|
||||||
|
defbinary('|', or, |, uintptr_t)
|
||||||
|
defbinary('^', xor, ^, uintptr_t)
|
||||||
|
defbinary('<', lt, <, intptr_t)
|
||||||
|
defbinary('=', eq, ==, intptr_t)
|
||||||
|
|
||||||
|
#endif
|
221
others/planck.py
Normal file
221
others/planck.py
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
# planck -
|
||||||
|
# Copyright (C) 2021 nineties
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
CELL = 4
|
||||||
|
MEMORY_SIZE = 0x08000000
|
||||||
|
STACK_SIZE = 0x400
|
||||||
|
RSTACK_SIZE = 0x400
|
||||||
|
HERE_CELL = 0
|
||||||
|
LATEST_CELL = CELL
|
||||||
|
|
||||||
|
memory = bytearray(MEMORY_SIZE)
|
||||||
|
sp = MEMORY_SIZE
|
||||||
|
rp = MEMORY_SIZE - STACK_SIZE
|
||||||
|
ip = 0
|
||||||
|
pc = 0
|
||||||
|
|
||||||
|
def read(addr):
|
||||||
|
return int.from_bytes(
|
||||||
|
memory[addr:addr+CELL], 'little', signed=True)
|
||||||
|
|
||||||
|
def write(addr, v):
|
||||||
|
memory[addr:addr+CELL] = v.to_bytes(4, 'little', signed=True)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
write(HERE_CELL, here + 3*CELL)
|
||||||
|
write(LATEST_CELL, here)
|
||||||
|
return builtin_id
|
||||||
|
|
||||||
|
def find(c):
|
||||||
|
it = read(LATEST_CELL)
|
||||||
|
while it != 0:
|
||||||
|
n = read_byte(it + CELL)
|
||||||
|
C = chr(read_byte(it + CELL + 1))
|
||||||
|
if (c == C and n == 1):
|
||||||
|
return it + 2*CELL
|
||||||
|
it = read(it)
|
||||||
|
raise Exception('Unknown word: {}'.format(c))
|
||||||
|
|
||||||
|
def push(v):
|
||||||
|
global sp
|
||||||
|
sp -= CELL
|
||||||
|
write(sp, v)
|
||||||
|
|
||||||
|
def pop():
|
||||||
|
global sp
|
||||||
|
v = read(sp)
|
||||||
|
sp += CELL
|
||||||
|
return v
|
||||||
|
|
||||||
|
def rpush(v):
|
||||||
|
global rp
|
||||||
|
rp -= CELL
|
||||||
|
write(rp, v)
|
||||||
|
|
||||||
|
def rpop():
|
||||||
|
global rp
|
||||||
|
v = read(rp)
|
||||||
|
rp += CELL
|
||||||
|
return v
|
||||||
|
|
||||||
|
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('=')
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
pc = here
|
||||||
|
ip = read(pc)
|
||||||
|
pc += CELL
|
||||||
|
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)
|
||||||
|
push(n)
|
||||||
|
pc = (pc + 2*CELL + n - 1) & ~CELL
|
||||||
|
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