From fb2e1811ffbef1cc03fd92bbe3dd5b7399ac2c37 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Thu, 31 Mar 2022 12:09:16 -0400 Subject: [PATCH] Rename possessive to structAccess. Gives better error messages. Use typical type-checking in structAccess. Make checkTypes() more global, and move to pebblisp.c --- src/env.c | 2 +- src/object.c | 5 +++++ src/object.h | 2 ++ src/pebblisp.c | 46 ++++++++++++++++++++++++++-------------------- src/pebblisp.h | 20 ++++++++++++++++++++ src/plfunc.c | 27 +-------------------------- src/plfunc.h | 8 -------- 7 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/env.c b/src/env.c index 8775b03..fc4d980 100644 --- a/src/env.c +++ b/src/env.c @@ -422,7 +422,7 @@ struct Environment defaultEnv() pf(isErr), pf(charVal), pf(parseEvalO), - pf(possessive), + pf(structAccess), pf(getTime), #ifndef LOW_MEM pf(reverse), diff --git a/src/object.c b/src/object.c index ef4dceb..0e4109b 100644 --- a/src/object.c +++ b/src/object.c @@ -580,6 +580,11 @@ inline int isBool(const Object test) return test.type == TYPE_BOOL; } +inline int isStruct(const Object test) +{ + return test.type == TYPE_STRUCT; +} + inline int isFuncy(const Object test) { return test.type == TYPE_LAMBDA || test.type == TYPE_FUNC; diff --git a/src/object.h b/src/object.h index 3e0c955..0951ee3 100644 --- a/src/object.h +++ b/src/object.h @@ -179,6 +179,8 @@ int isStringy(Object test); int isBool(Object test); +int isStruct(Object test); + int isFuncy(Object test); int isValidType(Object test); diff --git a/src/pebblisp.c b/src/pebblisp.c index 5f9741d..c31dad7 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -314,23 +314,13 @@ Object eval(const Object* obj, struct Environment* env) return errorObject(BAD_TYPE); } -Object possessive(Object* params, int length, struct Environment* env) +Object structAccess(Object* params, int length, struct Environment* env) { + checkTypes(structAccess) + Object structo = params[0]; Object field = params[1]; - if (structo.type != TYPE_STRUCT) { - printf("`'s` must be used on a struct!\n"); - return errorObject(NULL_PARSE); - } - if (!isStringy(field)) { - printf("`'s` field name must be stringy! Received a "); - printType(&field); - printObj(&field); - printf("\n"); - return errorObject(NULL_PARSE); - } - struct StructDef* structDef = getStructAt(structo.structObject->definition); for (int i = 0; i < structDef->fieldCount; i++) { if (strcmp(field.string, structDef->names[i]) == 0) { @@ -467,14 +457,14 @@ Result parseAtom(struct Slice* s) } else if (c == '"'/* || c == '\''*/) { return (Result) { objFromSlice(s->text, s->length), s }; } else if (s->text[s->length] == '.') { - Object possessiveFunc = newObject(TYPE_FUNC); - possessiveFunc.func = &possessive; - Object list = startList(possessiveFunc); - Object possesser = symFromSlice(s->text, s->length); - nf_addToList(&list, possesser); + Object structAccessFunc = newObject(TYPE_FUNC); + structAccessFunc.func = &structAccess; + Object list = startList(structAccessFunc); + Object theStruct = symFromSlice(s->text, s->length); + nf_addToList(&list, theStruct); struct Slice* next = s + 2; - Object possessed = objFromSlice(&next->text[-1], next->length + 1); - nf_addToList(&list, possessed); + Object structField = objFromSlice(&next->text[-1], next->length + 1); + nf_addToList(&list, structField); return (Result) { list, next }; } return (Result) { symFromSlice(s->text, s->length), s }; @@ -536,6 +526,22 @@ Object parseEval(const char* input, struct Environment* env) return obj; } +Object typeCheck(const char* funcName, Object* params, int length, + int (* typeChecks[])(Object), int typeLength, int* failed) +{ + *failed = 1; + if ((typeLength - 1) > length) { + return errorWithContext(NOT_ENOUGH_ARGUMENTS, funcName); + } + for (int i = 0; i < typeLength - 1; i++) { + if (typeChecks[i] && !typeChecks[i](params[i])) { // TODO: Use pl func name instead of C function name. + return /*errorObject(BAD_TYPE); */ errorWithContextLineNo(BAD_PARAMS_ON, funcName, 0, NULL); + } + } + *failed = 0; + return numberObject(0); +} + #ifdef STANDALONE int readFile(const char* filename, struct Environment* env) diff --git a/src/pebblisp.h b/src/pebblisp.h index c4c76d6..d57d54c 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -64,6 +64,18 @@ Object listEvalLambda(Object* lambda, const Object* remaining, int evalLength, Object simpleFuncEval(Object func, Object arg1, Object arg2, struct Environment* env); +Object typeCheck(const char* funcName, Object* params, int length, + int (* typeChecks[])(Object), int typeLength, int* failed); + +#ifndef DISABLE_TYPE_CHECKS +#define checkTypes(FUNC) int FAILED; Object ERROR = typeCheck(#FUNC, params, length, FUNC ## TypeChecks, array_length(FUNC ## TypeChecks), &FAILED); \ +if (FAILED) { \ + return ERROR; \ +} +#else +#define checkTypes(FUNC) ; +#endif + #ifdef STANDALONE int _readFile(FILE* input, struct Environment* env); @@ -82,4 +94,12 @@ fn(def, "def", "(def x 10) x", "10", ); +tfn(structAccess, "poss", + ({ isStruct, isStringy, NULL }), + "Get the value of a struct's field", + "(struct Post (title body))\n " + "(def p (Post \"TI\" \"BO\"))\n " + "p.title", "TI" +); + #endif \ No newline at end of file diff --git a/src/plfunc.c b/src/plfunc.c index 865e952..d2737ef 100644 --- a/src/plfunc.c +++ b/src/plfunc.c @@ -3,31 +3,6 @@ #include "plfunc.h" -Object typeCheck(const char* funcName, Object* params, int length, - int (* typeChecks[])(Object), int typeLength, int* failed) -{ - *failed = 1; - if ((typeLength - 1) > length) { - return errorWithContext(NOT_ENOUGH_ARGUMENTS, funcName); - } - for (int i = 0; i < typeLength - 1; i++) { - if (typeChecks[i] && !typeChecks[i](params[i])) { // TODO: Use pl func name instead of C function name. - return /*errorObject(BAD_TYPE); */ errorWithContextLineNo(BAD_PARAMS_ON, funcName, 0, NULL); - } - } - *failed = 0; - return numberObject(0); -} - -#ifndef DISABLE_TYPE_CHECKS -#define checkTypes(FUNC) int FAILED; Object ERROR = typeCheck(#FUNC, params, length, FUNC ## TypeChecks, array_length(FUNC ## TypeChecks), &FAILED); \ -if (FAILED) { \ - return ERROR; \ -} -#else -#define checkTypes(FUNC) ; -#endif - Object reduce(Object* params, int length, struct Environment* env) { checkTypes(reduce) @@ -377,7 +352,7 @@ Object numToChar(Object* params, int length, struct Environment* env) if (c.type != TYPE_NUMBER) { return errorObject(BAD_NUMBER); } - char ch[1] = {c.number}; + char ch[1] = { c.number }; return stringFromSlice(ch, 1); } diff --git a/src/plfunc.h b/src/plfunc.h index 6a344a5..186e48f 100644 --- a/src/plfunc.h +++ b/src/plfunc.h @@ -189,14 +189,6 @@ fn(parseEvalO, "eval", "(eval '(+ 5 5))", "10", ); -/// STRUCT, STRING => ANY -fn(possessive, "poss", - "Get the value of a struct's field", - "(struct Post (title body))\n " - "(def p (Post \"TI\" \"BO\"))\n " - "p.title", "TI" -); - #ifdef STANDALONE fn(print, "prn", "Prints the string representation of the given object to stdout.");