diff --git a/defs.h b/defs.h index 8dff6ad..78314c8 100644 --- a/defs.h +++ b/defs.h @@ -10,5 +10,18 @@ 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__ \ No newline at end of file diff --git a/doc/part-0x07.rst b/doc/part-0x07.rst index 6aa8ff6..8fa0b8e 100644 --- a/doc/part-0x07.rst +++ b/doc/part-0x07.rst @@ -3,3 +3,124 @@ Write You a Forth, 0x07 :date: 2018-03-01 19:31 :tags: wyaf, forth + +At this point, I've finished most of the nucleus layer. All that's left to +implement are ``EXIT``, ``I``, and ``J`` --- the first requires better +execution support, which I'll talk about at the end. The other two, I'm not so +sure about yet. + +However, I made some large changes, so let's dive in. Here's the new Linux +definitions file:: + + #ifndef __KF_LINUX_DEFS_H__ + #define __KF_LINUX_DEFS_H__ + + #include + #include + + 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 + +I've also updated the main ``defs.h`` file to move some constants there:: + + #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__ + +Addresses +^^^^^^^^^ + +The first major change is the addition of the ``KF_ADDR`` type. This is needed +to implement the memory manipulation words. I've added some additional utility +functions for pushing and popping addresses from the data stack; they're stored +as double numbers:: + + static bool + pop_addr(System *sys, KF_ADDR *a) + { + KF_LONG b; + if (!pop_long(sys, &b)) { + // Status is already set. + return false; + } + + *a = static_cast(b); + sys->status = STATUS_OK; + return true; + } + + static bool + push_addr(System *sys, KF_ADDR a) + { + KF_LONG b = static_cast(a); + if (!push_long(sys, b)) { + // Status is already set. + return false; + } + + sys->status = STATUS_OK; + return true; + } + +Now I can actually implement ``!`` and so forth:: + + static bool + store(System *sys) + { + KF_ADDR a = 0; // address + KF_INT b = 0; // value + KF_LONG c = 0; // temporary + + if (!pop_long(sys, &c)) { + sys->status = STATUS_STACK_UNDERFLOW; + return false; + } + a = static_cast(c); + + if (!sys->dstack.pop(&b)) { + sys->status = STATUS_STACK_UNDERFLOW; + return false; + } + + *((KF_INT *)a) = b; + sys->status = STATUS_OK; + return true; + } + +There's definitely a sense of finangling here. + +The return stack +^^^^^^^^^^^^^^^^ + +The ``>R`` series of words requires a \ No newline at end of file diff --git a/linux/defs.h b/linux/defs.h index c007fee..8cec973 100644 --- a/linux/defs.h +++ b/linux/defs.h @@ -7,22 +7,9 @@ typedef int32_t KF_INT; typedef uint32_t KF_UINT; typedef int64_t KF_LONG; -constexpr size_t dshift = (sizeof(KF_INT) * 8) - 1; typedef uintptr_t KF_ADDR; constexpr uint8_t STACK_SIZE = 128; constexpr size_t ARENA_SIZE = 65535; -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 \ No newline at end of file