Add LOW_MEM and SIMPLE_ERRORS flags for aplite.

LOW_MEM drops some functionality (like `defe`) for very low memory devices like
aplite. SIMPLE_ERRORS is enabled when compiling with LOW_MEM, and overrides the
new error-with-context functionality with older, less intensive methods.
Also marked more code for standalone compilation only.
This commit is contained in:
= 2021-07-21 19:31:40 +01:00
parent c142730837
commit 3d8e2d30d4
6 changed files with 84 additions and 27 deletions

View File

@ -258,10 +258,10 @@ static void code_click_subscribe(void *context)
} }
#define FORCE_TEXT \ #define FORCE_TEXT \
"(def time (fn () ((def m (mnt)) (utl tt \n"\ "(def time (fn () (utl tt \n"\
" (cat \"Hey, it's \"\n"\ " (cat \"Hey, it's \" \n"\
" (hrt) \":\" (if (< m 10) \"0\" \"\") m)\n"\ " (hrt) \":\" (mnt))\n"\
"))))\n" \ ")))\n" \
"(def ww (cw))\n" \ "(def ww (cw))\n" \
"(def tt (atl ww \":\"))\n" \ "(def tt (atl ww \":\"))\n" \
"(pw ww)\n" \ "(pw ww)\n" \

View File

@ -216,11 +216,14 @@ struct Environment defaultEnv()
{"=", &equ}, {">", &gth}, {"<", &lth}, {"=", &equ}, {">", &gth}, {"<", &lth},
{"cat", &catObjects}, {"fil", &filter}, {"len", &len}, {"cat", &catObjects}, {"fil", &filter}, {"len", &len},
{"ap", &append}, {"pre", &prepend}, {"ap", &append}, {"pre", &prepend},
{"at", &at}, {"rest", &rest}, {"rev", &reverse}, {"at", &at}, {"rest", &rest},
#ifndef LOW_MEM
{"rev", &reverse},
#endif
{"isnum", &isNum}, {"isstr", &isString}, {"iserr", &isErr}, {"isnum", &isNum}, {"isstr", &isString}, {"iserr", &isErr},
{"prn", &print}, {"pch", &pChar}, {"penv", &printEnvO},
{"eval", &parseEvalO}, {"eval", &parseEvalO},
#ifdef STANDALONE #ifdef STANDALONE
{"prn", &print}, {"pch", &pChar}, {"penv", &printEnvO},
{"loadfile", &loadFile}, {"loadfile", &loadFile},
{"inp", &takeInput}, {"inp", &takeInput},
#endif #endif

View File

