Add c-version and python-version

This commit is contained in:
Koichi Nakamura 2021-01-03 23:59:45 +09:00
parent c01cd8cc50
commit d197737bcc
2 changed files with 354 additions and 0 deletions

133
others/planck.c Normal file
View 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
View 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