diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..917b050 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +all: + pebble build && sudo cp build/*.pbw /media/sf_New_Folder diff --git a/src/.pebblisp.c.swp b/src/.pebblisp.c.swp deleted file mode 100644 index 95b393d..0000000 Binary files a/src/.pebblisp.c.swp and /dev/null differ diff --git a/src/calc.c b/src/calc.c index 2092da7..0d379bd 100644 --- a/src/calc.c +++ b/src/calc.c @@ -87,27 +87,97 @@ static void select_handler(ClickRecognizerRef recognizer, void *context){ enter(); } +static void long_select_handler(ClickRecognizerRef recognizer, void *context){ + persist_write_string(current_code, temptext); + window_stack_pop(true); +} + static void click_config_provider(void *context) { // Register click handlers window_single_repeating_click_subscribe(BUTTON_ID_UP, 100, up_down_handler); window_single_repeating_click_subscribe(BUTTON_ID_DOWN, 100, up_down_handler); window_single_click_subscribe(BUTTON_ID_SELECT, select_handler); + window_long_click_subscribe(BUTTON_ID_SELECT, 500, long_select_handler, NULL); window_single_click_subscribe(BUTTON_ID_BACK, back_handler); } -static void init(void) { - // Create a window and get information about the window - s_window = window_create(); +static uint16_t get_num_rows_callback(MenuLayer *menu_layer, + uint16_t section_index, void *context) { + return NUM_ROWS; +} + +static void draw_row_callback(GContext *ctx, const Layer *cell_layer, + MenuIndex *cell_index, void *context) { + static char s_buff[16]; + snprintf(s_buff, sizeof(s_buff), "Script %d", 1 + (int)cell_index->row); + + // Draw this row's index + menu_cell_basic_draw(ctx, cell_layer, s_buff, NULL, NULL); +} + +static int16_t get_cell_height_callback(struct MenuLayer *menu_layer, + MenuIndex *cell_index, void *context) { + const int16_t cell_height = 44; + return cell_height; +} + +void code_window_push() { + if(!s_code_window) { + s_code_window = window_create(); + WindowHandlers wh = { + .load = code_window_load, + .unload = code_window_unload }; + window_set_window_handlers(s_code_window, wh); + } + window_stack_push(s_code_window, true); +} + +static void select_callback(struct MenuLayer *menu_layer, + MenuIndex *cell_index, void *context) +{ + current_code = cell_index->row; + code_window_push(); +} + +static void menu_load(Window *window) +{ + Layer *window_layer = window_get_root_layer(window); + GRect bounds = layer_get_bounds(window_layer); + + s_menu_layer = menu_layer_create(bounds); + menu_layer_set_click_config_onto_window(s_menu_layer, window); +#if defined(PBL_COLOR) + menu_layer_set_normal_colors(s_menu_layer, GColorBlack, GColorWhite); + menu_layer_set_highlight_colors(s_menu_layer, GColorDukeBlue, GColorWhite); +#endif + menu_layer_set_callbacks(s_menu_layer, NULL, (MenuLayerCallbacks) { + .get_num_rows = get_num_rows_callback, + .draw_row = draw_row_callback, + .get_cell_height = get_cell_height_callback, + .select_click = select_callback, + }); + layer_add_child(window_layer, menu_layer_get_layer(s_menu_layer)); +} + +static void menu_unload(Window *window) +{ + menu_layer_destroy(s_menu_layer); +} + +void code_window_load(Window *window) +{ + Layer *window_layer = window_get_root_layer(window); + GRect bounds = layer_get_bounds(window_layer); // Register click config provider - window_set_click_config_provider(s_window, click_config_provider); + window_set_click_config_provider(s_code_window, click_config_provider); // Input text layer setup - GRect text_bounds = GRect(6, 6, 132, 127); - s_input_text_layer = text_layer_create(text_bounds); + // GRect text_bounds = GRect(6, 6, 132, 127); + s_input_text_layer = text_layer_create(bounds); text_layer_set_text(s_input_text_layer, getToken(1)); text_layer_set_font(s_input_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD)); - layer_add_child(window_get_root_layer(s_window), text_layer_get_layer(s_input_text_layer)); + layer_add_child(window_get_root_layer(s_code_window), text_layer_get_layer(s_input_text_layer)); // Result text layer setup GRect result_bounds = GRect(6, 128, 132, 132); @@ -115,26 +185,44 @@ static void init(void) { text_layer_set_text(s_result_text_layer, "R: "); text_layer_set_font(s_result_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD)); text_layer_set_text_alignment(s_result_text_layer, GTextAlignmentRight); - layer_add_child(window_get_root_layer(s_window), text_layer_get_layer(s_result_text_layer)); + layer_add_child(window_get_root_layer(s_code_window), text_layer_get_layer(s_result_text_layer)); // Push the window, setting the window animation to 'true' - window_stack_push(s_window, true); - env = defaultEnv(); + window_stack_push(s_code_window, true); // If possible, load the previous code text - if(persist_exists(CODE_PKEY)) { - persist_read_string(CODE_PKEY, mytext, SMAX_LENGTH); + if(persist_exists(current_code)) { + persist_read_string(current_code, mytext, SMAX_LENGTH); updateText(); } } -static void deinit(void) { +void code_window_unload(Window *window) +{ // Save the current code text - persist_write_string(CODE_PKEY, temptext); + persist_write_string(current_code, temptext); + text_layer_destroy(s_result_text_layer); + text_layer_destroy(s_input_text_layer); + + window_destroy(window); + s_code_window = NULL; +} + +static void init(void) { + env = defaultEnv(); + s_menu_window = window_create(); + window_set_window_handlers(s_menu_window, (WindowHandlers) { + .load = menu_load, + .unload = menu_unload + }); + window_stack_push(s_menu_window, true); +} + +static void deinit(void) { deleteEnv(&env); text_layer_destroy(s_input_text_layer); - window_destroy(s_window); + window_destroy(s_menu_window); } int main(void) { diff --git a/src/calc.h b/src/calc.h index e26dba4..a9c0fc0 100644 --- a/src/calc.h +++ b/src/calc.h @@ -8,13 +8,21 @@ #define MAX_LENGTH 11 #define END_PHRASE "END" -#define CODE_PKEY 1 +#define NUM_ROWS 5 -// Layers -Window *s_window; +Window *s_menu_window; +Window *s_code_window; + +// Code layers TextLayer *s_input_text_layer; TextLayer *s_result_text_layer; +// Menu layers +MenuLayer *s_menu_layer; +TextLayer *s_list_message_layer; + +int current_code; + // PebbLisp environment static struct Environment env; @@ -35,10 +43,11 @@ char *tokens[] = { "7","8","9", "0", "a", "b", "c", "d", "e", "= ", "< ", "> ", - "def", "if", "\n", + "fn", "def", "if", "\n", END_PHRASE }; -#define TOKEN_END 27 +void code_window_load(Window *window); +void code_window_unload(Window *window); #endif diff --git a/src/object.c b/src/object.c index a0ca4e2..80d3df4 100644 --- a/src/object.c +++ b/src/object.c @@ -71,6 +71,14 @@ void addToList(Object *dest, const Object src) end->forward->forward = NULL; } +void printErr(const Object *obj) +{ +#ifdef STANDALONE + printf("%s\n", errorText[(int)(obj->err)]); +#endif + return; +} + // Puts a string version of the given object into a given string char* stringObj(char *dest, const Object *obj) { @@ -131,6 +139,7 @@ void printObj(const Object *obj) char temp[20] = ""; stringObj(temp, obj); printf(": %s\n", temp); + printErr(obj); } void printList(const Object *list) @@ -150,6 +159,19 @@ void printList(const Object *list) } } +void cleanObject(Object *target) +{ + if(target == NULL) + return; + + const Type t = target->type; + if(t == TYPE_LAMBDA) { + free(target->lambda); + } else if(t == TYPE_LIST) { + deleteList(target); + } +} + // Frees all objects in a list void deleteList(const Object *dest) { @@ -162,25 +184,17 @@ void deleteList(const Object *dest) while(tail != NULL) { Object *prevTail = tail; tail = tail->forward; + cleanObject(prevTail); free(prevTail); } } -inline Object listObject() -{ - Object list; - list.forward = NULL; - list.type = TYPE_LIST; - list.list = NULL; - return list; -} - void copyList(Object *dest, const Object *src) { if(!dest || !src || dest->type != TYPE_LIST || src->type != TYPE_LIST) return; - // deleteList(dest); + deleteList(dest); const Object *march = src->list; while(march != NULL) { addToList(dest, *march); @@ -188,28 +202,60 @@ void copyList(Object *dest, const Object *src) } } +inline Object newObject(Type type) +{ + Object no; + no.forward = NULL; + no.type = type; + return no; +} + +inline Object listObject() +{ + Object list = newObject(TYPE_LIST); + list.list = NULL; + return list; +} + inline Object numberObject(int num) { - Object o; - o.forward = NULL; - o.type = TYPE_NUMBER; + Object o = newObject(TYPE_NUMBER); + o.number = num; + return o; +} + +inline Object symbolObject() +{ + Object o = newObject(TYPE_SYMBOL); return o; } inline Object lambdaObject() { - Object o; - o.forward = NULL; - o.type = TYPE_LAMBDA; + Object o = newObject(TYPE_LAMBDA); o.lambda = malloc(sizeof(struct Lambda)); return o; } +inline Object constructLambda(const Object *params, const Object *body) +{ + if(!params || !body) + return errorObject(NULL_LAMBDA_LIST); + + if(params->type != TYPE_LIST || body->type != TYPE_LIST) + return errorObject(LAMBDA_ARGS_NOT_LIST); + + Object o = lambdaObject(); + o.lambda->params = listObject(); + o.lambda->body = listObject(); + copyList(&o.lambda->params, params); + copyList(&o.lambda->body, body); + return o; +} + inline Object errorObject(enum errorCode err) { - Object o; - o.forward = NULL; - o.type = TYPE_ERROR; + Object o = newObject(TYPE_ERROR); o.err = err; return o; } diff --git a/src/object.h b/src/object.h index 4821bf8..6d5ba0c 100644 --- a/src/object.h +++ b/src/object.h @@ -10,9 +10,23 @@ enum errorCode { TYPE_LIST_NOT_CAUGHT, NULL_ENV, BUILT_IN_NOT_FOUND, - NULL_PARSE + NULL_PARSE, + NULL_LAMBDA_LIST, + LAMBDA_ARGS_NOT_LIST }; +#ifdef STANDALONE + static const char *errorText[] = { + "BAD_LIST_OF_SYMBOL_STRINGS", + "TYPE_LIST_NOT_CAUGHT", + "NULL_ENV", + "BUILT_IN_NOT_FOUND", + "NULL_PARSE", + "NULL_LAMBDA_LIST", + "LAMBDA_ARGS_NOT_LIST" + }; +#endif + typedef enum Type { TYPE_NUMBER, TYPE_BOOL, @@ -56,9 +70,13 @@ int listLength(const Object *listObj); Object *itemAt(const Object *listObj, int n); void copyList(Object *dest, const Object *src); +void cleanObject(Object *target); + +Object newObject(Type type); Object listObject(); Object numberObject(int num); Object lambdaObject(); -Object errorObject(); +Object constructLambda(const Object *params, const Object *body); +Object errorObject(enum errorCode err); #endif diff --git a/src/pebblisp.c b/src/pebblisp.c index 518f105..a7ed573 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -58,7 +58,6 @@ Result parse(struct Slice *slices) if(token->text != NULL) { rest = &slices[1]; } else { - printf("Assigning null...\n"); return R(errorObject(NULL_PARSE), NULL); } @@ -130,26 +129,8 @@ Object evalIfArgs(const Object *arg_forms, struct Environment *env) Object evalLambdaArgs(const Object *arg_forms) { - const Object *params_expr = &arg_forms[0]; - const Object *body_expr = &arg_forms[1]; - - Object o = lambdaObject(); - o.lambda->params = listObject(); - copyList(&o.lambda->params, params_expr); - - o.lambda->body = listObject(); - copyList(&o.lambda->body, arg_forms->forward); - return o; -} - -void parseListOfSymbolStrings(const Object *form, const char **symbolStrings, - int len) -{ - if(!form || form->type != TYPE_LIST) - return; - - for(int i = 0; i < len; i++) - symbolStrings[i] = itemAt(form, i)->name; + // params // body + return constructLambda(arg_forms, arg_forms->forward); } struct Environment envForLambda(const Object *params, const Object *arg_forms, diff --git a/src/pebblisp.h b/src/pebblisp.h index 59ffdb9..931ba9d 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -30,6 +30,8 @@ void copySlice(char * dest, struct Slice *src); Object parseEval(const char *input, struct Environment *env); void eval_forms(Object *destList, const Object *src, struct Environment *env); +Object evalLambdaArgs(const Object *arg_forms); + struct Environment defaultEnv(); void deleteEnv(struct Environment *e); void addToEnv(struct Environment *env, const char *name, const Object obj); diff --git a/src/tags b/src/tags index bf39104..121ca2a 100644 --- a/src/tags +++ b/src/tags @@ -5,7 +5,7 @@ !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ !_TAG_PROGRAM_VERSION 5.9~svn20110310 // BAD_LIST_OF_SYMBOL_STRINGS object.h /^ BAD_LIST_OF_SYMBOL_STRINGS,$/;" e enum:errorCode -BUILT_IN_NOT_FOUND object.h /^ BUILT_IN_NOT_FOUND$/;" e enum:errorCode +BUILT_IN_NOT_FOUND object.h /^ BUILT_IN_NOT_FOUND,$/;" e enum:errorCode CALC_H calc.h 2;" d CODE_PKEY calc.h 11;" d END_PHRASE calc.h 9;" d @@ -16,17 +16,17 @@ MAX_LENGTH calc.h 8;" d MAX_TOK_CNT object.h 5;" d MAX_TOK_LEN object.h 4;" d NULL_ENV object.h /^ NULL_ENV,$/;" e enum:errorCode +NULL_PARSE object.h /^ NULL_PARSE$/;" e enum:errorCode OBJECT_H object.h 2;" d Object object.h /^struct Object {$/;" s Object object.h /^typedef struct Object Object;$/;" t typeref:struct:Object PEBBLISP_H pebblisp.h 2;" d -R pebblisp.h 45;" d +R pebblisp.h 48;" d Result pebblisp.h /^typedef struct Result {$/;" s Result pebblisp.h /^} Result;$/;" t typeref:struct:Result SMAX_LENGTH calc.h 7;" d Slice pebblisp.h /^struct Slice {$/;" s TOKENS_H tokens.h 2;" d -TOKEN_END calc.h 42;" d TYPE_BOOL object.h /^ TYPE_BOOL,$/;" e enum:Type TYPE_ERROR object.h /^ TYPE_ERROR \/\/ Currently unused$/;" e enum:Type TYPE_FUNC object.h /^ TYPE_FUNC,$/;" e enum:Type @@ -43,9 +43,11 @@ addToList object.c /^void addToList(Object *dest, const Object src)$/;" f back_handler calc.c /^static void back_handler(ClickRecognizerRef recognizer, void *context) {$/;" f file: basicOp pebblisp.c /^Object basicOp(Object *obj1, Object *obj2, const char op)$/;" f body object.h /^ Object body;$/;" m struct:Lambda -bopf pebblisp.c 365;" d file: +bopf pebblisp.c 337;" d file: calculate calc.c /^static void calculate(){$/;" f file: +cleanObject object.c /^void cleanObject(Object *target)$/;" f click_config_provider calc.c /^static void click_config_provider(void *context) {$/;" f file: +constructLambda object.c /^inline Object constructLambda(const Object *params, const Object *body)$/;" f copyList object.c /^void copyList(Object *dest, const Object *src)$/;" f copySlice pebblisp.c /^void copySlice(char * dest, struct Slice *src)$/;" f debugSlice pebblisp.c /^void debugSlice(struct Slice *s)$/;" f @@ -53,6 +55,7 @@ defaultEnv pebblisp.c /^struct Environment defaultEnv() {$/;" f deinit calc.c /^static void deinit(void) {$/;" f file: deleteEnv pebblisp.c /^void deleteEnv(struct Environment *e)$/;" f deleteList object.c /^void deleteList(const Object *dest)$/;" f +depth object.c /^int depth = 0;$/;" v enter calc.c /^static void enter(){$/;" f file: env calc.h /^static struct Environment env;$/;" v typeref:struct:Environment envForLambda pebblisp.c /^struct Environment envForLambda(const Object *params, const Object *arg_forms,$/;" f @@ -63,7 +66,7 @@ eval pebblisp.c /^Object eval(const Object *obj, struct Environment *env)$/;" f evalBuiltIns pebblisp.c /^Object evalBuiltIns(const Object *first, const Object *rest,$/;" f evalDefArgs pebblisp.c /^Object evalDefArgs(const Object *arg_forms, struct Environment *env)$/;" f evalIfArgs pebblisp.c /^Object evalIfArgs(const Object *arg_forms, struct Environment *env)$/;" f -evalLambdaArgs pebblisp.c /^Object evalLambdaArgs(const Object *arg_forms, struct Environment *env)$/;" f +evalLambdaArgs pebblisp.c /^Object evalLambdaArgs(const Object *arg_forms)$/;" f eval_forms pebblisp.c /^void eval_forms(Object *destList, const Object *src, struct Environment *env)$/;" f fetchFromEnvironment pebblisp.c /^Object fetchFromEnvironment(const char *name, struct Environment *env)$/;" f forward object.h /^ Object *forward;$/;" m struct:Object @@ -84,6 +87,7 @@ main calc.c /^int main(void) {$/;" f main pebblisp.c /^int main(void)$/;" f mytext calc.h /^char mytext[SMAX_LENGTH] = "";$/;" v name object.h /^ char name[MAX_TOK_LEN];$/;" m union:Object::__anon1 +newObject object.c /^inline Object newObject(Type type)$/;" f nf_tokenize tokens.c /^struct Slice *nf_tokenize(const char *input)$/;" f notWhitespace tokens.c /^int notWhitespace(const char c) {$/;" f number object.h /^ int number;$/;" m union:Object::__anon1 @@ -95,7 +99,6 @@ params object.h /^ Object params;$/;" m struct:Lambda parse pebblisp.c /^Result parse(struct Slice *slices)$/;" f parseAtom pebblisp.c /^Object parseAtom(struct Slice *s)$/;" f parseEval pebblisp.c /^Object parseEval(const char *input, struct Environment *env)$/;" f -parseListOfSymbolStrings pebblisp.c /^void parseListOfSymbolStrings(const Object *form, const char **symbolStrings,$/;" f printEnv pebblisp.c /^void printEnv(struct Environment *env)$/;" f printList object.c /^void printList(const Object *list)$/;" f printObj object.c /^void printObj(const Object *obj)$/;" f @@ -115,6 +118,7 @@ singleTokens tokens.c /^static const char singleTokens[] = "()+-*\/=";$/;" v fil slices pebblisp.h /^ struct Slice *slices;$/;" m struct:Result typeref:struct:Result::Slice stringObj object.c /^char* stringObj(char *dest, const Object *obj)$/;" f strings pebblisp.h /^ char **strings;$/;" m struct:Environment +symbolObject object.c /^inline Object symbolObject()$/;" f tail object.c /^Object *tail(const Object *listObj)$/;" f temptext calc.h /^char temptext[SMAX_LENGTH] = "";$/;" v text pebblisp.h /^ const char *text;$/;" m struct:Slice diff --git a/src/tokens.c b/src/tokens.c index 2bc418d..de35992 100644 --- a/src/tokens.c +++ b/src/tokens.c @@ -52,7 +52,7 @@ struct Slice *nf_tokenize(const char *input) int parens = 0; while(input[i] != '\0') { - //printf("input: '%c'\n", input[i]); + // printf("input: '%c'\n", input[i]); if(isWhitespace(input[i])) { i++; @@ -73,31 +73,13 @@ struct Slice *nf_tokenize(const char *input) } else { slices[slice].text = &input[i]; - //int (*check)(const char c) = isDigit(input[i])? - //&isDigit : ¬Whitespace; int l = 1; while(!isWhitespace(input[++i]) && !isSingle(input[i])) { l++; - //slices[slice].length = l; - //debugSlice(&slices[slice]); } slices[slice].length = l; slice++; } - /* } else if(isDigit(input[i])) { - slices[slice].text = &input[i]; - - int l = 1; - while(isDigit(input[++i])) - l++; - - slices[slice].length = l; - slice++; - - } else { // Other uncaught - i++; - } - */ } if(parens){