Add basic struct notion and tests.
Don't auto-run tests in debug mode. Some new tests fail for list-related reasons (some work in the REPL).
This commit is contained in:
parent
80967b9275
commit
95762976c5
|
@ -10,7 +10,7 @@ val:
|
||||||
gcc -g -O0 -o pebblisp -D STANDALONE $(files) && ./tests.sh -val
|
gcc -g -O0 -o pebblisp -D STANDALONE $(files) && ./tests.sh -val
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
gcc -g -O0 -o pebblisp -D STANDALONE -D DEBUG $(files) && ./tests.sh
|
gcc -g -O0 -o pebblisp -D STANDALONE -D DEBUG $(files)
|
||||||
|
|
||||||
run:
|
run:
|
||||||
./pebblisp
|
./pebblisp
|
||||||
|
|
35
src/env.c
35
src/env.c
|
@ -38,6 +38,38 @@ Object fetchFromEnvironment(const char *name, struct Environment *env)
|
||||||
return errorObject(DID_NOT_FIND_SYMBOL);
|
return errorObject(DID_NOT_FIND_SYMBOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object* pointerFromEnvironment(const char *name, struct Environment *env)
|
||||||
|
{
|
||||||
|
if(!env) {
|
||||||
|
printf("env not found\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(env->size == 0) {
|
||||||
|
printf("empty env\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
printd("Fetching '%s' from env\n", name);
|
||||||
|
// printEnv(env);
|
||||||
|
for(int i = 0; i < env->size; i++) {
|
||||||
|
printd("Try %d\n", i);
|
||||||
|
if(env->strings[i] == NULL)
|
||||||
|
break;
|
||||||
|
if(strcmp(name, env->strings[i]) == 0) {
|
||||||
|
return &env->objects[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printd("Trying outer %p\n", env->outer);
|
||||||
|
if(env->outer) {
|
||||||
|
// printEnv(env->outer);
|
||||||
|
return pointerFromEnvironment(name, env->outer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct Environment envForLambda(const Object *params, const Object *arg_forms,
|
struct Environment envForLambda(const Object *params, const Object *arg_forms,
|
||||||
struct Environment *outer)
|
struct Environment *outer)
|
||||||
{
|
{
|
||||||
|
@ -173,6 +205,9 @@ const char *codes[] = {
|
||||||
) \
|
) \
|
||||||
))",
|
))",
|
||||||
|
|
||||||
|
// A demo struct
|
||||||
|
"(stct kitty (name age))",
|
||||||
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ struct Environment {
|
||||||
};
|
};
|
||||||
|
|
||||||
Object fetchFromEnvironment(const char *name, struct Environment *env);
|
Object fetchFromEnvironment(const char *name, struct Environment *env);
|
||||||
|
Object* pointerFromEnvironment(const char *name, struct Environment *env);
|
||||||
struct Environment envForLambda(const Object *params, const Object *arg_forms,
|
struct Environment envForLambda(const Object *params, const Object *arg_forms,
|
||||||
struct Environment *outer);
|
struct Environment *outer);
|
||||||
void addToEnv(struct Environment *env, const char *name, const Object obj);
|
void addToEnv(struct Environment *env, const char *name, const Object obj);
|
||||||
|
|
27
src/object.c
27
src/object.c
|
@ -3,7 +3,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define RESULT_LENGTH 20
|
#define RESULT_LENGTH 40
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define printd(...) printf(__VA_ARGS__)
|
#define printd(...) printf(__VA_ARGS__)
|
||||||
|
@ -226,6 +226,29 @@ void stringList(char *dest, const Object *obj)
|
||||||
strcat(dest, " )");
|
strcat(dest, " )");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stringStruct(char *dest, const Object *obj)
|
||||||
|
{
|
||||||
|
dest[0] = '\0';
|
||||||
|
|
||||||
|
Object *march = obj->list->forward;
|
||||||
|
Object *structMarch = obj->list->list;
|
||||||
|
while(march && structMarch) {
|
||||||
|
char tok[90] = "";
|
||||||
|
stringObj(tok, structMarch);
|
||||||
|
strcat(dest, tok);
|
||||||
|
strcat(dest, ": ");
|
||||||
|
|
||||||
|
tok[0] = '\0';
|
||||||
|
stringObj(tok, march);
|
||||||
|
strcat(dest, tok);
|
||||||
|
|
||||||
|
if(march->forward)
|
||||||
|
strcat(dest, " ");
|
||||||
|
march = march->forward;
|
||||||
|
structMarch = structMarch->forward;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a string from a given Object
|
* Creates a string from a given Object
|
||||||
* Returns NULL if either param is NULL
|
* Returns NULL if either param is NULL
|
||||||
|
@ -259,6 +282,8 @@ char* stringObj(char *dest, const Object *obj)
|
||||||
snprintf(dest, RESULT_LENGTH, "%s", obj->string);
|
snprintf(dest, RESULT_LENGTH, "%s", obj->string);
|
||||||
} else if(t == TYPE_LIST) {
|
} else if(t == TYPE_LIST) {
|
||||||
stringList(dest, obj);
|
stringList(dest, obj);
|
||||||
|
} else if(t == TYPE_STRUCT) {
|
||||||
|
stringStruct(dest, obj);
|
||||||
} else if(t == TYPE_ERROR) {
|
} else if(t == TYPE_ERROR) {
|
||||||
snprintf(dest, RESULT_LENGTH, "E%d", obj->err);
|
snprintf(dest, RESULT_LENGTH, "E%d", obj->err);
|
||||||
} else {
|
} else {
|
||||||
|
|
11
src/object.h
11
src/object.h
|
@ -28,13 +28,15 @@ enum errorCode {
|
||||||
NULL_PARSE,
|
NULL_PARSE,
|
||||||
NULL_LAMBDA_LIST,
|
NULL_LAMBDA_LIST,
|
||||||
NULL_MAP_ARGS,
|
NULL_MAP_ARGS,
|
||||||
|
NULL_STRUCT_ARGS,
|
||||||
LAMBDA_ARGS_NOT_LIST,
|
LAMBDA_ARGS_NOT_LIST,
|
||||||
DID_NOT_FIND_SYMBOL,
|
DID_NOT_FIND_SYMBOL,
|
||||||
BAD_TYPE,
|
BAD_TYPE,
|
||||||
UNEXPECTED_FORM,
|
UNEXPECTED_FORM,
|
||||||
LISTS_NOT_SAME_SIZE,
|
LISTS_NOT_SAME_SIZE,
|
||||||
SYMBOLS_CANT_START_WITH_DIGITS,
|
SYMBOLS_CANT_START_WITH_DIGITS,
|
||||||
UNSUPPORTED_NUMBER_TYPE
|
UNSUPPORTED_NUMBER_TYPE,
|
||||||
|
MISMATCHED_PARAM_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
//#ifdef STANDALONE
|
//#ifdef STANDALONE
|
||||||
|
@ -48,18 +50,18 @@ static const char *errorText[] = {
|
||||||
"NULL_PARSE",
|
"NULL_PARSE",
|
||||||
"NULL_LAMBDA_LIST",
|
"NULL_LAMBDA_LIST",
|
||||||
"NULL_MAP_ARGS",
|
"NULL_MAP_ARGS",
|
||||||
|
"NULL_STRUCT_ARGS",
|
||||||
"LAMBDA_ARGS_NOT_LIST",
|
"LAMBDA_ARGS_NOT_LIST",
|
||||||
"DID_NOT_FIND_SYMBOL",
|
"DID_NOT_FIND_SYMBOL",
|
||||||
"BAD_TYPE",
|
"BAD_TYPE",
|
||||||
"UNEXPECTED_FORM",
|
"UNEXPECTED_FORM",
|
||||||
"LISTS_NOT_SAME_SIZE",
|
"LISTS_NOT_SAME_SIZE",
|
||||||
"SYMBOLS_CANT_START_WITH_DIGITS",
|
"SYMBOLS_CANT_START_WITH_DIGITS",
|
||||||
"UNSUPPORTED_NUMBER_TYPE"
|
"UNSUPPORTED_NUMBER_TYPE",
|
||||||
|
"MISMATCHED_PARAM_COUNT"
|
||||||
};
|
};
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
#define MALLOC_FLAG 64
|
|
||||||
|
|
||||||
typedef enum Type {
|
typedef enum Type {
|
||||||
TYPE_NUMBER,
|
TYPE_NUMBER,
|
||||||
TYPE_BOOL,
|
TYPE_BOOL,
|
||||||
|
@ -68,6 +70,7 @@ typedef enum Type {
|
||||||
TYPE_SYMBOL,
|
TYPE_SYMBOL,
|
||||||
TYPE_LAMBDA,
|
TYPE_LAMBDA,
|
||||||
TYPE_STRING,
|
TYPE_STRING,
|
||||||
|
TYPE_STRUCT,
|
||||||
TYPE_ERROR
|
TYPE_ERROR
|
||||||
} Type;
|
} Type;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,48 @@ Object evalMapArgs(const Object *argForms, struct Environment *env)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object evalStructArgs(const Object *name, const Object *argForms,
|
||||||
|
struct Environment *env)
|
||||||
|
{
|
||||||
|
if(!argForms)
|
||||||
|
return errorObject(NULL_STRUCT_ARGS);
|
||||||
|
|
||||||
|
Object strct = cloneList(*argForms);
|
||||||
|
// strct.type = TYPE_STRUCT;
|
||||||
|
|
||||||
|
addToEnv(env, name->name, strct);
|
||||||
|
return strct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*(def herm (make cat ("Hermione" 10)))
|
||||||
|
* Stores a STRUCT named herm in the environment
|
||||||
|
* String in env is "herm"
|
||||||
|
* Object in env is a TYPE_STRUCT with
|
||||||
|
* ->forward = NULL
|
||||||
|
* ->list = pointer to cat in env
|
||||||
|
* ->forward = "Hermione"
|
||||||
|
* ->forward = 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
Object evalMakeArgs(const Object *structName, const Object *argForms,
|
||||||
|
struct Environment *env)
|
||||||
|
{
|
||||||
|
Object *structure = pointerFromEnvironment(structName->name, env);
|
||||||
|
if(listLength(structure) != listLength(argForms))
|
||||||
|
return errorObject(MISMATCHED_PARAM_COUNT);
|
||||||
|
|
||||||
|
// Could be made to re-use the string pointer in `structure`
|
||||||
|
Object newStruct = startList(*structure);
|
||||||
|
|
||||||
|
FOR_POINTER_IN_LIST(argForms) {
|
||||||
|
nf_addToList(&newStruct, eval(POINTER, env));
|
||||||
|
}
|
||||||
|
|
||||||
|
newStruct.type = TYPE_STRUCT;
|
||||||
|
return newStruct;
|
||||||
|
}
|
||||||
|
|
||||||
Object evalBuiltIns(const Object *first, const Object *rest,
|
Object evalBuiltIns(const Object *first, const Object *rest,
|
||||||
struct Environment *env)
|
struct Environment *env)
|
||||||
{
|
{
|
||||||
|
@ -75,6 +117,10 @@ Object evalBuiltIns(const Object *first, const Object *rest,
|
||||||
return evalLambdaArgs(rest);
|
return evalLambdaArgs(rest);
|
||||||
} else if(strcmp(first->name, "map") == 0) {
|
} else if(strcmp(first->name, "map") == 0) {
|
||||||
return evalMapArgs(rest, env);
|
return evalMapArgs(rest, env);
|
||||||
|
} else if(strcmp(first->name, "stct") == 0) {
|
||||||
|
return evalStructArgs(rest, rest->forward, env);
|
||||||
|
} else if(strcmp(first->name, "make") == 0) {
|
||||||
|
return evalMakeArgs(rest, rest->forward, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
return errorObject(BUILT_IN_NOT_FOUND);
|
return errorObject(BUILT_IN_NOT_FOUND);
|
||||||
|
@ -158,6 +204,7 @@ Object eval(const Object *obj, struct Environment *env)
|
||||||
return errorObject(UNEXPECTED_FORM);
|
return errorObject(UNEXPECTED_FORM);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
printf("RETURN OBJECT OF TYPE %d\n", obj->type);
|
||||||
return *obj;
|
return *obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ check() {
|
||||||
}
|
}
|
||||||
|
|
||||||
check "PlainRet" "10" "10"
|
check "PlainRet" "10" "10"
|
||||||
|
check "ListRet" "(10)" "(10)"
|
||||||
check "StrRetrn" "\"hey\"" "hey"
|
check "StrRetrn" "\"hey\"" "hey"
|
||||||
echo ""
|
echo ""
|
||||||
check "Addition" "(+ 1093 102852)" "103945"
|
check "Addition" "(+ 1093 102852)" "103945"
|
||||||
|
@ -90,6 +91,11 @@ check "Squaring" "(sq 9876)" "97535376"
|
||||||
check "Cubing" "(cube 81)" "531441"
|
check "Cubing" "(cube 81)" "531441"
|
||||||
check "Exponent" "(exp 9 9)" "387420489"
|
check "Exponent" "(exp 9 9)" "387420489"
|
||||||
echo ""
|
echo ""
|
||||||
|
check "BasicStruct" "(def h (make kitty (\"Hermione\" 2))) h" "name: Hermione age: 2"
|
||||||
|
check "BasicStruct" "(def h (make kitty (\"Hermione\" 2))) (h)" "(name: Hermione age: 2)"
|
||||||
|
check "StructAccess" "(def pet (fn (a) (cat \"You petted \" a))) (def h (make kitty (\"Hermione\" 2))) (pet h)" "You petted Hermione 2"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
||||||
if [ "$FAILS" -ne "0" ]; then
|
if [ "$FAILS" -ne "0" ]; then
|
||||||
echo "[1;31m$FAILS Tests Failed[0m"
|
echo "[1;31m$FAILS Tests Failed[0m"
|
||||||
|
|
Loading…
Reference in New Issue