#include <string.h>
#include "ficl.h"
static void
ficlPrimitiveDefinitions(ficlVm *vm)
{
ficlDictionary *dictionary = ficlVmGetDictionary(vm);
FICL_VM_ASSERT(vm, dictionary);
if (dictionary->wordlistCount < 1) {
ficlVmThrowError(vm, "DEFINITIONS error - empty search order");
}
dictionary->compilationWordlist =
dictionary->wordlists[dictionary->wordlistCount-1];
}
static void
ficlPrimitiveForthWordlist(ficlVm *vm)
{
ficlHash *hash = ficlVmGetDictionary(vm)->forthWordlist;
ficlStackPushPointer(vm->dataStack, hash);
}
static void
ficlPrimitiveGetCurrent(ficlVm *vm)
{
ficlDictionary *dictionary = ficlVmGetDictionary(vm);
ficlDictionaryLock(dictionary, FICL_TRUE);
ficlStackPushPointer(vm->dataStack, dictionary->compilationWordlist);
ficlDictionaryLock(dictionary, FICL_FALSE);
}
static void
ficlPrimitiveGetOrder(ficlVm *vm)
{
ficlDictionary *dictionary = ficlVmGetDictionary(vm);
int wordlistCount = dictionary->wordlistCount;
int i;
ficlDictionaryLock(dictionary, FICL_TRUE);
for (i = 0; i < wordlistCount; i++) {
ficlStackPushPointer(vm->dataStack, dictionary->wordlists[i]);
}
ficlStackPushUnsigned(vm->dataStack, wordlistCount);
ficlDictionaryLock(dictionary, FICL_FALSE);
}
static void
ficlPrimitiveSearchWordlist(ficlVm *vm)
{
ficlString name;
ficlUnsigned16 hashCode;
ficlWord *word;
ficlHash *hash = ficlStackPopPointer(vm->dataStack);
name.length = (ficlUnsigned8)ficlStackPopUnsigned(vm->dataStack);
name.text = ficlStackPopPointer(vm->dataStack);
hashCode = ficlHashCode(name);
ficlDictionaryLock(ficlVmGetDictionary(vm), FICL_TRUE);
word = ficlHashLookup(hash, name, hashCode);
ficlDictionaryLock(ficlVmGetDictionary(vm), FICL_FALSE);
if (word) {
ficlStackPushPointer(vm->dataStack, word);
ficlStackPushInteger(vm->dataStack,
(ficlWordIsImmediate(word) ? 1 : -1));
} else {
ficlStackPushUnsigned(vm->dataStack, 0);
}
}
static void
ficlPrimitiveSetCurrent(ficlVm *vm)
{
ficlHash *hash = ficlStackPopPointer(vm->dataStack);
ficlDictionary *dictionary = ficlVmGetDictionary(vm);
ficlDictionaryLock(dictionary, FICL_TRUE);
dictionary->compilationWordlist = hash;
ficlDictionaryLock(dictionary, FICL_FALSE);
}
static void
ficlPrimitiveSetOrder(ficlVm *vm)
{
int i;
int wordlistCount = ficlStackPopInteger(vm->dataStack);
ficlDictionary *dictionary = ficlVmGetDictionary(vm);
if (wordlistCount > FICL_MAX_WORDLISTS) {
ficlVmThrowError(vm,
"set-order error: list would be too large");
}
ficlDictionaryLock(dictionary, FICL_TRUE);
if (wordlistCount >= 0) {
dictionary->wordlistCount = wordlistCount;
for (i = wordlistCount-1; i >= 0; --i) {
dictionary->wordlists[i] =
ficlStackPopPointer(vm->dataStack);
}
} else {
ficlDictionaryResetSearchOrder(dictionary);
}
ficlDictionaryLock(dictionary, FICL_FALSE);
}
static void
ficlPrimitiveFiclWordlist(ficlVm *vm)
{
ficlDictionary *dictionary = ficlVmGetDictionary(vm);
ficlHash *hash;
ficlUnsigned nBuckets;
FICL_STACK_CHECK(vm->dataStack, 1, 1);
nBuckets = ficlStackPopUnsigned(vm->dataStack);
hash = ficlDictionaryCreateWordlist(dictionary, nBuckets);
ficlStackPushPointer(vm->dataStack, hash);
}
static void
ficlPrimitiveSearchPop(ficlVm *vm)
{
ficlDictionary *dictionary = ficlVmGetDictionary(vm);
int wordlistCount;
ficlDictionaryLock(dictionary, FICL_TRUE);
wordlistCount = dictionary->wordlistCount;
if (wordlistCount == 0) {
ficlVmThrowError(vm, "search> error: empty search order");
}
ficlStackPushPointer(vm->dataStack,
dictionary->wordlists[--dictionary->wordlistCount]);
ficlDictionaryLock(dictionary, FICL_FALSE);
}
static void
ficlPrimitiveSearchPush(ficlVm *vm)
{
ficlDictionary *dictionary = ficlVmGetDictionary(vm);
ficlDictionaryLock(dictionary, FICL_TRUE);
if (dictionary->wordlistCount > FICL_MAX_WORDLISTS) {
ficlVmThrowError(vm, ">search error: search order overflow");
}
dictionary->wordlists[dictionary->wordlistCount++] =
ficlStackPopPointer(vm->dataStack);
ficlDictionaryLock(dictionary, FICL_FALSE);
}
static void
ficlPrimitiveWidGetName(ficlVm *vm)
{
ficlHash *hash;
char *name;
ficlInteger length;
ficlCell c;
hash = ficlVmPop(vm).p;
name = hash->name;
if (name != NULL)
length = strlen(name);
else
length = 0;
c.p = name;
ficlVmPush(vm, c);
c.i = length;
ficlVmPush(vm, c);
}
static void
ficlPrimitiveWidSetName(ficlVm *vm)
{
char *name = (char *)ficlVmPop(vm).p;
ficlHash *hash = ficlVmPop(vm).p;
hash->name = name;
}
static void
ficlPrimitiveSetParentWid(ficlVm *vm)
{
ficlHash *parent, *child;
FICL_STACK_CHECK(vm->dataStack, 2, 0);
child = (ficlHash *)ficlStackPopPointer(vm->dataStack);
parent = (ficlHash *)ficlStackPopPointer(vm->dataStack);
child->link = parent;
}
void
ficlSystemCompileSearch(ficlSystem *system)
{
ficlDictionary *dictionary = ficlSystemGetDictionary(system);
ficlDictionary *environment = ficlSystemGetEnvironment(system);
FICL_SYSTEM_ASSERT(system, dictionary);
FICL_SYSTEM_ASSERT(system, environment);
(void) ficlDictionarySetPrimitive(dictionary, ">search",
ficlPrimitiveSearchPush, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "search>",
ficlPrimitiveSearchPop, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "definitions",
ficlPrimitiveDefinitions, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "forth-wordlist",
ficlPrimitiveForthWordlist, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "get-current",
ficlPrimitiveGetCurrent, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "get-order",
ficlPrimitiveGetOrder, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "search-wordlist",
ficlPrimitiveSearchWordlist, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "set-current",
ficlPrimitiveSetCurrent, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "set-order",
ficlPrimitiveSetOrder, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "ficl-wordlist",
ficlPrimitiveFiclWordlist, FICL_WORD_DEFAULT);
(void) ficlDictionarySetConstant(environment, "search-order",
FICL_TRUE);
(void) ficlDictionarySetConstant(environment, "search-order-ext",
FICL_TRUE);
(void) ficlDictionarySetConstant(environment, "wordlists",
FICL_MAX_WORDLISTS);
(void) ficlDictionarySetPrimitive(dictionary, "wid-get-name",
ficlPrimitiveWidGetName, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "wid-set-name",
ficlPrimitiveWidSetName, FICL_WORD_DEFAULT);
(void) ficlDictionarySetPrimitive(dictionary, "wid-set-super",
ficlPrimitiveSetParentWid, FICL_WORD_DEFAULT);
}