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__
 | 
				
			||||||
							
								
								
									
										85
									
								
								kforth.cc
								
								
								
								
							
							
						
						
									
										85
									
								
								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;
 | 
				
			||||||
		if (!parse_num(&token, dstack)) {
 | 
							case LOOKUP_NOTFOUND:
 | 
				
			||||||
			interface.wrln((char *)"failed to parse numeric", 23);
 | 
								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 (stop) {
 | 
				
			||||||
 | 
								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