misc/kforth: Start command processing.
This commit is contained in:
parent
0a010e4527
commit
14dc525084
6
Makefile
6
Makefile
|
@ -3,6 +3,8 @@ CXXFLAGS := -std=$(CXXSTD) -Wall -Werror -g -O0
|
||||||
OBJS := linux/io.o \
|
OBJS := linux/io.o \
|
||||||
io.o \
|
io.o \
|
||||||
parser.o \
|
parser.o \
|
||||||
|
word.o \
|
||||||
|
dict.o \
|
||||||
kforth.o
|
kforth.o
|
||||||
TARGET := kforth
|
TARGET := kforth
|
||||||
|
|
||||||
|
@ -13,3 +15,7 @@ $(TARGET): $(OBJS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJS) $(TARGET)
|
rm -f $(OBJS) $(TARGET)
|
||||||
|
|
||||||
|
install: $(TARGET)
|
||||||
|
cp $(TARGET) ~/bin
|
||||||
|
chmod 0755 ~/bin/$(TARGET)
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
#include "defs.h"
|
||||||
|
#include "dict.h"
|
||||||
|
#include "stack.h"
|
||||||
|
#include "system.h"
|
||||||
|
#include "word.h"
|
||||||
|
|
||||||
|
static bool
|
||||||
|
add(System *sys)
|
||||||
|
{
|
||||||
|
KF_INT a = 0;
|
||||||
|
KF_INT b = 0;
|
||||||
|
if (!sys->dstack.pop(&a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.pop(&b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
a += b;
|
||||||
|
return sys->dstack.push(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
sub(System *sys)
|
||||||
|
{
|
||||||
|
KF_INT a = 0;
|
||||||
|
KF_INT b = 0;
|
||||||
|
if (!sys->dstack.pop(&a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.pop(&b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
b -= a;
|
||||||
|
return sys->dstack.push(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
mul(System *sys)
|
||||||
|
{
|
||||||
|
KF_INT a = 0;
|
||||||
|
KF_INT b = 0;
|
||||||
|
if (!sys->dstack.pop(&a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.pop(&b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
b *= a;
|
||||||
|
return sys->dstack.push(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
div(System *sys)
|
||||||
|
{
|
||||||
|
KF_INT a = 0;
|
||||||
|
KF_INT b = 0;
|
||||||
|
if (!sys->dstack.pop(&a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.pop(&b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
b *= a;
|
||||||
|
return sys->dstack.push(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
swap(System *sys)
|
||||||
|
{
|
||||||
|
KF_INT a = 0;
|
||||||
|
KF_INT b = 0;
|
||||||
|
if (!sys->dstack.pop(&a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.pop(&b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.push(a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sys->dstack.push(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
rot(System *sys)
|
||||||
|
{
|
||||||
|
KF_INT a = 0;
|
||||||
|
KF_INT b = 0;
|
||||||
|
KF_INT c = 0;
|
||||||
|
if (!sys->dstack.pop(&a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.pop(&b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.pop(&c)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.push(b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sys->dstack.push(a)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sys->dstack.push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: print multiple per line
|
||||||
|
static bool
|
||||||
|
definitions(System *sys)
|
||||||
|
{
|
||||||
|
Word *cursor = dict;
|
||||||
|
char buf[MAX_TOKEN_LENGTH];
|
||||||
|
size_t buflen = 0;
|
||||||
|
|
||||||
|
while (cursor != nullptr) {
|
||||||
|
cursor->getname(buf, &buflen);
|
||||||
|
sys->interface->wrln(buf, buflen);
|
||||||
|
cursor = cursor->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init_dict()
|
||||||
|
{
|
||||||
|
dict = new Builtin((const char *)"DEFINITIONS", 11, dict, definitions);
|
||||||
|
dict = new Builtin((const char *)"+", 1, dict, add);
|
||||||
|
dict = new Builtin((const char *)"-", 1, dict, sub);
|
||||||
|
dict = new Builtin((const char *)"*", 1, dict, mul);
|
||||||
|
dict = new Builtin((const char *)"/", 1, dict, div);
|
||||||
|
dict = new Builtin((const char *)"SWAP", 4, dict, swap);
|
||||||
|
dict = new Builtin((const char *)"ROT", 3, dict, rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOOKUP
|
||||||
|
lookup(struct Token *token, System *sys)
|
||||||
|
{
|
||||||
|
Word *cursor = dict;
|
||||||
|
KF_INT n;
|
||||||
|
|
||||||
|
if (parse_num(token, &n)) {
|
||||||
|
if (sys->dstack.push(n)) {
|
||||||
|
return LOOKUP_OK;
|
||||||
|
}
|
||||||
|
return LOOKUP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cursor != nullptr) {
|
||||||
|
if (cursor->match(token)) {
|
||||||
|
if (cursor->eval(sys)) {
|
||||||
|
return LOOKUP_OK;
|
||||||
|
}
|
||||||
|
return LOOKUP_FAILED;
|
||||||
|
}
|
||||||
|
cursor = cursor->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return LOOKUP_NOTFOUND;
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef __KF_DICT_H__
|
||||||
|
#define __KF_DICT_H__
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "system.h"
|
||||||
|
#include "word.h"
|
||||||
|
|
||||||
|
static Word *dict = nullptr;
|
||||||
|
|
||||||
|
typedef enum _LOOKUP_ : uint8_t {
|
||||||
|
LOOKUP_OK = 0, // Lookup executed properly.
|
||||||
|
LOOKUP_NOTFOUND = 1, // The token isn't in the dictionary.
|
||||||
|
LOOKUP_FAILED = 2 // The word failed to execute.
|
||||||
|
} LOOKUP;
|
||||||
|
|
||||||
|
void init_dict(void);
|
||||||
|
LOOKUP lookup(struct Token *, System *);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __KF_DICT_H__
|
|
@ -10,6 +10,7 @@ Contents:
|
||||||
part-0x02
|
part-0x02
|
||||||
part-0x03
|
part-0x03
|
||||||
part-0x04
|
part-0x04
|
||||||
|
part-0x05
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
Write You a Forth, 0x05
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
:date: 2018-02-24 12:23
|
||||||
|
:tags: wyaf, forth
|
||||||
|
|
||||||
|
Today I need to start actually doing things with tokens. This requires two
|
||||||
|
things:
|
||||||
|
|
||||||
|
1. Some idea of what a word is, and
|
||||||
|
2. A dictionary of words
|
||||||
|
|
||||||
|
I started taking some notes on this previously, and I think there are a few
|
||||||
|
kinds of words that are possible:
|
||||||
|
|
||||||
|
1. Numbers (e.g. defining a variable)
|
||||||
|
2. Built-in functions
|
||||||
|
3. Lambda functions (that is, user-defined functions).
|
||||||
|
|
||||||
|
Stage 1 really only needs to incorporate #2, so that's what I'll focus on for
|
||||||
|
now. However, to prepare for the future, I'm going to define a ``Word`` base
|
||||||
|
class and inherit from there. This interface is going to need to be
|
||||||
|
stack-aware, so what I've done is define a ``System`` struct in ``system.h``::
|
||||||
|
|
||||||
|
#ifndef __KF_CORE_H__
|
||||||
|
#define __KF_CORE_H__
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
typedef struct _System {
|
||||||
|
Stack<KF_INT> dstack;
|
||||||
|
} System;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __KF_CORE_H__
|
||||||
|
|
||||||
|
This will let me later add in support for the return stack and other things
|
||||||
|
that might be useful. Other ideas: adding something like an ``errno``
|
||||||
|
equivalent to indicate the last error, and storing a dictionary of words. This
|
||||||
|
will need some restructuring, though. Anyways, this works for now.
|
||||||
|
|
||||||
|
The Word interface
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Now I can start defining a Word.h.
|
10
io.cc
10
io.cc
|
@ -6,7 +6,7 @@
|
||||||
static constexpr size_t nbuflen = 11;
|
static constexpr size_t nbuflen = 11;
|
||||||
|
|
||||||
void
|
void
|
||||||
write_num(IO &interface, KF_INT n)
|
write_num(IO *interface, KF_INT n)
|
||||||
{
|
{
|
||||||
|
|
||||||
// TODO(kyle): make the size of the buffer depend on the size of
|
// TODO(kyle): make the size of the buffer depend on the size of
|
||||||
|
@ -17,8 +17,12 @@ write_num(IO &interface, KF_INT n)
|
||||||
bool neg = n < 0;
|
bool neg = n < 0;
|
||||||
|
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
interface.wrch('-');
|
interface->wrch('-');
|
||||||
n = ~n;
|
n = ~n;
|
||||||
|
if (n == 0) {
|
||||||
|
neg = false;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (n != 0) {
|
while (n != 0) {
|
||||||
|
@ -30,5 +34,5 @@ write_num(IO &interface, KF_INT n)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t buflen = nbuflen - i % nbuflen;
|
uint8_t buflen = nbuflen - i % nbuflen;
|
||||||
interface.wrbuf(buf+i, buflen);
|
interface->wrbuf(buf+i, buflen);
|
||||||
}
|
}
|
2
io.h
2
io.h
|
@ -21,7 +21,7 @@ public:
|
||||||
virtual void wrln(char *buf, size_t len) = 0;
|
virtual void wrln(char *buf, size_t len) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void write_num(IO &, KF_INT);
|
void write_num(IO *, KF_INT);
|
||||||
|
|
||||||
|
|
||||||
#endif // __KF_IO_H__
|
#endif // __KF_IO_H__
|
81
kforth.cc
81
kforth.cc
|
@ -1,6 +1,7 @@
|
||||||
|
#include "dict.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "stack.h"
|
#include "system.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -11,33 +12,33 @@
|
||||||
|
|
||||||
static char ok[] = "ok.\n";
|
static char ok[] = "ok.\n";
|
||||||
static char bye[] = "bye";
|
static char bye[] = "bye";
|
||||||
|
static System sys;
|
||||||
// dstack is the data stack.
|
|
||||||
static Stack<KF_INT> dstack;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_dstack(IO &interface)
|
write_dstack()
|
||||||
{
|
{
|
||||||
KF_INT tmp;
|
KF_INT tmp;
|
||||||
interface.wrch('<');
|
sys.interface->wrch('<');
|
||||||
for (size_t i = 0; i < dstack.size(); i++) {
|
for (size_t i = 0; i < sys.dstack.size(); i++) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
interface.wrch(' ');
|
sys.interface->wrch(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
dstack.get(i, tmp);
|
sys.dstack.get(i, tmp);
|
||||||
write_num(interface, tmp);
|
write_num(sys.interface, tmp);
|
||||||
}
|
}
|
||||||
interface.wrch('>');
|
sys.interface->wrch('>');
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
parser(IO &interface, const char *buf, const size_t buflen)
|
parser(const char *buf, const size_t buflen)
|
||||||
{
|
{
|
||||||
static size_t offset = 0;
|
static size_t offset = 0;
|
||||||
static struct Token token;
|
static struct Token token;
|
||||||
static PARSE_RESULT result = PARSE_FAIL;
|
static PARSE_RESULT result = PARSE_FAIL;
|
||||||
|
static LOOKUP lresult = LOOKUP_FAILED;
|
||||||
|
static bool stop = false;
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
|
@ -46,50 +47,66 @@ parser(IO &interface, const char *buf, const size_t buflen)
|
||||||
token.length = 0;
|
token.length = 0;
|
||||||
|
|
||||||
while ((result = parse_next(buf, buflen, &offset, &token)) == PARSE_OK) {
|
while ((result = parse_next(buf, buflen, &offset, &token)) == PARSE_OK) {
|
||||||
interface.wrbuf((char *)"token: ", 7);
|
lresult = lookup(&token, &sys);
|
||||||
interface.wrbuf(token.token, token.length);
|
switch (lresult) {
|
||||||
interface.wrln((char *)".", 1);
|
case LOOKUP_OK:
|
||||||
|
continue;
|
||||||
|
case LOOKUP_NOTFOUND:
|
||||||
|
sys.interface->wrln((char *)"word not found", 15);
|
||||||
|
stop = true;
|
||||||
|
break;
|
||||||
|
case LOOKUP_FAILED:
|
||||||
|
sys.interface->wrln((char *)"execution failed", 17);
|
||||||
|
stop = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sys.interface->wrln((char *)"*** the world is broken ***", 27);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!parse_num(&token, dstack)) {
|
if (stop) {
|
||||||
interface.wrln((char *)"failed to parse numeric", 23);
|
stop = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary hack until the interpreter is working further.
|
// Temporary hack until the interpreter is working further.
|
||||||
if (match_token(token.token, token.length, bye, 3)) {
|
if (match_token(token.token, token.length, bye, 3)) {
|
||||||
interface.wrln((char *)"Goodbye!", 8);
|
sys.interface->wrln((char *)"Goodbye!", 8);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
|
case PARSE_OK:
|
||||||
|
return false;
|
||||||
case PARSE_EOB:
|
case PARSE_EOB:
|
||||||
interface.wrbuf(ok, 4);
|
sys.interface->wrbuf(ok, 4);
|
||||||
return true;
|
return true;
|
||||||
case PARSE_LEN:
|
case PARSE_LEN:
|
||||||
interface.wrln((char *)"parse error: token too long", 27);
|
sys.interface->wrln((char *)"parse error: token too long", 27);
|
||||||
return false;
|
return false;
|
||||||
case PARSE_FAIL:
|
case PARSE_FAIL:
|
||||||
interface.wrln((char *)"parser failure", 14);
|
sys.interface->wrln((char *)"parser failure", 14);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
interface.wrln((char *)"*** the world is broken ***", 27);
|
sys.interface->wrln((char *)"*** the world is broken ***", 27);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
interpreter(IO &interface)
|
interpreter()
|
||||||
{
|
{
|
||||||
static size_t buflen = 0;
|
static size_t buflen = 0;
|
||||||
static char linebuf[81];
|
static char linebuf[81];
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
write_dstack(interface);
|
write_dstack();
|
||||||
interface.wrch('\n');
|
sys.interface->wrch('\n');
|
||||||
interface.wrch('?');
|
sys.interface->wrch('?');
|
||||||
interface.wrch(' ');
|
sys.interface->wrch(' ');
|
||||||
buflen = interface.rdbuf(linebuf, 80, true, '\n');
|
buflen = sys.interface->rdbuf(linebuf, 80, true, '\n');
|
||||||
parser(interface, linebuf, buflen);
|
parser(linebuf, buflen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,10 +116,12 @@ const size_t bannerlen = 19;
|
||||||
int
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
|
init_dict();
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
Console interface;
|
Console interface;
|
||||||
|
sys.interface = &interface;
|
||||||
#endif
|
#endif
|
||||||
interface.wrbuf(banner, bannerlen);
|
sys.interface->wrbuf(banner, bannerlen);
|
||||||
interpreter(interface);
|
interpreter();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -25,6 +25,9 @@ Console::rdbuf(char *buf, size_t len, bool stopat, char stopch)
|
||||||
|
|
||||||
while (n < len) {
|
while (n < len) {
|
||||||
ch = this->rdch();
|
ch = this->rdch();
|
||||||
|
if (ch == 0x04) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (stopat && stopch == ch) {
|
if (stopat && stopch == ch) {
|
||||||
break;
|
break;
|
||||||
|
|
33
parser.cc
33
parser.cc
|
@ -19,7 +19,22 @@ match_token(const char *a, const size_t alen,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return memcmp(a, b, alen) == 0;
|
for (size_t i = 0; i < alen; i++) {
|
||||||
|
if (a[i] == b[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((a[i] ^ 0x20) == b[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a[i] == (b[i] ^ 0x20)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PARSE_RESULT
|
PARSE_RESULT
|
||||||
|
@ -72,9 +87,9 @@ parse_next(const char *buf, const size_t length, size_t *offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
parse_num(struct Token *token, Stack<KF_INT> &s)
|
parse_num(struct Token *token, KF_INT *n)
|
||||||
{
|
{
|
||||||
KF_INT n = 0;
|
KF_INT tmp = 0;
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
bool sign = false;
|
bool sign = false;
|
||||||
|
|
||||||
|
@ -83,6 +98,9 @@ parse_num(struct Token *token, Stack<KF_INT> &s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token->token[i] == '-') {
|
if (token->token[i] == '-') {
|
||||||
|
if (token->length == 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
sign = true;
|
sign = true;
|
||||||
}
|
}
|
||||||
|
@ -96,14 +114,15 @@ parse_num(struct Token *token, Stack<KF_INT> &s)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
n *= 10;
|
tmp *= 10;
|
||||||
n += (uint8_t)(token->token[i] - '0');
|
tmp += (uint8_t)(token->token[i] - '0');
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sign) {
|
if (sign) {
|
||||||
n *= -1;
|
tmp *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.push(n);
|
*n = tmp;
|
||||||
|
return true;
|
||||||
}
|
}
|
2
parser.h
2
parser.h
|
@ -21,7 +21,7 @@ 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
|
// TODO(kyle): investigate a better return value, e.g. to differentiate between
|
||||||
// stack failures and parse failures.
|
// stack failures and parse failures.
|
||||||
bool parse_num(struct Token *, Stack<KF_INT> &);
|
bool parse_num(struct Token *, KF_INT *);
|
||||||
|
|
||||||
|
|
||||||
#endif // __KF_PARSER_H__
|
#endif // __KF_PARSER_H__
|
||||||
|
|
10
stack.h
10
stack.h
|
@ -7,9 +7,10 @@ template <typename T>
|
||||||
class Stack {
|
class Stack {
|
||||||
public:
|
public:
|
||||||
bool push(T val);
|
bool push(T val);
|
||||||
bool pop(T &val);
|
bool pop(T *val);
|
||||||
bool get(size_t, T &);
|
bool get(size_t, T &);
|
||||||
size_t size(void) { return this->arrlen; };
|
size_t size(void) { return this->arrlen; }
|
||||||
|
void clear(void) { this->arrlen = 0; }
|
||||||
private:
|
private:
|
||||||
T arr[STACK_SIZE];
|
T arr[STACK_SIZE];
|
||||||
size_t arrlen;
|
size_t arrlen;
|
||||||
|
@ -31,14 +32,15 @@ Stack<T>::push(T val)
|
||||||
// pop returns false if there was a stack underflow.
|
// pop returns false if there was a stack underflow.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool
|
bool
|
||||||
Stack<T>::pop(T &val)
|
Stack<T>::pop(T *val)
|
||||||
{
|
{
|
||||||
if (this->arrlen == 0) {
|
if (this->arrlen == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = this->arr[this->arrlen - 1];
|
*val = this->arr[this->arrlen - 1];
|
||||||
this->arrlen--;
|
this->arrlen--;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get returns false on invalid bounds.
|
// get returns false on invalid bounds.
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef __KF_CORE_H__
|
||||||
|
#define __KF_CORE_H__
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
typedef struct _System {
|
||||||
|
Stack<KF_INT> dstack;
|
||||||
|
IO *interface;
|
||||||
|
} System;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __KF_CORE_H__
|
|
@ -0,0 +1,39 @@
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 *);
|
||||||
|
|
||||||
|
private:
|
||||||
|
char name[MAX_TOKEN_LENGTH];
|
||||||
|
size_t namelen;
|
||||||
|
Word *prev;
|
||||||
|
bool (*fun)(System *);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __KF_WORD_H__
|
Loading…
Reference in New Issue