#include "ficl.h"
ficlSystem *ficlSystemGlobal = NULL;
static void
ficlSystemSetVersion(ficlSystem *system)
{
int major = FICL_VERSION_MAJOR;
int minor = FICL_VERSION_MINOR;
ficl2Integer combined;
ficlDictionary *environment = ficlSystemGetEnvironment(system);
FICL_2INTEGER_SET(major, minor, combined);
(void) ficlDictionarySet2Constant(environment, "ficl-version",
combined);
(void) ficlDictionarySetConstant(environment, "ficl-robust",
FICL_ROBUST);
}
ficlSystem *
ficlSystemCreate(ficlSystemInformation *fsi)
{
ficlInteger dictionarySize;
ficlInteger environmentSize;
ficlInteger stackSize;
ficlSystem *system;
ficlCallback callback;
ficlSystemInformation fauxInfo;
ficlDictionary *environment;
if (fsi == NULL) {
fsi = &fauxInfo;
ficlSystemInformationInitialize(fsi);
}
callback.context = fsi->context;
callback.textOut = fsi->textOut;
callback.errorOut = fsi->errorOut;
callback.system = NULL;
callback.vm = NULL;
FICL_ASSERT(&callback, sizeof (ficlInteger) >= sizeof (void *));
FICL_ASSERT(&callback, sizeof (ficlUnsigned) >= sizeof (void *));
#if (FICL_WANT_FLOAT)
FICL_ASSERT(&callback, sizeof (ficlFloat) <= sizeof (ficlInteger));
#endif
system = ficlMalloc(sizeof (ficlSystem));
FICL_ASSERT(&callback, system);
memset(system, 0, sizeof (ficlSystem));
dictionarySize = fsi->dictionarySize;
if (dictionarySize <= 0)
dictionarySize = FICL_DEFAULT_DICTIONARY_SIZE;
environmentSize = fsi->environmentSize;
if (environmentSize <= 0)
environmentSize = FICL_DEFAULT_ENVIRONMENT_SIZE;
stackSize = fsi->stackSize;
if (stackSize < FICL_DEFAULT_STACK_SIZE)
stackSize = FICL_DEFAULT_STACK_SIZE;
system->dictionary = ficlDictionaryCreateHashed(system,
(unsigned)dictionarySize, FICL_HASH_SIZE);
system->dictionary->forthWordlist->name = "forth-wordlist";
environment = ficlDictionaryCreate(system, (unsigned)environmentSize);
system->environment = environment;
system->environment->forthWordlist->name = "environment";
system->callback.textOut = fsi->textOut;
system->callback.errorOut = fsi->errorOut;
system->callback.context = fsi->context;
system->callback.system = system;
system->callback.vm = NULL;
system->stackSize = stackSize;
#if FICL_WANT_LOCALS
system->locals = ficlDictionaryCreate(system,
(unsigned)FICL_MAX_LOCALS * FICL_CELLS_PER_WORD);
#endif
ficlSystemCompileCore(system);
ficlSystemCompilePrefix(system);
#if FICL_WANT_FLOAT
ficlSystemCompileFloat(system);
#endif
#if FICL_WANT_PLATFORM
ficlSystemCompilePlatform(system);
#endif
ficlSystemSetVersion(system);
ficlSystemAddPrimitiveParseStep(system, "?word", ficlVmParseWord);
ficlSystemAddPrimitiveParseStep(system, "?prefix", ficlVmParsePrefix);
ficlSystemAddPrimitiveParseStep(system, "?number", ficlVmParseNumber);
#if FICL_WANT_FLOAT
ficlSystemAddPrimitiveParseStep(system, "?float",
ficlVmParseFloatNumber);
#endif
(void) ficlSystemCreateVm(system);
#define ADD_COMPILE_FLAG(name) \
(void) ficlDictionarySetConstant(environment, #name, name)
ADD_COMPILE_FLAG(FICL_WANT_LZ4_SOFTCORE);
ADD_COMPILE_FLAG(FICL_WANT_FILE);
ADD_COMPILE_FLAG(FICL_WANT_FLOAT);
ADD_COMPILE_FLAG(FICL_WANT_DEBUGGER);
ADD_COMPILE_FLAG(FICL_WANT_EXTENDED_PREFIX);
ADD_COMPILE_FLAG(FICL_WANT_USER);
ADD_COMPILE_FLAG(FICL_WANT_LOCALS);
ADD_COMPILE_FLAG(FICL_WANT_OOP);
ADD_COMPILE_FLAG(FICL_WANT_SOFTWORDS);
ADD_COMPILE_FLAG(FICL_WANT_MULTITHREADED);
ADD_COMPILE_FLAG(FICL_WANT_OPTIMIZE);
ADD_COMPILE_FLAG(FICL_WANT_VCALL);
ADD_COMPILE_FLAG(FICL_PLATFORM_ALIGNMENT);
ADD_COMPILE_FLAG(FICL_ROBUST);
#define ADD_COMPILE_STRING(name) \
(void) ficlDictionarySetConstantString(environment, #name, name)
ADD_COMPILE_STRING(FICL_PLATFORM_ARCHITECTURE);
ADD_COMPILE_STRING(FICL_PLATFORM_OS);
ficlSystemCompileSoftCore(system);
ficlSystemDestroyVm(system->vmList);
if (ficlSystemGlobal == NULL)
ficlSystemGlobal = system;
return (system);
}
void
ficlSystemDestroy(ficlSystem *system)
{
if (system->dictionary)
ficlDictionaryDestroy(system->dictionary);
system->dictionary = NULL;
if (system->environment)
ficlDictionaryDestroy(system->environment);
system->environment = NULL;
#if FICL_WANT_LOCALS
if (system->locals)
ficlDictionaryDestroy(system->locals);
system->locals = NULL;
#endif
while (system->vmList != NULL) {
ficlVm *vm = system->vmList;
system->vmList = system->vmList->link;
ficlVmDestroy(vm);
}
if (ficlSystemGlobal == system)
ficlSystemGlobal = NULL;
ficlFree(system);
system = NULL;
}
int
ficlSystemAddParseStep(ficlSystem *system, ficlWord *word)
{
int i;
for (i = 0; i < FICL_MAX_PARSE_STEPS; i++) {
if (system->parseList[i] == NULL) {
system->parseList[i] = word;
return (0);
}
}
return (1);
}
void
ficlSystemAddPrimitiveParseStep(ficlSystem *system, char *name,
ficlParseStep pStep)
{
ficlDictionary *dictionary = system->dictionary;
ficlWord *word;
ficlCell c;
word = ficlDictionaryAppendPrimitive(dictionary, name,
ficlPrimitiveParseStepParen, FICL_WORD_DEFAULT);
c.fn = (void (*)(void))pStep;
ficlDictionaryAppendCell(dictionary, c);
(void) ficlSystemAddParseStep(system, word);
}
ficlVm *
ficlSystemCreateVm(ficlSystem *system)
{
ficlVm *vm = ficlVmCreate(NULL, system->stackSize, system->stackSize);
vm->link = system->vmList;
memcpy(&(vm->callback), &(system->callback), sizeof (system->callback));
vm->callback.vm = vm;
vm->callback.system = system;
system->vmList = vm;
return (vm);
}
void
ficlSystemDestroyVm(ficlVm *vm)
{
ficlSystem *system = vm->callback.system;
ficlVm *pList = system->vmList;
FICL_VM_ASSERT(vm, vm != NULL);
if (system->vmList == vm) {
system->vmList = system->vmList->link;
} else
for (; pList != NULL; pList = pList->link) {
if (pList->link == vm) {
pList->link = vm->link;
break;
}
}
if (pList)
ficlVmDestroy(vm);
}
ficlWord *
ficlSystemLookup(ficlSystem *system, char *name)
{
ficlString s;
FICL_STRING_SET_FROM_CSTRING(s, name);
return (ficlDictionaryLookup(system->dictionary, s));
}
ficlDictionary *
ficlSystemGetDictionary(ficlSystem *system)
{
return (system->dictionary);
}
ficlDictionary *
ficlSystemGetEnvironment(ficlSystem *system)
{
return (system->environment);
}
#if FICL_WANT_LOCALS
ficlDictionary *
ficlSystemGetLocals(ficlSystem *system)
{
return (system->locals);
}
#endif
#if FICL_WANT_LOCALS
ficlWord *
ficlSystemLookupLocal(ficlSystem *system, ficlString name)
{
ficlWord *word = NULL;
ficlDictionary *dictionary = system->dictionary;
ficlHash *hash = ficlSystemGetLocals(system)->forthWordlist;
int i;
ficlUnsigned16 hashCode = ficlHashCode(name);
FICL_SYSTEM_ASSERT(system, hash);
FICL_SYSTEM_ASSERT(system, dictionary);
ficlDictionaryLock(dictionary, FICL_TRUE);
word = ficlHashLookup(hash, name, hashCode);
for (i = (int)dictionary->wordlistCount - 1; (i >= 0) && (!word); --i) {
hash = dictionary->wordlists[i];
word = ficlHashLookup(hash, name, hashCode);
}
ficlDictionaryLock(dictionary, FICL_FALSE);
return (word);
}
#endif