Fix up bad git subtree import.
This commit is contained in:
23
misc/kforth/v1/Makefile
Normal file
23
misc/kforth/v1/Makefile
Normal file
@@ -0,0 +1,23 @@
|
||||
CXXSTD := c++14
|
||||
CXXFLAGS := -std=$(CXXSTD) -Wall -Werror -O0 -g
|
||||
LDFLAGS := -static
|
||||
OBJS := linux/io.o \
|
||||
io.o \
|
||||
system.o \
|
||||
parser.o \
|
||||
word.o \
|
||||
dict.o \
|
||||
kforth.o
|
||||
TARGET := kforth
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CXX) $(LDFLAGS) -o $@ $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(TARGET)
|
||||
|
||||
install: $(TARGET)
|
||||
cp $(TARGET) ~/bin
|
||||
chmod 0755 ~/bin/$(TARGET)
|
||||
8
misc/kforth/v1/TODO.txt
Normal file
8
misc/kforth/v1/TODO.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
nucleus layer:
|
||||
+ EXIT: requires better execution control
|
||||
+ I: requires support for loop index
|
||||
+ J: requires support for loop index
|
||||
|
||||
return addressing / rstack
|
||||
dictionary -> fixed size stack / array
|
||||
|
||||
27
misc/kforth/v1/defs.h
Normal file
27
misc/kforth/v1/defs.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef __KF_DEFS_H__
|
||||
#define __KF_DEFS_H__
|
||||
|
||||
#ifdef __linux__
|
||||
#include "linux/defs.h"
|
||||
#else
|
||||
typedef int KF_INT;
|
||||
typedef long KF_LONG;
|
||||
constexpr uint8_t STACK_SIZE = 16;
|
||||
#endif
|
||||
|
||||
constexpr size_t MAX_TOKEN_LENGTH = 16;
|
||||
constexpr size_t dshift = (sizeof(KF_INT) * 8) - 1;
|
||||
|
||||
static inline KF_INT
|
||||
mask(size_t bits)
|
||||
{
|
||||
KF_INT m = 0;
|
||||
|
||||
for (size_t i = 0; i < bits; i++) {
|
||||
m += 1 << i;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
#endif // __KF_DEFS_H__
|
||||
1678
misc/kforth/v1/dict.cc
Normal file
1678
misc/kforth/v1/dict.cc
Normal file
File diff suppressed because it is too large
Load Diff
15
misc/kforth/v1/dict.h
Normal file
15
misc/kforth/v1/dict.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef __KF_DICT_H__
|
||||
#define __KF_DICT_H__
|
||||
|
||||
#include "defs.h"
|
||||
#include "parser.h"
|
||||
#include "system.h"
|
||||
#include "word.h"
|
||||
|
||||
void init_dict(System *);
|
||||
void reset_system(System *);
|
||||
bool lookup(struct Token *, System *);
|
||||
|
||||
|
||||
|
||||
#endif // __KF_DICT_H__
|
||||
98
misc/kforth/v1/io.cc
Normal file
98
misc/kforth/v1/io.cc
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "defs.h"
|
||||
#include "io.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
write_num(IO *interface, KF_INT n)
|
||||
{
|
||||
static constexpr size_t nbuflen = 11;
|
||||
char buf[nbuflen];
|
||||
uint8_t i = nbuflen - 1;
|
||||
memset(buf, 0, nbuflen);
|
||||
|
||||
if (n < 0) {
|
||||
interface->wrch('-');
|
||||
}
|
||||
else if (n == 0) {
|
||||
interface->wrch('0');
|
||||
return;
|
||||
}
|
||||
|
||||
while (n != 0) {
|
||||
char x = n % 10;
|
||||
x = x < 0 ? -x : x;
|
||||
x += '0';
|
||||
buf[i--] = x;
|
||||
n /= 10;
|
||||
}
|
||||
|
||||
interface->wrbuf(buf+i, nbuflen - i);
|
||||
}
|
||||
|
||||
void
|
||||
write_unum(IO *interface, KF_UINT n)
|
||||
{
|
||||
static constexpr size_t nbuflen = 11;
|
||||
char buf[nbuflen];
|
||||
uint8_t i = nbuflen - 1;
|
||||
memset(buf, 0, nbuflen);
|
||||
|
||||
if (n == 0) {
|
||||
interface->wrch('0');
|
||||
return;
|
||||
}
|
||||
|
||||
while (n != 0) {
|
||||
char x = n % 10;
|
||||
x += '0';
|
||||
buf[i--] = x;
|
||||
n /= 10;
|
||||
}
|
||||
|
||||
interface->wrbuf(buf+i, nbuflen - i);
|
||||
}
|
||||
|
||||
void
|
||||
write_dnum(IO *interface, KF_LONG n)
|
||||
{
|
||||
static constexpr size_t dnbuflen = 21;
|
||||
char buf[dnbuflen];
|
||||
uint8_t i = dnbuflen - 1;
|
||||
memset(buf, 0, dnbuflen);
|
||||
|
||||
if (n < 0) {
|
||||
interface->wrch('-');
|
||||
}
|
||||
else if (n == 0) {
|
||||
interface->wrch('0');
|
||||
return;
|
||||
}
|
||||
|
||||
while (n != 0) {
|
||||
char x = n % 10;
|
||||
x = x < 0 ? -x : x;
|
||||
x += '0';
|
||||
buf[i--] = x;
|
||||
n /= 10;
|
||||
}
|
||||
|
||||
interface->wrbuf(buf+i, dnbuflen - i);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
write_dstack(IO *interface, Stack<KF_INT> dstack)
|
||||
{
|
||||
KF_INT tmp;
|
||||
interface->wrch('<');
|
||||
for (size_t i = 0; i < dstack.size(); i++) {
|
||||
if (i > 0) {
|
||||
interface->wrch(' ');
|
||||
}
|
||||
|
||||
dstack.get(i, tmp);
|
||||
write_num(interface, tmp);
|
||||
}
|
||||
interface->wrch('>');
|
||||
}
|
||||
33
misc/kforth/v1/io.h
Normal file
33
misc/kforth/v1/io.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __KF_IO_H__
|
||||
#define __KF_IO_H__
|
||||
|
||||
#include "defs.h"
|
||||
#include "stack.h"
|
||||
|
||||
class IO {
|
||||
public:
|
||||
// Virtual destructor is required in all ABCs.
|
||||
virtual ~IO() {};
|
||||
|
||||
// Building block methods.
|
||||
virtual char rdch(void) = 0;
|
||||
virtual void wrch(char c) = 0;
|
||||
|
||||
// Buffer I/O.
|
||||
virtual size_t rdbuf(char *buf, size_t len, bool stopat, char stopch) = 0;
|
||||
virtual void wrbuf(char *buf, size_t len) = 0;
|
||||
|
||||
// Line I/O
|
||||
virtual bool rdln(char *buf, size_t len, size_t *readlen) = 0;
|
||||
virtual void wrln(char *buf, size_t len) = 0;
|
||||
|
||||
virtual void newline(void) = 0;
|
||||
};
|
||||
|
||||
void write_num(IO *, KF_INT);
|
||||
void write_unum(IO *, KF_UINT);
|
||||
void write_dnum(IO *, KF_LONG);
|
||||
void write_dstack(IO *, Stack<KF_INT>);
|
||||
|
||||
|
||||
#endif // __KF_IO_H__
|
||||
89
misc/kforth/v1/kforth.cc
Normal file
89
misc/kforth/v1/kforth.cc
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "dict.h"
|
||||
#include "io.h"
|
||||
#include "parser.h"
|
||||
#include "system.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include "linux.h"
|
||||
#endif // __linux__
|
||||
|
||||
static System sys;
|
||||
#ifndef TRACE_STACK
|
||||
#define TRACE_STACK false
|
||||
#endif
|
||||
|
||||
static bool
|
||||
parser(const char *buf, const size_t buflen)
|
||||
{
|
||||
static size_t offset = 0;
|
||||
static struct Token token;
|
||||
static PARSE_RESULT result = PARSE_FAIL;
|
||||
|
||||
offset = 0;
|
||||
|
||||
// reset token
|
||||
token.token = nullptr;
|
||||
token.length = 0;
|
||||
|
||||
while ((result = parse_next(buf, buflen, &offset, &token)) == PARSE_OK) {
|
||||
if (!lookup(&token, &sys)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
system_write_status(&sys);
|
||||
sys.interface->newline();
|
||||
switch (result) {
|
||||
case PARSE_OK:
|
||||
return false;
|
||||
case PARSE_EOB:
|
||||
return true;
|
||||
case PARSE_LEN:
|
||||
sys.interface->wrln((char *)"parse error: token too long", 27);
|
||||
return false;
|
||||
case PARSE_FAIL:
|
||||
sys.interface->wrln((char *)"parser failure", 14);
|
||||
return false;
|
||||
default:
|
||||
sys.interface->wrln((char *)"*** the world is broken ***", 27);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
interpreter()
|
||||
{
|
||||
static size_t buflen = 0;
|
||||
static char linebuf[81];
|
||||
|
||||
while (true) {
|
||||
if (TRACE_STACK) {
|
||||
write_dstack(sys.interface, sys.dstack);
|
||||
sys.interface->newline();
|
||||
}
|
||||
sys.interface->wrch('?');
|
||||
sys.interface->wrch(' ');
|
||||
buflen = sys.interface->rdbuf(linebuf, 80, true, '\n');
|
||||
parser(linebuf, buflen);
|
||||
}
|
||||
}
|
||||
|
||||
static char banner[] = "kforth interpreter";
|
||||
const size_t bannerlen = 18;
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
reset_system(&sys);
|
||||
init_dict(&sys);
|
||||
#ifdef __linux__
|
||||
Console interface;
|
||||
sys.interface = &interface;
|
||||
#endif
|
||||
sys.interface->wrln(banner, bannerlen);
|
||||
interpreter();
|
||||
return 0;
|
||||
}
|
||||
10
misc/kforth/v1/linux.h
Normal file
10
misc/kforth/v1/linux.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef __KF_LINUX_H__
|
||||
#define __KF_LINUX_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// build support for linux
|
||||
#include "linux/io.h"
|
||||
|
||||
|
||||
#endif // __KF_LINUX_H__
|
||||
15
misc/kforth/v1/linux/defs.h
Normal file
15
misc/kforth/v1/linux/defs.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef __KF_LINUX_DEFS_H__
|
||||
#define __KF_LINUX_DEFS_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int32_t KF_INT;
|
||||
typedef uint32_t KF_UINT;
|
||||
typedef int64_t KF_LONG;
|
||||
|
||||
typedef uintptr_t KF_ADDR;
|
||||
constexpr uint8_t STACK_SIZE = 128;
|
||||
constexpr size_t ARENA_SIZE = 65535;
|
||||
|
||||
#endif
|
||||
82
misc/kforth/v1/linux/io.cc
Normal file
82
misc/kforth/v1/linux/io.cc
Normal file
@@ -0,0 +1,82 @@
|
||||
#include <iostream>
|
||||
#include "../io.h"
|
||||
#include "io.h"
|
||||
|
||||
char
|
||||
Console::rdch()
|
||||
{
|
||||
std::cout.flush();
|
||||
return getchar();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::wrch(char c)
|
||||
{
|
||||
std::cout << c;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
Console::rdbuf(char *buf, size_t len, bool stopat, char stopch)
|
||||
{
|
||||
size_t n = 0;
|
||||
char ch;
|
||||
|
||||
while (n < len) {
|
||||
ch = this->rdch();
|
||||
if (ch == 0x04) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (stopat && stopch == ch) {
|
||||
break;
|
||||
}
|
||||
|
||||
buf[n++] = ch;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::wrbuf(char *buf, size_t len)
|
||||
{
|
||||
for (size_t n = 0; n < len; n++) {
|
||||
this->wrch(buf[n]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Line I/O
|
||||
bool
|
||||
Console::rdln(char *buf, size_t len, size_t *readlen) {
|
||||
size_t n = 0;
|
||||
char ch;
|
||||
bool line = false;
|
||||
|
||||
while (n < len) {
|
||||
ch = this->rdch();
|
||||
|
||||
if (ch == '\n') {
|
||||
line = true;
|
||||
break;
|
||||
}
|
||||
|
||||
buf[n++] = ch;
|
||||
}
|
||||
|
||||
if (nullptr != readlen) {
|
||||
*readlen = n;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Console::wrln(char *buf, size_t len)
|
||||
{
|
||||
this->wrbuf(buf, len);
|
||||
this->wrch(0x0a);
|
||||
}
|
||||
25
misc/kforth/v1/linux/io.h
Normal file
25
misc/kforth/v1/linux/io.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef __KF_IO_LINUX_H__
|
||||
#define __KF_IO_LINUX_H__
|
||||
|
||||
#include "io.h"
|
||||
#include "defs.h"
|
||||
|
||||
class Console : public IO {
|
||||
public:
|
||||
~Console() {};
|
||||
char rdch(void);
|
||||
void wrch(char c);
|
||||
|
||||
// Buffer I/O.
|
||||
size_t rdbuf(char *buf, size_t len, bool stopat, char stopch);
|
||||
void wrbuf(char *buf, size_t len);
|
||||
|
||||
// Line I/O
|
||||
bool rdln(char *buf, size_t len, size_t *readlen);
|
||||
void wrln(char *buf, size_t len);
|
||||
|
||||
void newline(void) { this->wrch('\n'); };
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // __KF_IO_LINUX_H__
|
||||
131
misc/kforth/v1/parser.cc
Normal file
131
misc/kforth/v1/parser.cc
Normal file
@@ -0,0 +1,131 @@
|
||||
#include "defs.h"
|
||||
#include "parser.h"
|
||||
#include "stack.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
static inline void
|
||||
reset(struct Token *t)
|
||||
{
|
||||
t->token = nullptr;
|
||||
t->length = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
match_token(const char *a, const size_t alen,
|
||||
const char *b, const size_t blen)
|
||||
{
|
||||
if (alen != blen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < alen; i++) {
|
||||
if (a[i] == b[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isalpha(a[i]) || !isalpha(b[i])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a[i] ^ 0x20) == b[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a[i] == (b[i] ^ 0x20)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PARSE_RESULT
|
||||
parse_next(const char *buf, const size_t length, size_t *offset,
|
||||
struct Token *token)
|
||||
{
|
||||
size_t cursor = *offset;
|
||||
|
||||
reset(token);
|
||||
if (cursor == length) {
|
||||
return PARSE_EOB;
|
||||
}
|
||||
|
||||
while (cursor <= length) {
|
||||
if (buf[cursor] != ' ') {
|
||||
if (buf[cursor] != '\t') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cursor++;
|
||||
}
|
||||
|
||||
if (cursor == length) {
|
||||
return PARSE_EOB;
|
||||
}
|
||||
|
||||
token->token = (char *)buf + cursor;
|
||||
while ((token->length <= MAX_TOKEN_LENGTH) && (cursor < length)) {
|
||||
if (buf[cursor] != ' ') {
|
||||
if (buf[cursor] != '\t') {
|
||||
cursor++;
|
||||
token->length++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
cursor++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (token->length > MAX_TOKEN_LENGTH) {
|
||||
reset(token);
|
||||
return PARSE_LEN;
|
||||
}
|
||||
|
||||
*offset = cursor;
|
||||
return PARSE_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
parse_num(struct Token *token, KF_INT *n)
|
||||
{
|
||||
KF_INT tmp = 0;
|
||||
uint8_t i = 0;
|
||||
bool sign = false;
|
||||
|
||||
if (token->length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (token->token[i] == '-') {
|
||||
if (token->length == 1) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
sign = true;
|
||||
}
|
||||
|
||||
while (i < token->length) {
|
||||
if (token->token[i] < '0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (token->token[i] > '9') {
|
||||
return false;
|
||||
}
|
||||
|
||||
tmp *= 10;
|
||||
tmp += (uint8_t)(token->token[i] - '0');
|
||||
i++;
|
||||
}
|
||||
|
||||
if (sign) {
|
||||
tmp *= -1;
|
||||
}
|
||||
|
||||
*n = tmp;
|
||||
return true;
|
||||
}
|
||||
27
misc/kforth/v1/parser.h
Normal file
27
misc/kforth/v1/parser.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef __KF_PARSER_H__
|
||||
#define __KF_PARSER_H__
|
||||
|
||||
#include "defs.h"
|
||||
#include "stack.h"
|
||||
|
||||
struct Token {
|
||||
char *token;
|
||||
uint8_t length;
|
||||
};
|
||||
|
||||
typedef enum _PARSE_RESULT_ : uint8_t {
|
||||
PARSE_OK = 0,
|
||||
PARSE_EOB = 1, // end of buffer
|
||||
PARSE_LEN = 2, // token is too long
|
||||
PARSE_FAIL = 3 // catch-all error
|
||||
} PARSE_RESULT;
|
||||
|
||||
bool match_token(const char *, const size_t, const char *, const size_t);
|
||||
PARSE_RESULT parse_next(const char *, const size_t, size_t *, struct Token *);
|
||||
|
||||
// TODO(kyle): investigate a better return value, e.g. to differentiate between
|
||||
// stack failures and parse failures.
|
||||
bool parse_num(struct Token *, KF_INT *);
|
||||
|
||||
|
||||
#endif // __KF_PARSER_H__
|
||||
92
misc/kforth/v1/stack.h
Normal file
92
misc/kforth/v1/stack.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef __KF_STACK_H__
|
||||
#define __KF_STACK_H__
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
template <typename T>
|
||||
class Stack {
|
||||
public:
|
||||
bool push(T val);
|
||||
bool pop(T *val);
|
||||
bool peek(T *val);
|
||||
bool get(size_t, T &);
|
||||
bool remove(size_t, T *);
|
||||
size_t size(void) { return this->arrlen; }
|
||||
void clear(void) { this->arrlen = 0; }
|
||||
private:
|
||||
T arr[STACK_SIZE];
|
||||
size_t arrlen;
|
||||
};
|
||||
|
||||
// push returns false if there was a stack overflow.
|
||||
template <typename T>
|
||||
bool
|
||||
Stack<T>::push(T val)
|
||||
{
|
||||
if ((this->arrlen + 1) > STACK_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->arr[this->arrlen++] = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
// pop returns false if there was a stack underflow.
|
||||
template <typename T>
|
||||
bool
|
||||
Stack<T>::pop(T *val)
|
||||
{
|
||||
if (this->arrlen == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = this->arr[this->arrlen - 1];
|
||||
this->arrlen--;
|
||||
return true;
|
||||
}
|
||||
|
||||
// peek returns false if there was a stack underflow.
|
||||
template <typename T>
|
||||
bool
|
||||
Stack<T>::peek(T *val)
|
||||
{
|
||||
if (this->arrlen == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = this->arr[this->arrlen - 1];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// get returns false on invalid bounds.
|
||||
template <typename T>
|
||||
bool
|
||||
Stack<T>::get(size_t i, T &val)
|
||||
{
|
||||
if (i > this->arrlen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = this->arr[i];
|
||||
return true;
|
||||
}
|
||||
|
||||
// remove returns false on invalid bounds
|
||||
template <typename T>
|
||||
bool
|
||||
Stack<T>::remove(size_t i, T *val)
|
||||
{
|
||||
if (i > this->arrlen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = this->arr[i];
|
||||
for (; i < (arrlen - 1); i++) {
|
||||
this->arr[i] = this->arr[i+1];
|
||||
}
|
||||
arrlen--;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // __KF_STACK_H__
|
||||
74
misc/kforth/v1/system.cc
Normal file
74
misc/kforth/v1/system.cc
Normal file
@@ -0,0 +1,74 @@
|
||||
#include "defs.h"
|
||||
#include "system.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
constexpr static char STATE_STR_OK[] = "ok";
|
||||
constexpr static char STATE_STR_STACK_OVERFLOW[] = "stack overflow";
|
||||
constexpr static char STATE_STR_STACK_UNDERFLOW[] = "stack underflow";
|
||||
constexpr static char STATE_STR_EXECUTION_FAILURE[] = "execution failure";
|
||||
constexpr static char STATE_STR_UNKNOWN_WORD[] = "unknown word";
|
||||
constexpr static char STATE_STR_RSTACK_OVERFLOW[] = "return stack overflow";
|
||||
constexpr static char STATE_STR_RSTACK_UNDERFLOW[] = "return stack underflow";
|
||||
constexpr static char STATE_STR_UNKNOWN_STATE[] = "undefined state";
|
||||
constexpr static char STATE_STR_ERROR_CODE[] = " (error code ";
|
||||
|
||||
void
|
||||
system_clear_error(System *sys)
|
||||
{
|
||||
sys->status = STATUS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
system_write_status(System *sys)
|
||||
{
|
||||
char *buf = nullptr;
|
||||
size_t len = 0;
|
||||
|
||||
if (sys->interface == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (sys->status) {
|
||||
case STATUS_OK:
|
||||
buf = (char *)(STATE_STR_OK);
|
||||
len = sizeof STATE_STR_OK;
|
||||
break;
|
||||
case STATUS_STACK_OVERFLOW:
|
||||
buf = (char *)(STATE_STR_STACK_OVERFLOW);
|
||||
len = sizeof STATE_STR_STACK_OVERFLOW;
|
||||
break;
|
||||
case STATUS_STACK_UNDERFLOW:
|
||||
buf = (char *)(STATE_STR_STACK_UNDERFLOW);
|
||||
len = sizeof STATE_STR_STACK_UNDERFLOW;
|
||||
break;
|
||||
case STATUS_EXECUTION_FAILURE:
|
||||
buf = (char *)(STATE_STR_EXECUTION_FAILURE);
|
||||
len = sizeof STATE_STR_EXECUTION_FAILURE;
|
||||
break;
|
||||
case STATUS_UNKNOWN_WORD:
|
||||
buf = (char *)(STATE_STR_UNKNOWN_WORD);
|
||||
len = sizeof STATE_STR_UNKNOWN_WORD;
|
||||
break;
|
||||
case STATUS_RSTACK_OVERFLOW:
|
||||
buf = (char *)(STATE_STR_RSTACK_OVERFLOW);
|
||||
len = sizeof STATE_STR_RSTACK_OVERFLOW;
|
||||
break;
|
||||
case STATUS_RSTACK_UNDERFLOW:
|
||||
buf = (char *)(STATE_STR_RSTACK_UNDERFLOW);
|
||||
len = sizeof STATE_STR_RSTACK_UNDERFLOW;
|
||||
break;
|
||||
default:
|
||||
buf = (char *)(STATE_STR_UNKNOWN_STATE);
|
||||
len = sizeof STATE_STR_UNKNOWN_STATE;
|
||||
break;
|
||||
}
|
||||
|
||||
sys->interface->wrbuf(buf, len);
|
||||
if (sys->status != STATUS_OK) {
|
||||
sys->interface->wrbuf((char *)STATE_STR_ERROR_CODE, sizeof STATE_STR_ERROR_CODE);
|
||||
write_num(sys->interface, (KF_INT)sys->status);
|
||||
sys->interface->wrch(')');
|
||||
}
|
||||
sys->interface->wrch('.');
|
||||
}
|
||||
32
misc/kforth/v1/system.h
Normal file
32
misc/kforth/v1/system.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef __KF_CORE_H__
|
||||
#define __KF_CORE_H__
|
||||
|
||||
#include "defs.h"
|
||||
#include "io.h"
|
||||
#include "stack.h"
|
||||
|
||||
typedef enum _SYS_STATUS : uint8_t {
|
||||
STATUS_OK = 0,
|
||||
STATUS_STACK_OVERFLOW = 1,
|
||||
STATUS_STACK_UNDERFLOW = 2,
|
||||
STATUS_EXECUTION_FAILURE = 3,
|
||||
STATUS_UNKNOWN_WORD = 4,
|
||||
STATUS_RSTACK_OVERFLOW = 5,
|
||||
STATUS_RSTACK_UNDERFLOW = 6
|
||||
} SYS_STATUS;
|
||||
|
||||
class Word;
|
||||
|
||||
typedef struct _System {
|
||||
Stack<KF_INT> dstack;
|
||||
Stack<KF_ADDR> rstack;
|
||||
IO *interface;
|
||||
Word *dict;
|
||||
SYS_STATUS status;
|
||||
uint8_t arena[ARENA_SIZE];
|
||||
} System;
|
||||
|
||||
void system_clear_error(System *sys);
|
||||
void system_write_status(System *sys);
|
||||
|
||||
#endif // __KF_CORE_H__
|
||||
84
misc/kforth/v1/word.cc
Normal file
84
misc/kforth/v1/word.cc
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "defs.h"
|
||||
#include "parser.h"
|
||||
#include "system.h"
|
||||
#include "word.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
Builtin::Builtin(const char *name, size_t namelen, Word *head, bool (*target)(System *))
|
||||
: prev(head), fun(target)
|
||||
{
|
||||
memcpy(this->name, name, namelen);
|
||||
this->namelen = namelen;
|
||||
}
|
||||
|
||||
bool
|
||||
Builtin::eval(System *sys)
|
||||
{
|
||||
return this->fun(sys);
|
||||
}
|
||||
|
||||
Word *
|
||||
Builtin::next()
|
||||
{
|
||||
return this->prev;
|
||||
}
|
||||
|
||||
bool
|
||||
Builtin::match(struct Token *token)
|
||||
{
|
||||
return match_token(this->name, this->namelen, token->token, token->length);
|
||||
}
|
||||
|
||||
void
|
||||
Builtin::getname(char *buf, size_t *buflen)
|
||||
{
|
||||
memcpy(buf, this->name, this->namelen);
|
||||
*buflen = namelen;
|
||||
}
|
||||
|
||||
|
||||
Address::Address(const char *name, size_t namelen, Word *head, KF_ADDR addr)
|
||||
: prev(head), addr(addr)
|
||||
{
|
||||
memcpy(this->name, name, namelen);
|
||||
this->namelen = namelen;
|
||||
}
|
||||
|
||||
bool
|
||||
Address::eval(System *sys)
|
||||
{
|
||||
KF_INT a;
|
||||
|
||||
a = static_cast<KF_INT>(this->addr & mask(dshift));
|
||||
if (!sys->dstack.push(a)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
a = static_cast<KF_INT>((this->addr >> dshift) & mask(dshift));
|
||||
if (!sys->dstack.push(a)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Word *
|
||||
Address::next(void)
|
||||
{
|
||||
return this->prev;
|
||||
}
|
||||
|
||||
bool
|
||||
Address::match(struct Token *token)
|
||||
{
|
||||
return match_token(this->name, this->namelen, token->token, token->length);
|
||||
}
|
||||
|
||||
void
|
||||
Address::getname(char *buf, size_t *buflen)
|
||||
{
|
||||
memcpy(buf, this->name, this->namelen);
|
||||
*buflen = namelen;
|
||||
}
|
||||
54
misc/kforth/v1/word.h
Normal file
54
misc/kforth/v1/word.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef __KF_WORD_H__
|
||||
#define __KF_WORD_H__
|
||||
|
||||
#include "defs.h"
|
||||
#include "parser.h"
|
||||
#include "stack.h"
|
||||
#include "system.h"
|
||||
|
||||
class Word {
|
||||
public:
|
||||
virtual ~Word() {};
|
||||
|
||||
virtual bool eval(System *) = 0;
|
||||
virtual Word *next(void) = 0;
|
||||
virtual bool match(struct Token *) = 0;
|
||||
virtual void getname(char *, size_t *) = 0;
|
||||
virtual uintptr_t address(void) = 0;
|
||||
};
|
||||
|
||||
class Builtin : public Word {
|
||||
public:
|
||||
~Builtin() {};
|
||||
Builtin(const char *name, size_t namelen, Word *head, bool (*fun)(System *));
|
||||
|
||||
bool eval(System *);
|
||||
Word *next(void);
|
||||
bool match(struct Token *);
|
||||
void getname(char *, size_t *);
|
||||
uintptr_t address(void) { return reinterpret_cast<uintptr_t>(this); }
|
||||
private:
|
||||
char name[MAX_TOKEN_LENGTH];
|
||||
size_t namelen;
|
||||
Word *prev;
|
||||
bool (*fun)(System *);
|
||||
};
|
||||
|
||||
class Address : public Word {
|
||||
public:
|
||||
~Address() {};
|
||||
Address(const char *name, size_t namelen, Word *head, KF_ADDR addr);
|
||||
|
||||
bool eval(System *);
|
||||
Word *next(void);
|
||||
bool match(struct Token *);
|
||||
void getname(char *, size_t *);
|
||||
uintptr_t address(void) { return reinterpret_cast<uintptr_t>(this); }
|
||||
private:
|
||||
char name[MAX_TOKEN_LENGTH];
|
||||
size_t namelen;
|
||||
Word *prev;
|
||||
KF_ADDR addr;
|
||||
};
|
||||
|
||||
#endif // __KF_WORD_H__
|
||||
Reference in New Issue
Block a user