@ -5,13 +5,15 @@
#ifdef DEBUG #ifdef DEBUG
#define printd(...) printf(__VA_ARGS__) #define printd(...) printf(__VA_ARGS__)
#else #else
#define printd(...) stringObj(NULL, NULL) #define printd(...) ;
#endif #endif
#ifndef STANDALONE #ifndef STANDALONE
#include <pebble.h> #include <pebble.h>
#undef printf #undef printf
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__) #undef printd
#define printf(...) ;
#define printd(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
#endif #endif
/** /**
@ -105,7 +107,7 @@ inline int isEmpty(const Object *obj)
case TYPE_OTHER: case TYPE_OTHER:
return obj->other == NULL; return obj->other == NULL;
case TYPE_ERROR: case TYPE_ERROR:
return obj->error->code == 0; return getErrorCode(*obj);
} }
return 0; return 0;
@ -290,13 +292,17 @@ char* stringNObj(char *dest, const Object *obj, const size_t len) {
stringList(dest, obj); stringList(dest, obj);
break; break;
case TYPE_ERROR: { case TYPE_ERROR: {
int code = obj->error->code; int code = getErrorCode(*obj);
#ifdef SIMPLE_ERRORS
snprintf(dest, len, "%s", errorText[code]);
#else
if (obj->error->context && obj->error->context[0] != '\0') { if (obj->error->context && obj->error->context[0] != '\0') {
snprintf(dest, len, "'%s': %s", snprintf(dest, len, "'%s': %s",
errorText[code], obj->error->context); errorText[code], obj->error->context);
} else { } else {
snprintf(dest, len, "%s", errorText[code]); snprintf(dest, len, "%s", errorText[code]);
} }
#endif
break; break;
} }
case TYPE_FUNC: case TYPE_FUNC:
@ -330,6 +336,7 @@ void debugObj(const Object *obj)
return; return;
} }
#if defined(DEBUG) || defined(STANDALONE)
void printType(const Object *obj) void printType(const Object *obj)
{ {
switch(obj->type) { switch(obj->type) {
@ -419,6 +426,7 @@ void printList(const Object *list)
{ {
_printList(list, 1); _printList(list, 1);
} }
#endif
/** /**
* Performs appropriate free() on a given Object and NULLs its ->forward * Performs appropriate free() on a given Object and NULLs its ->forward
@ -432,7 +440,6 @@ void printList(const Object *list)
*/ */
void cleanObject(Object *target) void cleanObject(Object *target)
{ {
//printf("CLEANING:");
if(target == NULL) if(target == NULL)
return; return;
@ -451,9 +458,11 @@ void cleanObject(Object *target)
free(target->lambda); free(target->lambda);
break; break;
case TYPE_ERROR: case TYPE_ERROR:
#ifndef SIMPLE_ERRORS
free(target->error->context); free(target->error->context);
free(target->error); free(target->error);
target->error = NULL; target->error = NULL;
#endif
break; break;
case TYPE_OTHER: case TYPE_OTHER:
if(target->other->cleanup) { if(target->other->cleanup) {
@ -473,11 +482,13 @@ void cleanObject(Object *target)
* Print the given object with a newline, then clean it * Print the given object with a newline, then clean it
* @param target The object to print and clean * @param target The object to print and clean
*/ */
#ifdef STANDALONE
void printAndClean(Object *target) void printAndClean(Object *target)
{ {
printObj(target); printObj(target);
cleanObject(target); cleanObject(target);
} }
#endif
/** /**
* Frees all objects in a given list * Frees all objects in a given list
@ -653,7 +664,7 @@ inline Object cloneObject(const Object src)
case TYPE_SYMBOL: case TYPE_SYMBOL:
return cloneString(src); return cloneString(src);
case TYPE_ERROR: case TYPE_ERROR:
return errorWithContext(src.error->code, src.error->context); return errorWithContext(getErrorCode(src), src.error->context);
case TYPE_BOOL: case TYPE_BOOL:
case TYPE_NUMBER: case TYPE_NUMBER:
case TYPE_FUNC: case TYPE_FUNC:
@ -718,7 +729,7 @@ inline Object constructLambda(const Object *params, const Object *body)
inline int isError(const Object obj, const enum errorCode err) inline int isError(const Object obj, const enum errorCode err)
{ {
return obj.type == TYPE_ERROR && obj.error->code == err; return obj.type == TYPE_ERROR && getErrorCode(obj) == err;
} }
inline int bothAre(const enum Type type, const Object *obj1, const Object *obj2) inline int bothAre(const enum Type type, const Object *obj1, const Object *obj2)
@ -746,13 +757,27 @@ inline Object otherObject()
inline Object errorObject(enum errorCode err) inline Object errorObject(enum errorCode err)
{ {
Object o = newObject(TYPE_ERROR); Object o = newObject(TYPE_ERROR);
#ifdef SIMPLE_ERRORS
o.error = err;
#else
o.error = malloc(sizeof(struct Error)); o.error = malloc(sizeof(struct Error));
o.error->code = err; o.error->code = err;
o.error->context = NULL; o.error->context = NULL;
#endif
return o; return o;
} }
inline enum errorCode getErrorCode(const Object obj)
{
#ifdef SIMPLE_ERRORS
return obj.error;
#else
return obj.error->code;
#endif
}
#ifndef SIMPLE_ERRORS
inline void errorAddContext(Object *o, const char* context) inline void errorAddContext(Object *o, const char* context)
{ {
o->error->context = calloc(sizeof(char), RESULT_LENGTH); o->error->context = calloc(sizeof(char), RESULT_LENGTH);
@ -765,6 +790,7 @@ inline Object errorWithContext(enum errorCode err, const char* context)
errorAddContext(&o, context); errorAddContext(&o, context);
return o; return o;
} }
#endif
inline Object toBool(const Object test) inline Object toBool(const Object test)
{ {

View File

@ -21,6 +21,14 @@
#define P1 POINTER #define P1 POINTER
#define P2 _element2 #define P2 _element2
#ifdef PBL_PLATFORM_APLITE
#define LOW_MEM
#endif
#ifdef LOW_MEM
#define SIMPLE_ERRORS
#endif
enum errorCode { enum errorCode {
MISMATCHED_PARENS, MISMATCHED_PARENS,
BAD_LIST_OF_SYMBOL_STRINGS, BAD_LIST_OF_SYMBOL_STRINGS,
@ -64,7 +72,12 @@ struct Lambda;
struct Environment; struct Environment;
struct Slice; struct Slice;
struct Other; struct Other;
struct Error; #ifndef SIMPLE_ERRORS
struct Error {
enum errorCode code;
char* context;
};
#endif
struct Object { struct Object {
Type type; Type type;
@ -76,15 +89,14 @@ struct Object {
Object (*func)(Object, Object, struct Environment *); Object (*func)(Object, Object, struct Environment *);
struct Lambda *lambda; struct Lambda *lambda;
struct Other *other; struct Other *other;
#ifdef SIMPLE_ERRORS
enum errorCode error;
#else
struct Error *error; struct Error *error;
#endif
}; };
}; };
struct Error {
enum errorCode code;
char* context;
};
struct Lambda { struct Lambda {
Object params; Object params;
Object body; Object body;
@ -143,8 +155,15 @@ Object boolObject(int b);
Object numberObject(int num); Object numberObject(int num);
Object otherObject(); Object otherObject();
Object errorObject(enum errorCode err); Object errorObject(enum errorCode err);
enum errorCode getErrorCode(const Object obj);
#ifdef SIMPLE_ERRORS
#define errorWithContext(code, context) errorObject(code)
#define errorAddContext(x, y) ;
#else
Object errorWithContext(enum errorCode err, const char* context); Object errorWithContext(enum errorCode err, const char* context);
void errorAddContext(Object *o, const char* context); void errorAddContext(Object *o, const char* context);
#endif
Object constructLambda(const Object *params, const Object *body); Object constructLambda(const Object *params, const Object *body);
// Object version of listLength() // Object version of listLength()

View File

@ -7,6 +7,7 @@
#ifndef STANDALONE #ifndef STANDALONE
#undef printf #undef printf
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__) #define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
#include <pebble.h>
#endif #endif
/** /**
@ -108,11 +109,13 @@ Object evalBuiltIns(const Object *first, const Object *rest,
if(strcmp(first->string, "def") == 0) { if(strcmp(first->string, "def") == 0) {
return evalDefArgs(rest, rest->forward, env); return evalDefArgs(rest, rest->forward, env);
#ifndef LOW_MEM
} else if(strcmp(first->string, "defe") == 0) { } else if(strcmp(first->string, "defe") == 0) {
Object symbol = eval(rest, env); Object symbol = eval(rest, env);
Object e = evalDefArgs(&symbol, rest->forward, env); Object e = evalDefArgs(&symbol, rest->forward, env);
cleanObject(&symbol); cleanObject(&symbol);
return e; return e;
#endif
} else if(strcmp(first->string, "if") == 0) { } else if(strcmp(first->string, "if") == 0) {
return evalIfArgs(rest, env); return evalIfArgs(rest, env);
} else if(strcmp(first->string, "fn") == 0) { } else if(strcmp(first->string, "fn") == 0) {
@ -511,22 +514,23 @@ Object reverse(Object _list, Object ignore, struct Environment *ignore2)
Object isNum(Object test, Object ignore, struct Environment *ignore2) Object isNum(Object test, Object ignore, struct Environment *ignore2)
{ {
return test.type == TYPE_NUMBER ? return test.type == TYPE_NUMBER ?
boolObject(1) : boolObject(0); boolObject(1) : boolObject(0);
} }
Object isString(Object test, Object ignore, struct Environment *ignore2) Object isString(Object test, Object ignore, struct Environment *ignore2)
{ {
return test.type == TYPE_STRING ? return test.type == TYPE_STRING ?
boolObject(1) : boolObject(0); boolObject(1) : boolObject(0);
} }
Object isErr(Object test, Object ignore, struct Environment *ignore2) Object isErr(Object test, Object ignore, struct Environment *ignore2)
{ {
return test.type == TYPE_ERROR ? return test.type == TYPE_ERROR ?
boolObject(1) : boolObject(0); boolObject(1) : boolObject(0);
} }
#ifdef STANDALONE
Object print(Object p, Object ignore, struct Environment *env) Object print(Object p, Object ignore, struct Environment *env)
{ {
p = cloneObject(p); p = cloneObject(p);
@ -552,6 +556,7 @@ Object printEnvO(Object i1, Object i2, struct Environment *env) {
printEnv(env); printEnv(env);
return numberObject(0); return numberObject(0);
} }
#endif
Object parseEvalO(Object text, Object ignore, struct Environment *env) Object parseEvalO(Object text, Object ignore, struct Environment *env)
{ {
@ -586,6 +591,7 @@ void copySlice(char * dest, struct Slice *src)
void debugSlice(struct Slice *s) void debugSlice(struct Slice *s)
{ {
#ifdef DEBUG
if(!s) { if(!s) {
printf("NULL SLICE\n"); printf("NULL SLICE\n");
return; return;
@ -599,6 +605,7 @@ void debugSlice(struct Slice *s)
} }
printf("'\n"); printf("'\n");
printf(" length: %d\n", s->length); printf(" length: %d\n", s->length);
#endif
} }
Result parse(struct Slice *slices) Result parse(struct Slice *slices)
@ -687,10 +694,12 @@ Object parseAtom(struct Slice *s)
if(isDigit(c)) { if(isDigit(c)) {
if(c != '0' || s->length == 1) { if(c != '0' || s->length == 1) {
return parseDecimal(s); return parseDecimal(s);
#ifndef LOW_MEM
} else if(c == '0' && s->text[1] == 'x') { } else if(c == '0' && s->text[1] == 'x') {
return parseHex(s); return parseHex(s);
} else if(c == '0' && s->text[1] == 'b') { } else if(c == '0' && s->text[1] == 'b') {
return parseBin(s); return parseBin(s);
#endif
} else { } else {
return errorObject(UNSUPPORTED_NUMBER_TYPE); return errorObject(UNSUPPORTED_NUMBER_TYPE);
} }

View File

@ -6,13 +6,13 @@
#ifndef STANDALONE #ifndef STANDALONE
#include <pebble.h> #include <pebble.h>
#define printd(...) copySlice(NULL, NULL) #define printd(...) ;
#endif #endif
#ifdef DEBUG #ifdef DEBUG
#define printd(...) printf(__VA_ARGS__) #define printd(...) printf(__VA_ARGS__)
#else #else
#define printd(...) copySlice(NULL, NULL) #define printd(...) ;
#endif #endif
struct Slice { struct Slice {