Extremely barebones struct object implementation.

This commit is contained in:
Sage Vaillancourt 2022-03-14 16:51:45 -04:00 committed by Sage Vaillancourt
parent e2c977e95a
commit 6c8ff04711
6 changed files with 208 additions and 31 deletions

View File

@ -3,6 +3,8 @@ exe = pl
BINPREFIX ?= /usr/bin
SCRIPTDIR ?= /usr/local/share/pebblisp
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
mkfile_dir := $(dir $(mkfile_path))
GCC_COM ?= gcc -g -O0 -Wall -o $(exe) -D STANDALONE -DSCRIPTDIR=\"$(SCRIPTDIR)\"
@ -12,6 +14,9 @@ all:
notest:
$(GCC_COM) $(files)
local:
gcc -g -O0 -Wall -o $(exe) -D STANDALONE -DSCRIPTDIR=\"$(mkfile_dir)/examples\" $(files)
val:
$(GCC_COM) $(files) && ./tests.sh -val

View File

@ -50,6 +50,7 @@ struct Environment envForLambda(const Object* params, const Object* arg_forms,
struct Environment env = {.outer = outer,
.strings = NULL,
.objects = NULL,
.structCount = 0,
.size = paramCount};
if (paramCount == 0) {
@ -210,6 +211,7 @@ struct Environment defaultEnv()
.strings = strings,
.objects = objects,
.size = size,
.structCount = 0,
};
struct symFunc symFuncs[] = {
@ -243,7 +245,7 @@ struct Environment defaultEnv()
{"prn", &print},
{"pch", &pChar},
{"penv", &printEnvO},
{"sys", &systemCall},
//{"sys", &systemCall},
{"loadfile", &loadFile},
{"inp", &takeInput},
#endif

View File

@ -9,6 +9,9 @@ struct Environment {
Object* objects;
struct Environment* outer;
int size;
int structCount;
struct StructDef* structDefs;
};
Object fetchFromEnvironment(const char* name, struct Environment* env);

View File

@ -95,6 +95,8 @@ inline int isEmpty(const Object* obj)
return obj->list == NULL;
case TYPE_LAMBDA:
return obj->lambda == NULL;
case TYPE_STRUCT:
return obj->structObject == NULL;
case TYPE_SYMBOL:
case TYPE_STRING:
return obj->string == NULL || obj->string[0] == '\0';
@ -109,6 +111,7 @@ inline int isEmpty(const Object* obj)
return 0;
}
int allocations = 0;
/**
* Allocate a copy of a given object into the given pointer.
* Does nothing if `spot` is NULL
@ -117,6 +120,12 @@ inline int isEmpty(const Object* obj)
*/
void allocObject(Object** spot, const Object src)
{
if (allocations >= 10000) {
printf("MAX ALLOCATIONS EXCEEDED\n");
*spot = NULL;
return;
}
allocations++;
*spot = malloc(sizeof(struct Object));
**spot = src;
(*spot)->forward = NULL;
@ -247,6 +256,42 @@ void stringList(char* dest, const Object* obj)
strcat(dest, " )");
}
/**
* Creates a string from a given struct Object
* Blocks out with curly braces
*/
void stringStruct(char* dest, const Object* obj)
{
struct StructObject* so = obj->structObject;
dest[0] = '{';
dest[1] = '\0';
for (int i = 0; i < so->definition->fieldCount; i++) {
strcat(dest, " ");
strcat(dest, so->definition->names[i]);
strcat(dest, ": ");
int isString = so->fields[i].type == TYPE_STRING;
if (isString) {
strcat(dest, "\"");
}
char tok[90] = "";
stringObj(tok, &so->fields[i]);
strcat(dest, tok);
if (isString) {
strcat(dest, "\"");
}
strcat(dest, ",");
}
int i = 0;
while (dest[i]) {
i++;
}
dest[i - 1] = ' ';
dest[i + 0] = '}';
dest[i + 1] = '\0';
}
/**
* Creates a string from a given Object
* Returns NULL if either param is NULL
@ -282,6 +327,10 @@ char* stringNObj(char* dest, const Object* obj, const size_t len)
case TYPE_SYMBOL:
snprintf(dest, len, "`%s`", obj->string);
break;
case TYPE_STRUCT:
//snprintf(dest, len, "{%s}", obj->structObject->definition->names[0]);
stringStruct(dest, obj);
break;
case TYPE_LIST:
case TYPE_SLIST:
stringList(dest, obj);
@ -335,38 +384,26 @@ void debugObj(const Object* obj)
#if defined(DEBUG) || defined(STANDALONE)
#define SIMPLE_TYPE(_type) case _type:\
printf(#_type);\
return
void printType(const Object* obj)
{
switch (obj->type) {
case TYPE_NUMBER:
printf("TYPE_NUMBER");
return;
case TYPE_BOOL:
printf("TYPE_BOOL");
return;
case TYPE_LIST:
printf("TYPE_LIST");
return;
case TYPE_SLIST:
printf("TYPE_SLIST");
return;
case TYPE_FUNC:
printf("TYPE_FUNC");
return;
case TYPE_SYMBOL:
printf("TYPE_SYMBOL");
return;
case TYPE_STRING:
printf("TYPE_STRING");
return;
SIMPLE_TYPE(TYPE_NUMBER);
SIMPLE_TYPE(TYPE_STRUCT);
SIMPLE_TYPE(TYPE_BOOL);
SIMPLE_TYPE(TYPE_LIST);
SIMPLE_TYPE(TYPE_SLIST);
SIMPLE_TYPE(TYPE_FUNC);
SIMPLE_TYPE(TYPE_SYMBOL);
SIMPLE_TYPE(TYPE_STRING);
SIMPLE_TYPE(TYPE_OTHER);
SIMPLE_TYPE(TYPE_ERROR);
case TYPE_LAMBDA:
printf("TYPE_LAMBDA Params:\n");
return;
case TYPE_OTHER:
printf("TYPE_OTHER: ");
case TYPE_ERROR:
printf("TYPE_ERROR: ");
return;
}
if (!isValidType(*obj)) {
@ -467,10 +504,18 @@ void cleanObject(Object* target)
cleanObject(&target->lambda->body);
free(target->lambda);
break;
case TYPE_STRUCT:
for (int i = 0; i < target->structObject->definition->fieldCount; i++) {
cleanObject(&target->structObject->fields[i]);
}
free(target->structObject->fields);
free(target->structObject);
target->structObject = NULL;
break;
case TYPE_ERROR:
#ifndef SIMPLE_ERRORS
free(target->error->context);
free(target->error);
//free(target->error->context);
//free(target->error);
target->error = NULL;
#endif
break;
@ -605,6 +650,16 @@ inline Object listObject()
return list;
}
// Returns an empty struct Object
inline Object structObject(struct StructDef *definition)
{
Object structo = newObject(TYPE_STRUCT);
structo.structObject = malloc(sizeof(struct StructObject));
structo.structObject->definition = definition;
structo.structObject->fields = malloc(sizeof(Object) * definition->fieldCount);
return structo;
}
// Returns a list Object starting with the given Object
inline Object startList(const Object start)
{
@ -629,6 +684,7 @@ inline int isValidType(const Object test)
case TYPE_NUMBER:
case TYPE_BOOL:
case TYPE_LIST:
case TYPE_STRUCT:
case TYPE_SLIST:
case TYPE_FUNC:
case TYPE_SYMBOL:
@ -673,6 +729,8 @@ inline Object cloneOther(const Object src)
return src.other->clone ? src.other->clone(src.other) : src;
}
Object cloneStruct(const Object src);
inline Object cloneObject(const Object src)
{
switch (src.type) {
@ -681,6 +739,8 @@ inline Object cloneObject(const Object src)
return cloneList(src);
case TYPE_LAMBDA:
return cloneLambda(src);
case TYPE_STRUCT:
return cloneStruct(src);
case TYPE_STRING:
case TYPE_SYMBOL:
return cloneString(src);
@ -696,6 +756,16 @@ inline Object cloneObject(const Object src)
return src;
}
Object cloneStruct(const Object src)
{
Object structo = structObject(src.structObject->definition);
struct StructObject* so = structo.structObject;
for (int i = 0; i < so->definition->fieldCount; i++) {
so->fields[i] = cloneObject(src.structObject->fields[i]);
}
return structo;
}
inline Object numberObject(int num)
{
Object o = newObject(TYPE_NUMBER);

View File

@ -72,6 +72,7 @@ typedef enum Type {
TYPE_BOOL,
TYPE_LIST,
TYPE_SLIST,
TYPE_STRUCT,
TYPE_FUNC,
TYPE_SYMBOL,
TYPE_LAMBDA,
@ -81,6 +82,7 @@ typedef enum Type {
} Type;
typedef struct Object Object;
struct Lambda;
struct Environment;
struct Slice;
@ -101,6 +103,7 @@ struct Object {
Object (*func)(Object, Object, struct Environment *);
struct StructObject *structObject;
struct Lambda *lambda;
struct Other *other;
#ifdef SIMPLE_ERRORS
@ -111,6 +114,17 @@ struct Object {
};
};
struct StructDef {
int fieldCount;
char* name;
const char** names;
};
struct StructObject {
struct StructDef *definition;
struct Object* fields; // Order should match that in the definition.
};
struct Lambda {
Object params;
Object body;
@ -204,6 +218,8 @@ Object boolObject(int b);
Object numberObject(int num);
Object structObject(struct StructDef *definition);
Object otherObject();
Object errorObject(enum errorCode err);

View File

@ -43,6 +43,52 @@ Object evalDefArgs(const Object* symbol, const Object* value,
return cloneObject(*symbol);
}
void printStructDef(const struct StructDef *def)
{
printf("%s: {\n", def->name);
for (int i = 0; i < def->fieldCount; i++) {
printf(" %s,\n", def->names[i]);
}
printf("}\n");
}
/**
* Add a struct to the environment with a given name and fields.
*
* (struct point (x y))
*/
Object evalStructArgs(const Object* symbol, const Object* fields, struct Environment* env)
{
const char* name = symbol->string;
if (!isListy(*fields)) {
return errorObject(NOT_A_LIST);
}
struct StructDef def;
//def.name = name;
def.name = malloc(sizeof(char) * (strlen(name) + 1));
strcpy(def.name, name);
def.fieldCount = listLength(fields);
def.names = malloc(sizeof(char*) * def.fieldCount);
int i = 0;
FOR_POINTER_IN_LIST(fields) {
def.names[i] = POINTER->string;
i++;
}
while (env->outer) {
env = env->outer;
}
env->structDefs = malloc(sizeof(struct StructDef) * 1);
env->structCount = 1;
env->structDefs[0] = def;
printStructDef(&env->structDefs[0]);
return boolObject(1);
}
Object evalIfArgs(const Object* argForms, struct Environment* env)
{
Object condition = eval(argForms, env);
@ -118,6 +164,8 @@ Object evalBuiltIns(const Object* first, const Object* rest,
return evalLambdaArgs(rest);
} else if (strcmp(first->string, "map") == 0) {
return evalMapArgs(rest, env);
} else if (strcmp(first->string, "struct") == 0) {
return evalStructArgs(rest, rest->forward, env);
}
return errorObject(BUILT_IN_NOT_FOUND);
@ -246,7 +294,6 @@ Object evalList(const Object* obj, struct Environment* env)
}
Object* first_form = obj->list;
{ // Try to eval built-ins
Object builtIn = evalBuiltIns(first_form, first_form->forward, env);
@ -257,6 +304,36 @@ Object evalList(const Object* obj, struct Environment* env)
cleanObject(&builtIn);
}
struct StructDef *def = NULL;
if (first_form->type == TYPE_SYMBOL) {
struct Environment* outerEnv = env;
while (outerEnv->outer) {
outerEnv = outerEnv->outer;
}
//printf("evalList firstElementName: %s\n", first_form->string);
//printf("checking for struct `%s`\n", first_form->string);
//printf("%d structs available\n", outerEnv->structCount);
for (int i = 0; i < outerEnv->structCount; i++) {
//printf("struct[%d] - `%s`\n", i, outerEnv->structDefs[i].name);
if (strcmp(first_form->string, outerEnv->structDefs[i].name) == 0) {
def = &outerEnv->structDefs[i];
printf("Found struct definition for %s!\n", first_form->string);
break;
}
}
}
if (def) {
Object structo = structObject(def);
int i = 0;
FOR_POINTER_IN_LIST(obj) {
if (i != 0) {
structo.structObject->fields[i - 1] = eval(POINTER, env);
}
i++;
}
return structo;
}
// Evaluate the list based on the first element's type
Object first_eval = eval(first_form, env);
switch (first_eval.type) {
@ -273,6 +350,9 @@ Object evalList(const Object* obj, struct Environment* env)
nf_addToList(&list, first_eval);
FOR_POINTER_IN_LIST(obj) {
if (i != 0) {
if (isStringy(*POINTER)) {
printf("evalList elementName: %s\n", POINTER->string);
}
nf_addToList(&list, eval(POINTER, env));
}
i++;
@ -291,6 +371,7 @@ Object eval(const Object* obj, struct Environment* env)
case TYPE_NUMBER:
case TYPE_BOOL:
case TYPE_STRING:
case TYPE_STRUCT:
return cloneObject(*obj);
case TYPE_SYMBOL:
@ -924,4 +1005,4 @@ int main(int argc, const char* argv[])
deleteEnv(&env);
}
#endif
#endif