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 \
"(def time (fn () ((def m (mnt)) (utl tt \n"\
" (cat \"Hey, it's \"\n"\
" (hrt) \":\" (if (< m 10) \"0\" \"\") m)\n"\
"))))\n" \
"(def time (fn () (utl tt \n"\
" (cat \"Hey, it's \" \n"\
" (hrt) \":\" (mnt))\n"\
")))\n" \
"(def ww (cw))\n" \
"(def tt (atl ww \":\"))\n" \
"(pw ww)\n" \

View File

@ -216,11 +216,14 @@ struct Environment defaultEnv()
{"=", &equ}, {">", &gth}, {"<", &lth},
{"cat", &catObjects}, {"fil", &filter}, {"len", &len},
{"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},
{"prn", &print}, {"pch", &pChar}, {"penv", &printEnvO},
{"eval", &parseEvalO},
#ifdef STANDALONE
{"prn", &print}, {"pch", &pChar}, {"penv", &printEnvO},
{"loadfile", &loadFile},
{"inp", &takeInput},
#endif

View File

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

View File

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

View File

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

View File

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