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:
parent
c142730837
commit
3d8e2d30d4
|
@ -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" \
|
||||||
|
|
|
@ -216,11 +216,14 @@ struct Environment defaultEnv()
|
||||||
{"=", &equ}, {">", >h}, {"<", <h},
|
{"=", &equ}, {">", >h}, {"<", <h},
|
||||||
{"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
|
||||||
|
|
40
src/object.c
40
src/object.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
31
src/object.h
31
src/object.h
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue