Simplify Environment struct.
Fill in envForLambda with errorObjects if not enough are provided. Move addStructDef() into env.c Add dedicated Dictionary struct to env.c env->size -> env->capacity
This commit is contained in:
parent
69cf9212d7
commit
34032cb1c6
100
src/env.c
100
src/env.c
|
@ -8,13 +8,27 @@
|
||||||
#include "web.h"
|
#include "web.h"
|
||||||
#include "plfunc.h"
|
#include "plfunc.h"
|
||||||
|
|
||||||
|
struct Environment* globalEnv;
|
||||||
|
|
||||||
|
struct Environment* global()
|
||||||
|
{
|
||||||
|
return globalEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGlobal(struct Environment* env)
|
||||||
|
{
|
||||||
|
globalEnv = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Dictionary dictionary;
|
||||||
|
|
||||||
Object fetchFromEnvironment(const char* name, struct Environment* env)
|
Object fetchFromEnvironment(const char* name, struct Environment* env)
|
||||||
{
|
{
|
||||||
if (!env) {
|
if (!env) {
|
||||||
return errorObject(NULL_ENV);
|
return errorObject(NULL_ENV);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env->size == 0) {
|
if (env->capacity == 0) {
|
||||||
if (env->outer) {
|
if (env->outer) {
|
||||||
return fetchFromEnvironment(name, env->outer);
|
return fetchFromEnvironment(name, env->outer);
|
||||||
} else {
|
} else {
|
||||||
|
@ -22,7 +36,7 @@ Object fetchFromEnvironment(const char* name, struct Environment* env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < env->size; i++) {
|
for (int i = 0; i < env->capacity; i++) {
|
||||||
if (env->strings[i] == NULL) { printd("Try %d (NULL)\n", i);
|
if (env->strings[i] == NULL) { printd("Try %d (NULL)\n", i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -53,9 +67,7 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms,
|
||||||
|
|
||||||
struct Environment env = {
|
struct Environment env = {
|
||||||
.outer = outer,
|
.outer = outer,
|
||||||
.structCount = 0,
|
.capacity = paramCount,
|
||||||
.structCapacity = 0,
|
|
||||||
.size = paramCount,
|
|
||||||
.refs = 1,
|
.refs = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,10 +87,10 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms,
|
||||||
for (int i = 0; i < paramCount; i++) {
|
for (int i = 0; i < paramCount; i++) {
|
||||||
const char* newObjName = itemAt(params, i)->string;
|
const char* newObjName = itemAt(params, i)->string;
|
||||||
// Eval the `march` list
|
// Eval the `march` list
|
||||||
Object newEnvObj = eval(march, outer);
|
Object newEnvObj = march ? eval(march, outer) : errorObject(NOT_ENOUGH_ARGUMENTS);
|
||||||
addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms?
|
addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms?
|
||||||
cleanObject(&newEnvObj);
|
cleanObject(&newEnvObj);
|
||||||
march = march->forward;
|
march = march ? march->forward : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
|
@ -95,7 +107,7 @@ void addToEnv(struct Environment* env, const char* name, const Object obj)
|
||||||
{
|
{
|
||||||
struct Environment* temp_env = env;
|
struct Environment* temp_env = env;
|
||||||
while (temp_env) {
|
while (temp_env) {
|
||||||
for (int i = 0; i < temp_env->size; i++) {
|
for (int i = 0; i < temp_env->capacity; i++) {
|
||||||
if (temp_env->strings[i] == NULL) {
|
if (temp_env->strings[i] == NULL) {
|
||||||
// Add *new* item to env only if we're in the original scope
|
// Add *new* item to env only if we're in the original scope
|
||||||
if (temp_env == env) {
|
if (temp_env == env) {
|
||||||
|
@ -115,10 +127,10 @@ void addToEnv(struct Environment* env, const char* name, const Object obj)
|
||||||
|
|
||||||
printd("Reallocating environment\n");
|
printd("Reallocating environment\n");
|
||||||
const int inc = 5;
|
const int inc = 5;
|
||||||
const int old_size = env->size;
|
const int old_size = env->capacity;
|
||||||
env->size += inc;
|
env->capacity += inc;
|
||||||
env->strings = realloc(env->strings, sizeof(char*) * env->size);
|
env->strings = realloc(env->strings, sizeof(char*) * env->capacity);
|
||||||
env->objects = realloc(env->objects, sizeof(Object) * env->size);
|
env->objects = realloc(env->objects, sizeof(Object) * env->capacity);
|
||||||
|
|
||||||
for (int j = 0; j < inc; j++) {
|
for (int j = 0; j < inc; j++) {
|
||||||
env->strings[old_size + j] = NULL;
|
env->strings[old_size + j] = NULL;
|
||||||
|
@ -133,8 +145,8 @@ void printEnv(struct Environment* env)
|
||||||
printf("NULL env\n");
|
printf("NULL env\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf("env->size = %d\n", env->size);
|
printf("env->capacity = %d\n", env->capacity);
|
||||||
for (int i = 0; i < env->size; i++) {
|
for (int i = 0; i < env->capacity; i++) {
|
||||||
if (env->strings[i] == NULL) {
|
if (env->strings[i] == NULL) {
|
||||||
printf("env[%d]: NULL %p\n", i, env->strings[i]);
|
printf("env[%d]: NULL %p\n", i, env->strings[i]);
|
||||||
break;
|
break;
|
||||||
|
@ -176,15 +188,18 @@ void deleteEnv(struct Environment* e)
|
||||||
free(e->strings);
|
free(e->strings);
|
||||||
free(e->objects);
|
free(e->objects);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < e->structCount; i++) {
|
void shredDictionary()
|
||||||
free(e->structDefs[i].name);
|
{
|
||||||
for (int j = 0; j < e->structDefs[i].fieldCount; j++) {
|
for (int i = 0; i < dictionary.structCount; i++) {
|
||||||
free(e->structDefs[i].names[j]);
|
free(dictionary.structDefs[i].name);
|
||||||
|
for (int j = 0; j < dictionary.structDefs[i].fieldCount; j++) {
|
||||||
|
free(dictionary.structDefs[i].names[j]);
|
||||||
}
|
}
|
||||||
free(e->structDefs[i].names);
|
free(dictionary.structDefs[i].names);
|
||||||
}
|
}
|
||||||
free(e->structDefs);
|
free(dictionary.structDefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct symFunc {
|
struct symFunc {
|
||||||
|
@ -353,14 +368,19 @@ int runTests(int detailed)
|
||||||
|
|
||||||
struct Environment defaultEnv()
|
struct Environment defaultEnv()
|
||||||
{
|
{
|
||||||
|
if (!helpInitialized) {
|
||||||
|
dictionary = (struct Dictionary) {
|
||||||
|
.structCount = 0,
|
||||||
|
.structCapacity = 8,
|
||||||
|
.structDefs = malloc(sizeof(struct StructDef) * 8),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct Environment e = {
|
struct Environment e = {
|
||||||
.outer = NULL,
|
.outer = NULL,
|
||||||
.strings = calloc(sizeof(char*), MAX_ENV_ELM),
|
.strings = calloc(sizeof(char*), MAX_ENV_ELM),
|
||||||
.objects = malloc(sizeof(Object) * MAX_ENV_ELM),
|
.objects = malloc(sizeof(Object) * MAX_ENV_ELM),
|
||||||
.size = MAX_ENV_ELM,
|
.capacity = MAX_ENV_ELM,
|
||||||
.structCount = 0,
|
|
||||||
.structCapacity = 8,
|
|
||||||
.structDefs = malloc(sizeof(struct StructDef) * 8),
|
|
||||||
.refs = 1,
|
.refs = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -421,24 +441,34 @@ struct Environment defaultEnv()
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getStructIndex(struct Environment* env, const char* name)
|
int getStructIndex(const char* name)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < env->structCount; i++) {
|
for (int i = 0; i < dictionary.structCount; i++) {
|
||||||
if (strcmp(name, env->structDefs[i].name) == 0) {
|
if (strcmp(name, dictionary.structDefs[i].name) == 0) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Environment* globalEnv;
|
struct StructDef* getStructAt(int i)
|
||||||
|
|
||||||
struct Environment* global()
|
|
||||||
{
|
{
|
||||||
return globalEnv;
|
return &dictionary.structDefs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGlobal(struct Environment* env)
|
void addStructDef(struct StructDef def)
|
||||||
{
|
{
|
||||||
globalEnv = env;
|
dictionary.structDefs[dictionary.structCount] = def;
|
||||||
}
|
dictionary.structCount += 1;
|
||||||
|
if (dictionary.structCount == dictionary.structCapacity) {
|
||||||
|
struct StructDef* prev = dictionary.structDefs;
|
||||||
|
int prevCapacity = dictionary.structCapacity;
|
||||||
|
dictionary.structCapacity *= 2;
|
||||||
|
dictionary.structDefs = malloc(sizeof(struct StructDef) * dictionary.structCapacity);
|
||||||
|
for (int i = 0; i < prevCapacity; i++) {
|
||||||
|
dictionary.structDefs[i] = prev[i];
|
||||||
|
}
|
||||||
|
free(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
16
src/env.h
16
src/env.h
|
@ -8,13 +8,15 @@ struct Environment {
|
||||||
char** strings;
|
char** strings;
|
||||||
Object* objects;
|
Object* objects;
|
||||||
struct Environment* outer;
|
struct Environment* outer;
|
||||||
int size;
|
int capacity;
|
||||||
|
|
||||||
|
int refs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Dictionary {
|
||||||
int structCount;
|
int structCount;
|
||||||
int structCapacity;
|
int structCapacity;
|
||||||
struct StructDef* structDefs;
|
struct StructDef* structDefs;
|
||||||
|
|
||||||
int refs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Environment* global();
|
struct Environment* global();
|
||||||
|
@ -37,9 +39,15 @@ void addFunc(const char* name,
|
||||||
|
|
||||||
void deleteEnv(struct Environment* e);
|
void deleteEnv(struct Environment* e);
|
||||||
|
|
||||||
|
void shredDictionary();
|
||||||
|
|
||||||
struct Environment defaultEnv();
|
struct Environment defaultEnv();
|
||||||
|
|
||||||
int getStructIndex(struct Environment* env, const char* name);
|
int getStructIndex(const char* name);
|
||||||
|
|
||||||
|
struct StructDef* getStructAt(int i);
|
||||||
|
|
||||||
|
void addStructDef(struct StructDef def);
|
||||||
|
|
||||||
/// Needs to be freed!
|
/// Needs to be freed!
|
||||||
char* getHelp(const char* symbol);
|
char* getHelp(const char* symbol);
|
||||||
|
|
13
src/object.c
13
src/object.c
|
@ -181,7 +181,7 @@ static const char* errorText[] = {"MISMATCHED_PARENS",
|
||||||
"LISTS_NOT_SAME_SIZE",
|
"LISTS_NOT_SAME_SIZE",
|
||||||
"BAD_NUMBER",
|
"BAD_NUMBER",
|
||||||
"UNSUPPORTED_NUMBER_TYPE",
|
"UNSUPPORTED_NUMBER_TYPE",
|
||||||
"ONLY_ONE_ARGUMENT",
|
"NOT_ENOUGH_ARGUMENTS",
|
||||||
"NOT_A_LIST",
|
"NOT_A_LIST",
|
||||||
"SCRIPT_NOT_FOUND",
|
"SCRIPT_NOT_FOUND",
|
||||||
"NO_CLONE_SPECIFIED",
|
"NO_CLONE_SPECIFIED",
|
||||||
|
@ -225,8 +225,9 @@ int stringStruct(char* dest, const Object* obj)
|
||||||
const char* initial = dest;
|
const char* initial = dest;
|
||||||
dest += sprintf(dest, "{");
|
dest += sprintf(dest, "{");
|
||||||
|
|
||||||
for (int i = 0; i < global()->structDefs[so->definition].fieldCount; i++) {
|
struct StructDef* def = getStructAt(so->definition);
|
||||||
dest += sprintf(dest, " %s: ", global()->structDefs[so->definition].names[i]);
|
for (int i = 0; i < def->fieldCount; i++) {
|
||||||
|
dest += sprintf(dest, " %s: ", def->names[i]);
|
||||||
int isString = so->fields[i].type == TYPE_STRING;
|
int isString = so->fields[i].type == TYPE_STRING;
|
||||||
if (isString) {
|
if (isString) {
|
||||||
dest += sprintf(dest, "\"");
|
dest += sprintf(dest, "\"");
|
||||||
|
@ -453,7 +454,7 @@ void cleanObject(Object* target)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_STRUCT:
|
case TYPE_STRUCT:
|
||||||
for (int i = 0; i < global()->structDefs[target->structObject->definition].fieldCount; i++) {
|
for (int i = 0; i < getStructAt(target->structObject->definition)->fieldCount; i++) {
|
||||||
cleanObject(&target->structObject->fields[i]);
|
cleanObject(&target->structObject->fields[i]);
|
||||||
}
|
}
|
||||||
free(target->structObject->fields);
|
free(target->structObject->fields);
|
||||||
|
@ -587,7 +588,7 @@ inline Object structObject(int definition)
|
||||||
Object structo = newObject(TYPE_STRUCT);
|
Object structo = newObject(TYPE_STRUCT);
|
||||||
structo.structObject = malloc(sizeof(struct StructObject));
|
structo.structObject = malloc(sizeof(struct StructObject));
|
||||||
structo.structObject->definition = definition;
|
structo.structObject->definition = definition;
|
||||||
structo.structObject->fields = malloc(sizeof(Object) * global()->structDefs[definition].fieldCount);
|
structo.structObject->fields = malloc(sizeof(Object) * getStructAt(definition)->fieldCount);
|
||||||
return structo;
|
return structo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,7 +686,7 @@ Object cloneStruct(const Object src)
|
||||||
{
|
{
|
||||||
Object structo = structObject(src.structObject->definition);
|
Object structo = structObject(src.structObject->definition);
|
||||||
struct StructObject* so = structo.structObject;
|
struct StructObject* so = structo.structObject;
|
||||||
for (int i = 0; i < global()->structDefs[so->definition].fieldCount; i++) {
|
for (int i = 0; i < getStructAt(so->definition)->fieldCount; i++) {
|
||||||
so->fields[i] = cloneObject(src.structObject->fields[i]);
|
so->fields[i] = cloneObject(src.structObject->fields[i]);
|
||||||
}
|
}
|
||||||
return structo;
|
return structo;
|
||||||
|
|
|
@ -53,7 +53,7 @@ enum errorCode {
|
||||||
LISTS_NOT_SAME_SIZE,
|
LISTS_NOT_SAME_SIZE,
|
||||||
BAD_NUMBER,
|
BAD_NUMBER,
|
||||||
UNSUPPORTED_NUMBER_TYPE,
|
UNSUPPORTED_NUMBER_TYPE,
|
||||||
ONLY_ONE_ARGUMENT,
|
NOT_ENOUGH_ARGUMENTS,
|
||||||
NOT_A_LIST,
|
NOT_A_LIST,
|
||||||
SCRIPT_NOT_FOUND,
|
SCRIPT_NOT_FOUND,
|
||||||
NO_CLONE_SPECIFIED,
|
NO_CLONE_SPECIFIED,
|
||||||
|
|
|
@ -76,20 +76,7 @@ Object evalStructArgs(const Object* symbol, const Object* fields, struct Environ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
env = global();
|
addStructDef(def);
|
||||||
|
|
||||||
env->structDefs[env->structCount] = def;
|
|
||||||
env->structCount += 1;
|
|
||||||
if (env->structCount == env->structCapacity) {
|
|
||||||
struct StructDef* prev = env->structDefs;
|
|
||||||
int prevCapacity = env->structCapacity;
|
|
||||||
env->structCapacity *= 2;
|
|
||||||
env->structDefs = malloc(sizeof(struct StructDef) * env->structCapacity);
|
|
||||||
for (int i = 0; i < prevCapacity; i++) {
|
|
||||||
env->structDefs[i] = prev[i];
|
|
||||||
}
|
|
||||||
free(prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
return boolObject(1);
|
return boolObject(1);
|
||||||
}
|
}
|
||||||
|
@ -269,19 +256,17 @@ Object evalList(const Object* obj, struct Environment* env)
|
||||||
return builtIn;
|
return builtIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Environment* outerEnv = global();
|
int i = getStructIndex(first_form->string);
|
||||||
for (int i = 0; i < outerEnv->structCount; i++) {
|
if (i >= 0) {
|
||||||
if (strcmp(first_form->string, outerEnv->structDefs[i].name) == 0) {
|
Object structo = structObject(i);
|
||||||
Object structo = structObject(i);
|
int s = 0;
|
||||||
int s = 0;
|
FOR_POINTER_IN_LIST(obj) {
|
||||||
FOR_POINTER_IN_LIST(obj) {
|
if (s != 0) { // Skip the field name
|
||||||
if (s != 0) { // Skip the field name
|
structo.structObject->fields[s - 1] = eval(POINTER, env);
|
||||||
structo.structObject->fields[s - 1] = eval(POINTER, env);
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
}
|
}
|
||||||
return structo;
|
s++;
|
||||||
}
|
}
|
||||||
|
return structo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,9 +345,9 @@ Object possessive(Object* params, int length, struct Environment* env)
|
||||||
return errorObject(NULL_PARSE);
|
return errorObject(NULL_PARSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StructDef structDef = global()->structDefs[structo.structObject->definition];
|
struct StructDef* structDef = getStructAt(structo.structObject->definition);
|
||||||
for (int i = 0; i < structDef.fieldCount; i++) {
|
for (int i = 0; i < structDef->fieldCount; i++) {
|
||||||
if (strcmp(field.string, structDef.names[i]) == 0) {
|
if (strcmp(field.string, structDef->names[i]) == 0) {
|
||||||
return cloneObject(structo.structObject->fields[i]);
|
return cloneObject(structo.structObject->fields[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -696,6 +681,7 @@ int main(int argc, const char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
|
shredDictionary();
|
||||||
deleteEnv(global());
|
deleteEnv(global());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -727,6 +713,7 @@ int main(int argc, const char* argv[])
|
||||||
repl(&env);
|
repl(&env);
|
||||||
}
|
}
|
||||||
deleteEnv(&env);
|
deleteEnv(&env);
|
||||||
|
shredDictionary();
|
||||||
// printf("TOTAL ALLOCATIONS: %d\n", getAllocations());
|
// printf("TOTAL ALLOCATIONS: %d\n", getAllocations());
|
||||||
// printf("TOTAL BYTES: %d\n", getBytes());
|
// printf("TOTAL BYTES: %d\n", getBytes());
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,7 +269,7 @@ Object _basicOp(const Object* obj1, const Object* obj2, const char op,
|
||||||
Object basicOp(const Object* obj1, const Object* obj2, const char op,
|
Object basicOp(const Object* obj1, const Object* obj2, const char op,
|
||||||
struct Environment* env)
|
struct Environment* env)
|
||||||
{
|
{
|
||||||
if (isError(*obj2, ONLY_ONE_ARGUMENT)) {
|
if (isError(*obj2, NOT_ENOUGH_ARGUMENTS)) {
|
||||||
return *obj2;
|
return *obj2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ void initialize()
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
Object o = parseEval("(struct Request (queryParams))", global());
|
Object o = parseEval("(struct Request (queryParams))", global());
|
||||||
cleanObject(&o);
|
cleanObject(&o);
|
||||||
requestDefinition = getStructIndex(global(), "Request");
|
requestDefinition = getStructIndex("Request");
|
||||||
}
|
}
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue