#ifndef ENVIRONMENT_H #define ENVIRONMENT_H #include "object.h" #include "hash.h" struct StrippedObject { Type type; void* data; }; struct EnvElement { char* symbol; struct StrippedObject object; }; struct Environment; struct Environment { struct Environment* outer; struct ObjectTable table; int refs; }; Object deStrip(struct StrippedObject object); struct Environment* global(); void setGlobal(struct Environment* env); Object fetchFromEnvironment(const char* name, struct Environment* env); struct Environment envForLambda(const Object* params, const Object* arguments, int paramCount, struct Environment* outer); void addToEnv(struct Environment* env, const char* name, Object obj); void printEnv(struct Environment* env, int printPointers); void addFunc(const char* name, Object (* func)(Object*, int, struct Environment*), struct Environment* env); void deleteEnv(struct Environment* e); void shredDictionary(); struct Environment defaultEnv(); struct Environment defaultEnvPreAllocated(struct EnvElement* elements); int getStructIndex(const char* name); struct StructDef* getStructAt(int i); void addStructDef(struct StructDef def); void printColored(const char* code); int runTests(int detailed, int specificTest); int getTotalSearchDepth(); int getTotalSearches(); #define unused __attribute__((unused)) #define array_length(_array) (sizeof(_array) / sizeof((_array)[0])) #define fnn(_name, _docs, ...) \ static const char * const _name ## Doc = _docs; \ unused static const char * const _name ## Tests[] = {__VA_ARGS__}; \ _Static_assert(array_length(_name ## Tests) % 2 == 0, "Array of test strings must have exactly one expected result for each test."); \ Object _name(Object* params, int length, struct Environment* env) #define fn(_name, _symbol, _docs, ...) \ static const char * const _name ## Symbol = _symbol; \ fnn(_name, _docs, __VA_ARGS__) fn(segfault, "seg", "Induces a segfault." ); fn(help, "?", "Gets a string with help text or a string representation for the object.\n" "\n" " Function help:\n" " (? islist) => \"(islist (1 2 3)) => T\"\n" "\n" " Struct fields:\n" " (? Output) => \"{ stdout stderr }\"\n" "\n" " Other objects:\n" " (? \"Hello\") => \"Hello\"" ); #endif