From a3bf8ab8649e66cc851eab6ef63da8df6f42a781 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Mon, 4 May 2020 23:14:41 +0100 Subject: [PATCH] Decent `if` and `def` support! --- appinfo.json | 2 +- src/.pebblisp.c.swp | Bin 36864 -> 28672 bytes src/calc.c | 64 ++++++---- src/calc.h | 20 ++- src/fixed.c | 299 -------------------------------------------- src/fixed.h | 55 -------- src/pebblisp.c | 246 ++++++++++++++++-------------------- src/pebblisp.h | 55 ++------ src/tags | 97 +++++++------- src/tokens.c | 9 +- src/tokens.h | 2 +- 11 files changed, 234 insertions(+), 615 deletions(-) delete mode 100644 src/fixed.c delete mode 100644 src/fixed.h diff --git a/appinfo.json b/appinfo.json index 15793ef..2a8e1b8 100644 --- a/appinfo.json +++ b/appinfo.json @@ -24,7 +24,7 @@ "aplite", "basalt" ], - "uuid": "3a239ae0-adc5-4d40-b871-6fbcd8c37e7c", + "uuid": "70ec170a-8e1b-11ea-bc55-0242ac130003", "versionLabel": "0.1", "watchapp": { "watchface": false diff --git a/src/.pebblisp.c.swp b/src/.pebblisp.c.swp index c9633e6087dcfc768035b784c4160fa518c3cf05..30bc5b07c1ad5a137dc662ef5fda2efcb0b8e146 100644 GIT binary patch literal 28672 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 #include -#include "fixed.h" +//#include "fixed.h" #include "calc.h" -#include "pebblisp.h" -static inline char* getToken(int n) { - const int length = sizeof(tokens) / sizeof(tokens[0]); - return tokens[n % length]; +static inline int8_t tokenCount() { + return sizeof(tokens) / sizeof(tokens[0]); } -static int8_t selected_token = 1; //Currently selected button, starts on '5' -static struct Environment env; +static inline char* getToken(int8_t n) { + return tokens[n % tokenCount()]; +} +// Currently selected button, starts on '(' +static int8_t selected_token = 1; + +// Update the current code text with the contents of `mytext`, +// and add the current selected_token to the end static void updateText() { strcpy(temptext, mytext); - if(getToken(selected_token)[0] == ' ') { + const char *token = getToken(selected_token); + if(token[0] == ' ') { strcat(temptext, "_"); + } else if(token[0] == '\n') { + strcat(temptext, "\\n"); } else { - strcat(temptext, getToken(selected_token)); + strcat(temptext, token); } text_layer_set_text(s_input_text_layer, temptext); @@ -27,19 +34,27 @@ static void updateText() // Button handler static void up_down_handler(ClickRecognizerRef recognizer, void *context){ - // Change current token - selected_token += (click_recognizer_get_button_id(recognizer) == BUTTON_ID_DOWN) ? 1 : -1; - // If selected token is outside of range, wrap around - selected_token = selected_token < 0 ? TOKEN_END : selected_token > TOKEN_END ? 0 : selected_token; + // Change current token + if(click_recognizer_get_button_id(recognizer) == BUTTON_ID_DOWN) + selected_token++; + else + selected_token--; - updateText(); + // If selected token is outside of range, wrap around + if(selected_token < 0) + selected_token = tokenCount() - 1; + else if(selected_token >= tokenCount()) + selected_token = 0; + + updateText(); } +// Backspace if possible, otherwise close the app static void back_handler(ClickRecognizerRef recognizer, void *context) { if(mytext[0] == '\0') { window_stack_remove(window_stack_get_top_window(), true); } else { - int i = 0; + int8_t i = 0; while(mytext[++i] != '\0') { ; } mytext[i-1] = '\0'; updateText(); @@ -53,14 +68,14 @@ static void enter(){ updateText(); } -//Calculate result, display it and reset +// Calculate result, display it and reset static void calculate(){ Object obj = parseEval(mytext, &env); char temp[MAX_LENGTH-2] = ""; + stringObj(temp, &obj); snprintf(resulttext, MAX_LENGTH, "R:%s", temp); selected_token = 0; - //strcpy(mytext, HAHA); text_layer_set_text(s_result_text_layer, resulttext); } @@ -83,7 +98,7 @@ static void click_config_provider(void *context) { static void init(void) { // Create a window and get information about the window s_window = window_create(); - // Layer *window_layer = window_get_root_layer(s_window); + // Register click config provider window_set_click_config_provider(s_window, click_config_provider); @@ -105,13 +120,20 @@ static void init(void) { // Push the window, setting the window animation to 'true' window_stack_push(s_window, true); env = defaultEnv(); + + // If possible, load the previous code text + if(persist_exists(CODE_PKEY)) { + persist_read_string(CODE_PKEY, mytext, SMAX_LENGTH); + updateText(); + } } static void deinit(void) { - // Destroy the text layer - text_layer_destroy(s_input_text_layer); + // Save the current code text + persist_write_string(CODE_PKEY, temptext); - // Destroy the window + deleteEnv(&env); + text_layer_destroy(s_input_text_layer); window_destroy(s_window); } diff --git a/src/calc.h b/src/calc.h index 9334e41..e26dba4 100644 --- a/src/calc.h +++ b/src/calc.h @@ -1,3 +1,6 @@ +#ifndef CALC_H +#define CALC_H + #include #include "pebblisp.h" @@ -5,13 +8,23 @@ #define MAX_LENGTH 11 #define END_PHRASE "END" +#define CODE_PKEY 1 + // Layers Window *s_window; TextLayer *s_input_text_layer; TextLayer *s_result_text_layer; +// PebbLisp environment +static struct Environment env; + +// Live code text char mytext[SMAX_LENGTH] = ""; + +// The actual displayed code text char temptext[SMAX_LENGTH] = ""; + +// The result of execution char resulttext[MAX_LENGTH] = ""; char *tokens[] = { @@ -21,8 +34,11 @@ char *tokens[] = { "4","5","6", "7","8","9", "0", "a", "b", "c", "d", "e", - "= ", "< ", "> ", "def", + "= ", "< ", "> ", + "def", "if", "\n", END_PHRASE }; -#define TOKEN_END 26 +#define TOKEN_END 27 + +#endif diff --git a/src/fixed.c b/src/fixed.c deleted file mode 100644 index a3ee97b..0000000 --- a/src/fixed.c +++ /dev/null @@ -1,299 +0,0 @@ -/** @file fixed.c - * @brief A fixed point numbers implementation. - * @author Wojciech 'vifon' Siewierski - */ - -/***********************************************************************************/ -/* Copyright (C) 2015 Wojciech Siewierski */ -/* */ -/* Author: Wojciech Siewierski */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 3 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program. If not, see . */ -/***********************************************************************************/ - -#include "fixed.h" - -#include -#include -#include - -/** Sum two fixed point numbers. - * - * @param lhs - * @param rhs - * @param[out] overflow Indicate whether the addition would - * result in an overflow. If the initial value is @p true, it will - * stay @p true. The returned value is unspecified if it is true. - * - * @return The result. - */ -fixed fixed_add(fixed lhs, fixed rhs, bool* overflow) -{ - // If both arguments have the same sign... - if ((rhs > 0) == (lhs > 0)) { - // ...check for the overflow. - *overflow = *overflow || abs(lhs) > FIXED_MAX - abs(rhs); - } - - if (*overflow) { - return lhs; - } - - return lhs + rhs; -} - -/** Subtract two fixed point numbers. - * - * @param lhs - * @param rhs - * @param[out] overflow Indicate whether the subtraction would - * result in an overflow. If the initial value is @p true, it will - * stay @p true. The returned value is unspecified if it is true. - * - * @return The result. - */ -fixed fixed_subt(fixed lhs, fixed rhs, bool* overflow) -{ - return fixed_add(lhs, -rhs, overflow); -} - -/** Multiply two fixed point numbers. - * - * @param lhs - * @param rhs - * @param[out] overflow Indicate whether the multiplication would - * result in an overflow. If the initial value is @p true, it will - * stay @p true. The returned value is unspecified if it is true. - * - * @return The result. - */ -fixed fixed_mult(fixed lhs, fixed rhs, bool* overflow) -{ - if (fixed_to_int(rhs) != 0) { - *overflow = *overflow || abs(lhs) > abs(fixed_div(FIXED_MAX, rhs)); - } - - if (*overflow) { - return lhs; - } - - return (lhs / FIXED_SCALE) * rhs - + ((lhs % FIXED_SCALE) * rhs) / FIXED_SCALE; -} - -/** Divide two fixed point numbers. - * - * @param lhs - * @param rhs - * - * @note The fractional part of @p rhs is ignored for large @p lhs - * due to a change in the order of performed operations made to avoid - * overflows. - * - * @return The result. - */ -fixed fixed_div(fixed lhs, fixed rhs) -{ - /* Check if it's safe to normalize lhs instead of rhs for precision. */ - if (lhs < FIXED_MAX / FIXED_SCALE) { - /* Keep precision whether possible. */ - lhs = lhs * FIXED_SCALE; - } else { - /* Sacrifice the fractional part of rhs when the another order - * of operations would cause an overflow. */ - rhs = fixed_to_int(rhs); - } - - if (rhs == 0) { - return 0; /* TODO: handle properly */ - } else { - return lhs / rhs; - } -} - -/** Create the textual representation of the fixed point number. - * - * @param fixed A number to represent. - * @param buffer A buffer to store the representation. - * @param size Size of @p buffer. - * - * @return A pointer to the @p buffer parameter. - */ -char* fixed_repr(fixed fixed, char* buffer, size_t size) -{ - const char* sign = (fixed < 0 ? "-" : ""); - int integal_part = abs(fixed) / FIXED_SCALE; - int fractional_part = abs(fixed) % FIXED_SCALE; - - if (fractional_part != 0) { - int n = snprintf(buffer, size, - "%s%d.%02u", - sign, integal_part, fractional_part); - - /* Remove the trailing zeros. */ - if (fractional_part >= 10 && - fractional_part % 10 == 0) { - - buffer[n-1] = '\0'; - } - } else { - snprintf(buffer, size, - "%s%d", - sign, integal_part); - } - - return buffer; -} - -/** Convert a string to integer. - * - * @param str String to convert. - * @param[out] endptr If non-NULL, set to the first invalid character. - * @param maxnum Max number of digits to read. Pass -1 for unlimited. - * - * @return The converted integer. - */ -int str_to_int(const char *str, char **endptr, int maxnum) { - int result = 0; - - int sign = 1; - if (*str == '-') { - ++str; - sign = -1; - } - - while (*str >= '0' && *str <= '9' && maxnum-- != 0) { - result *= 10; - result += *str++ - '0'; - } - - /* save the position of the first invalid character */ - if (endptr != NULL) { - /* http://stackoverflow.com/questions/993700/are-strtol-strtod-unsafe */ - *endptr = (char*)str; - } - - return sign * result; -} - -/** Convert a string to a fixed point number. - * - * @param str String to convert. - * @param[out] overflow Indicate whether the conversion would - * result in an overflow. If the initial value is @p true, it will - * stay @p true. The returned value is unspecified if it is true. - * - * @return The converted fixed point number. - */ -fixed str_to_fixed(const char* str, bool* overflow) -{ - char* fractional_start; - char* endptr; - - int sign = 1; - if (*str == '-') { - ++str; - sign = -1; - } - - // Detect a potential overflow. - static const int FIXED_MAX_digits = 8; - static const char* FIXED_MAX_char = "21474836"; /* FIXED_MAX/FIXED_SCALE */ - const char* integral_end = strchr(str, '.'); - if (integral_end == NULL) { - integral_end = str + strlen(str); - } - - if (integral_end - str > FIXED_MAX_digits) { - *overflow = true; - return 0; - } else if (integral_end - str == FIXED_MAX_digits) { - /* strcmp will return a positive number for string - * lexicographically greater than FIXED_MAX_digits. For - * strings of the same length (which is the case in this if - * branch) it is the same as being numerically greater. */ - if (strncmp(str, FIXED_MAX_char, FIXED_MAX_digits) > 0) { - *overflow = true; - return 0; - } - } - - - int integral_part = str_to_int(str, &fractional_start, -1) * FIXED_SCALE; - if (*fractional_start != '\0') { - ++fractional_start; - } - int fractional_part = str_to_int(fractional_start, &endptr, 2); - - if (endptr - fractional_start == 1) { - /* There was only one digit -- higher order of magnitude. */ - fractional_part *= 10; - } - - return sign * (integral_part + fractional_part); -} - -/** Convert the fixed point value to a regular integer. - * - * @param n - * - * @return The integral part of the fixed point number. - */ -int fixed_to_int(fixed n) -{ - return n / FIXED_SCALE; -} - -/** Convert the integer to a fixed point value. - * - * @param n - * - * @return The converted fixed point number. - */ -fixed int_to_fixed(int n) -{ - return n * FIXED_SCALE; -} - -/** A simple implementation of the pow(3) standard function - * for fixed point numbers. - * - * @param base - * @param exponent - * @param[out] overflow Indicate whether the exponentiation would - * result in an overflow. If the initial value is @p true, it will - * stay @p true. The returned value is unspecified if it is true. - * - * @return The exponentiation result. - * - * @note The exponent is an integer, not a fixed point number. - */ -fixed fixed_pow(fixed base, int exponent, bool* overflow) -{ - fixed result = FIXED_SCALE; - - bool negative = exponent < 0; - exponent = abs(exponent); - - while (exponent-- && *overflow == false) { - result = fixed_mult(result, base, overflow); - } - - if (negative) { - return fixed_div(int_to_fixed(1), - result); - } else { - return result; - } -} \ No newline at end of file diff --git a/src/fixed.h b/src/fixed.h deleted file mode 100644 index a2a0487..0000000 --- a/src/fixed.h +++ /dev/null @@ -1,55 +0,0 @@ -/** @file fixed.h - * @brief A fixed point numbers implementation. - * @author Wojciech 'vifon' Siewierski - */ - -/***********************************************************************************/ -/* Copyright (C) 2015 Wojciech Siewierski */ -/* */ -/* Author: Wojciech Siewierski */ -/* */ -/* This program is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU General Public License */ -/* as published by the Free Software Foundation; either version 3 */ -/* of the License, or (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ -/* GNU General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program. If not, see . */ -/***********************************************************************************/ - -#ifndef _h_FIXED_ -#define _h_FIXED_ - -/* Do not include pebble.h when compiling the unittests. */ -#ifndef __cplusplus -# include /* for bool */ -#endif - -#include -#include - -/** The underlying fixed point representation. */ -typedef int fixed; - -/** The scaling factor of the fixed point numbers. */ -#define FIXED_SCALE 100 - -/** Maximum representable value. */ -static const fixed FIXED_MAX = INT_MAX; - -fixed fixed_add(fixed lhs, fixed rhs, bool* overflow); -fixed fixed_subt(fixed lhs, fixed rhs, bool* overflow); -fixed fixed_mult(fixed lhs, fixed rhs, bool* overflow); -fixed fixed_div(fixed lhs, fixed rhs); -char* fixed_repr(fixed fixed, char* buffer, size_t size); -fixed str_to_fixed(const char* str, bool* overflow); -int fixed_to_int(fixed n); -fixed int_to_fixed(int n); -fixed fixed_pow(fixed base, int exponent, bool* overflow); - -#endif \ No newline at end of file diff --git a/src/pebblisp.c b/src/pebblisp.c index 617ba21..4a7f91f 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -6,7 +6,6 @@ #ifndef STANDALONE #define printf(...) copySlice(NULL, NULL) -#else #endif void copySlice(char * dest, struct Slice *src) @@ -14,25 +13,25 @@ void copySlice(char * dest, struct Slice *src) if(!dest || !src) return; strncpy(dest, src->text, src->length); - dest[src->length] = '\0'; + dest[(int)src->length] = '\0'; } void debugSlice(struct Slice *s) { - //printf("Debug Slice\n text:'"); + printf("Debug Slice\n text:'"); for(int i = 0; i < s->length; i++) { - //printf("%c", s->text[i]); + printf("%c", s->text[i]); } - // printf("'\n"); - // printf(" length: %d\n", s->length); + printf("'\n"); + printf(" length: %d\n", s->length); } Object fetchFromEnvironment(const char *name, struct Environment *env) { + printf("Fetching '%s' from env\n", name); int i = 0; const char *next = env->strings[i]; while(next != NULL) { - // printf("fetching '%s' against '%s'\n", name, next); if(strcmp(name, next) == 0) { return env->objects[i]; } @@ -46,13 +45,12 @@ Object fetchFromEnvironment(const char *name, struct Environment *env) Result parse(struct Slice *slices) { - // printf("parse() START\n"); struct Slice *token = slices; struct Slice *rest; if(token->text != NULL) { rest = &slices[1]; } else { - // printf("Assigning null...\n"); + printf("Assigning null...\n"); rest = NULL; } @@ -62,18 +60,11 @@ Result parse(struct Slice *slices) } else { // todo error on closed paren return R(parseAtom(token), rest); } - // printf("parse() END\n"); } Result readSeq(struct Slice *tokens) { - // printf("readSeq() START\n"); - Object res; - res.forward = NULL; - res.type = TYPE_LIST; - //res.list = malloc(sizeof(Object)); - - Object *march = &res; + Object res = listObject(); for(;;) { struct Slice *next = &tokens[0]; struct Slice *rest = next->text? &next[1] : NULL; @@ -81,16 +72,9 @@ Result readSeq(struct Slice *tokens) return R(res, rest); } Result r = parse(tokens); - // printf("readSeq() before malloc\n"); - march->forward = malloc(sizeof(struct Object)); - // printf("readSeq() after malloc\n"); - *march->forward = r.obj; - // char out[MAX_TOK_LEN]; - // printf("stringObj: %s\n", stringObj(out, &r.obj)); + addToList(&res, r.obj); tokens = r.slices; - march = march->forward; } - // printf("readSeq() END\n"); } Object parseAtom(struct Slice *s) @@ -117,34 +101,25 @@ Object parseAtom(struct Slice *s) return o; } -Object evalDefArgs(const Object *first, const Object *rest, - struct Environment *env) +Object evalDefArgs(const Object *arg_forms, struct Environment *env) { printf("evalDefArgs()\n"); - Object o; - return o; + + const Object *first_form = &arg_forms[0]; + const char *name = first_form->name; + + Object second_eval = eval(first_form->forward, env); + + addToEnv(env, name, second_eval); + + return *first_form; } Object evalIfArgs(const Object *arg_forms, struct Environment *env) { - printf("evalIfArgs()\n"); - Object o; - - printf("test_form:\n"); - const Object *test_form = arg_forms; - printObj(test_form); - printObj(test_form->list); - //printObj(test_form->list->forward); - - printf("test_eval:\n"); - Object test_eval = eval(test_form, env); - printObj(&test_eval); - - printf("test_form END\n"); - - o.type = TYPE_NUMBER; - o.number = 222; - return o; + return eval(arg_forms, env).number? + eval(arg_forms->forward, env) : + eval(arg_forms->forward->forward, env); } Object evalBuiltIns(const Object *first, const Object *rest, int *found, @@ -152,7 +127,7 @@ Object evalBuiltIns(const Object *first, const Object *rest, int *found, { if(strcmp(first->name, "def") == 0) { *found = 0; - return evalDefArgs(first, rest, env); + return evalDefArgs(rest, env); }else if(strcmp(first->name, "if") == 0) { *found = 0; return evalIfArgs(rest, env); @@ -165,20 +140,27 @@ Object evalBuiltIns(const Object *first, const Object *rest, int *found, Object eval(const Object *obj, struct Environment *env) { - printf("eval(): "); - printObj(obj); + // printf("eval(): "); + // printObj(obj); Object o = *obj; switch(obj->type) { case TYPE_NUMBER: case TYPE_BOOL: - return *obj; + return o; case TYPE_SYMBOL: - return fetchFromEnvironment(obj->name, env); + o = fetchFromEnvironment(obj->name, env); + printf("fetched object '%s':\n", obj->name); + printObj(&o); + return o; case TYPE_LIST: { - Object first_form = *obj->forward; + if(listLength(obj) == 1) { + o = *obj->list; + return o; + } + Object first_form = *obj->list; { // Try to eval built-ins int i = -1; @@ -195,7 +177,9 @@ Object eval(const Object *obj, struct Environment *env) Object arg2 = eval(first_form.forward->forward, env); printf("Evaluating func\n"); - return first_eval.func(arg1, arg2); + Object func_eval = first_eval.func(arg1, arg2); + deleteList(obj); + return func_eval; } default: ; @@ -203,37 +187,6 @@ Object eval(const Object *obj, struct Environment *env) return o; } -char* stringObj(char *dest, const Object *obj) -{ - if(obj->type == TYPE_NUMBER) { - snprintf(dest, MAX_TOK_LEN, "%d", obj->number); - } else if(obj->type == TYPE_SYMBOL) { - snprintf(dest, MAX_TOK_LEN, "%s", obj->name); - } else if(obj->type == TYPE_BOOL) { - snprintf(dest, MAX_TOK_LEN, "%s", obj->number ? "T" : "F"); - } - - return dest; -} - -void printObj(const Object *obj) -{ - if(obj->type == TYPE_NUMBER) { - printf("TYPE_NUMBER"); - } else if(obj->type == TYPE_LIST) { - printf("TYPE_LIST"); - } else if(obj->type == TYPE_SYMBOL) { - printf("TYPE_SYMBOL"); - } else if(obj->type == TYPE_BOOL) { - printf("TYPE_BOOL"); - } else { - printf("TYPE_OTHER"); - } - char temp[20] = ""; - stringObj(temp, obj); - printf(": %s\n", temp); -} - Result resultFromObjAndSlices(Object obj, struct Slice *slices) { Result r; @@ -242,37 +195,54 @@ Result resultFromObjAndSlices(Object obj, struct Slice *slices) return r; } +// todo could include and return a starting index for faster multi-adds +void addToEnv(struct Environment *env, const char *name, const Object obj) +{ + int i; + for(i = 0; i < MAX_ENV_ELM; i++) { + if(env->strings[i] == NULL) { + env->strings[i] = malloc(sizeof(name)); + strncpy(env->strings[i], name, MAX_TOK_LEN); + env->objects[i] = obj; + break; + } + } +} + Object basicOp(Object *obj1, Object *obj2, const char op) { Object o; o.forward = NULL; o.type = TYPE_NUMBER; + const int n1 = obj1->number; + const int n2 = obj2->number; + switch(op){ case '+': - o.number = obj1->number + obj2->number; + o.number = n1 + n2; return o; case '-': - o.number = obj1->number - obj2->number; + o.number = n1 - n2; return o; case '*': - o.number = obj1->number * obj2->number; + o.number = n1 * n2; return o; case '/': - o.number = obj1->number / obj2->number; + o.number = n1 / n2; return o; } o.type = TYPE_BOOL; switch(op) { case '=': - o.number = obj1->number == obj2->number; + o.number = n1 == n2; return o; case '>': - o.number = obj1->number > obj2->number; + o.number = n1 > n2; return o; case '<': - o.number = obj1->number < obj2->number; + o.number = n1 < n2; return o; } @@ -291,24 +261,31 @@ bopf(sub, '-'); bopf(mul, '*'); bopf(dvi, '/'); bopf(equ, '='); +bopf(gth, '>'); +bopf(lth, '<'); void addFunc(const char *name, Object (*func)(Object, Object), struct Environment *env) { - int i; - for(i = 0; i < MAX_ENV_ELM; i++) { - if(env->strings[i] == NULL) { - //printf("Adding at %d\n", i); - env->strings[i] = malloc(sizeof(name)); - strncpy(env->strings[i], name, MAX_TOK_LEN); - Object o; - o.type = TYPE_FUNC; - o.forward = NULL; - o.func = func; - env->objects[i] = o; - break; - } + Object o; + o.type = TYPE_FUNC; + o.forward = NULL; + o.func = func; + addToEnv(env, name, o); +} + +void deleteEnv(struct Environment *e) +{ + int i = 0; + while(e->strings[i]) { + free(e->strings[i]); + i++; } + free(e->strings); + e->strings = NULL; + + free(e->objects); + e->objects = NULL; } struct Environment defaultEnv() { @@ -317,42 +294,32 @@ struct Environment defaultEnv() { for(int i = 0; i < MAX_ENV_ELM; i++) { e.strings[i] = NULL; } + e.objects = malloc(sizeof(Object) * MAX_ENV_ELM); + addFunc("+", &add, &e); addFunc("-", &sub, &e); addFunc("*", &mul, &e); addFunc("/", &dvi, &e); addFunc("=", &equ, &e); + addFunc(">", >h, &e); + addFunc("<", <h, &e); - /* - e.strings[0] = malloc(sizeof("+")); - strncpy(e.strings[0], "+", MAX_TOK_LEN); - Object o; - o.type = TYPE_FUNC; - o.forward = NULL; - o.func = &add; - e.objects[0] = o; - */ return e; } Object parseEval(const char *input, struct Environment *env) { - struct Slice *tokens = tokenize(input); - struct Slice *debug = tokens; + struct Slice *tokens = nf_tokenize(input); #ifdef STANDALONE + struct Slice *debug = tokens; if(debug) { while(debug->text) { char tok[MAX_TOK_LEN]; copySlice(tok, debug); - // printf("'%s', ", tok); debug++; } - // printf("\n"); - } else { - // printf("parse error\n"); } - // printf("parseEval() parse()\n"); #endif Object parsed = parse(tokens).obj; free(tokens); @@ -368,32 +335,33 @@ int repl(struct Environment *env) fgets(input, 100, stdin); Object obj = parseEval(input, env); printObj(&obj); - //printf("eval: %d\n", obj.number); - break; + //break; } } int main(void) { struct Environment env = defaultEnv(); - if(1) { - repl(&env); - } else { - struct Slice *tokens = tokenize("(+ 10 5)"); - struct Slice *debug = tokens; +#ifndef NO_REPL + repl(&env); +#else + struct Slice *tokens = nf_tokenize("(+ 10 5)"); + struct Slice *debug = tokens; - if(debug) { - while(debug->text) { - char tok[10]; - copySlice(tok, debug); - printf("'%s', ", tok); - debug++; - } - printf("\n"); - } else { - printf("parse error\n"); + if(debug) { + while(debug->text) { + char tok[10]; + copySlice(tok, debug); + printf("'%s', ", tok); + debug++; } - parse(tokens); + printf("\n"); + } else { + printf("parse error\n"); } + parse(tokens); + free(tokens); +#endif + deleteEnv(&env); } #endif diff --git a/src/pebblisp.h b/src/pebblisp.h index 3ff1664..ffd575e 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -2,54 +2,13 @@ #define PEBBLISP_H // #define STANDALONE +// #define NO_REPL -#define MAX_TOK_LEN 4 -#define MAX_TOK_CNT 128 // 128 -#define MAX_ENV_ELM 15 // 50 - -// static const char* tokenFail = "Missing ')'\n"; - -typedef struct Object Object; +#include "object.h" struct Slice { const char *text; - int length; -}; - -typedef enum Type { - TYPE_NUMBER, - TYPE_BOOL, - TYPE_LIST, - TYPE_FUNC, - //TYPE_STRING, - TYPE_SYMBOL, - //TYPE_CONS, - //TYPE_LAMBDA, - //TYPE_MACRO, - //TYPE_PRIMITIVE, - TYPE_ENV, - TYPE_ERROR -} Type; - -struct Object { - Type type; - Object *forward; - union { - int number; - Object *list; - char name[MAX_TOK_LEN]; - Object (*func)(Object, Object); - - /* - struct { double number; }; // number - struct { char string[sizeof (Object *[3])]; }; // string, symbol - struct { Object *car, *cdr; }; // cons - struct { Object *params, *body, *env; }; // lambda, macro - struct { int primitive; char *name; }; // primitive - struct { Object *parent, *vars, *vals; }; // env - struct { Object *forward; }; // forwarding pointer - */ - }; + char length; }; typedef struct Result { @@ -63,18 +22,22 @@ struct Environment { }; Object eval(const Object *obj, struct Environment *env); -char* stringObj(char *dest, const Object *obj); Result parse(struct Slice *slices); Result readSeq(struct Slice *slices); Object parseAtom(struct Slice *slice); void copySlice(char * dest, struct Slice *src); Object parseEval(const char *input, struct Environment *env); struct Environment defaultEnv(); -void printObj(const Object *obj); +void deleteEnv(struct Environment *e); +void addToEnv(struct Environment *env, const char *name, const Object obj); Result resultFromObjAndSlices(Object obj, struct Slice *slices); Object add(Object obj1, Object obj2); +// Slices +void copySlice(char * dest, struct Slice *src); +void debugSlice(struct Slice *s); + #define R(_obj, _slices) resultFromObjAndSlices(_obj, _slices) #endif diff --git a/src/tags b/src/tags index 04f9d44..09ae243 100644 --- a/src/tags +++ b/src/tags @@ -4,79 +4,81 @@ !_TAG_PROGRAM_NAME Exuberant Ctags // !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ !_TAG_PROGRAM_VERSION 5.9~svn20110310 // -END_PHRASE calc.h 6;" d +CALC_H calc.h 2;" d +CODE_PKEY calc.h 11;" d +END_PHRASE calc.h 9;" d Environment pebblisp.h /^struct Environment {$/;" s -FIXED_MAX fixed.h /^static const fixed FIXED_MAX = INT_MAX;$/;" v -FIXED_SCALE fixed.h 40;" d -MAX_ENV_ELM pebblisp.h 8;" d -MAX_LENGTH calc.h 5;" d -MAX_TOK_CNT pebblisp.h 7;" d -MAX_TOK_LEN pebblisp.h 6;" d -Object pebblisp.h /^struct Object {$/;" s -Object pebblisp.h /^typedef struct Object Object;$/;" t typeref:struct:Object +MAX_ENV_ELM object.h 6;" d +MAX_LENGTH calc.h 8;" d +MAX_TOK_CNT object.h 5;" d +MAX_TOK_LEN object.h 4;" d +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 78;" d +R pebblisp.h 41;" d Result pebblisp.h /^typedef struct Result {$/;" s Result pebblisp.h /^} Result;$/;" t typeref:struct:Result -SMAX_LENGTH calc.h 4;" d +SMAX_LENGTH calc.h 7;" d Slice pebblisp.h /^struct Slice {$/;" s TOKENS_H tokens.h 2;" d -TOKEN_END calc.h 28;" d -TYPE_BOOL pebblisp.h /^ TYPE_BOOL,$/;" e enum:Type -TYPE_ENV pebblisp.h /^ TYPE_ENV,$/;" e enum:Type -TYPE_ERROR pebblisp.h /^ TYPE_ERROR$/;" e enum:Type -TYPE_FUNC pebblisp.h /^ TYPE_FUNC,$/;" e enum:Type -TYPE_LIST pebblisp.h /^ TYPE_LIST,$/;" e enum:Type -TYPE_NUMBER pebblisp.h /^ TYPE_NUMBER,$/;" e enum:Type -TYPE_SYMBOL pebblisp.h /^ TYPE_SYMBOL,$/;" e enum:Type -Type pebblisp.h /^typedef enum Type {$/;" g -Type pebblisp.h /^} Type;$/;" t typeref:enum:Type -_h_FIXED_ fixed.h 26;" d +TOKEN_END calc.h 42;" d +TYPE_BOOL object.h /^ TYPE_BOOL,$/;" e enum:Type +TYPE_ERROR object.h /^ TYPE_ERROR$/;" e enum:Type +TYPE_FUNC object.h /^ TYPE_FUNC,$/;" e enum:Type +TYPE_LIST object.h /^ TYPE_LIST,$/;" e enum:Type +TYPE_NUMBER object.h /^ TYPE_NUMBER,$/;" e enum:Type +TYPE_SYMBOL object.h /^ TYPE_SYMBOL,$/;" e enum:Type +Type object.h /^typedef enum Type {$/;" g +Type object.h /^} Type;$/;" t typeref:enum:Type addFunc pebblisp.c /^void addFunc(const char *name, Object (*func)(Object, Object), $/;" f +addToEnv pebblisp.c /^void addToEnv(struct Environment *env, const char *name, const Object obj)$/;" f +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 -bopf pebblisp.c 257;" d file: +bopf pebblisp.c 264;" d file: calculate calc.c /^static void calculate(){$/;" f file: click_config_provider calc.c /^static void click_config_provider(void *context) {$/;" f file: copySlice pebblisp.c /^void copySlice(char * dest, struct Slice *src)$/;" f debugSlice pebblisp.c /^void debugSlice(struct Slice *s)$/;" f 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 enter calc.c /^static void enter(){$/;" f file: -env calc.c /^static struct Environment env;$/;" v typeref:struct:Environment file: +env calc.h /^static struct Environment env;$/;" v typeref:struct:Environment eval pebblisp.c /^Object eval(const Object *obj, struct Environment *env)$/;" f evalBuiltIns pebblisp.c /^Object evalBuiltIns(const Object *first, const Object *rest, int *found,$/;" f -evalIfArgs pebblisp.c /^Object evalIfArgs(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 fetchFromEnvironment pebblisp.c /^Object fetchFromEnvironment(const char *name, struct Environment *env)$/;" f -fixed fixed.h /^typedef int fixed;$/;" t -fixed_add fixed.c /^fixed fixed_add(fixed lhs, fixed rhs, bool* overflow)$/;" f -fixed_div fixed.c /^fixed fixed_div(fixed lhs, fixed rhs)$/;" f -fixed_mult fixed.c /^fixed fixed_mult(fixed lhs, fixed rhs, bool* overflow)$/;" f -fixed_pow fixed.c /^fixed fixed_pow(fixed base, int exponent, bool* overflow)$/;" f -fixed_repr fixed.c /^char* fixed_repr(fixed fixed, char* buffer, size_t size)$/;" f -fixed_subt fixed.c /^fixed fixed_subt(fixed lhs, fixed rhs, bool* overflow)$/;" f -fixed_to_int fixed.c /^int fixed_to_int(fixed n)$/;" f -forward pebblisp.h /^ Object *forward;$/;" m struct:Object -func pebblisp.h /^ Object (*func)(Object, Object);$/;" m union:Object::__anon1 -getToken calc.c /^static inline char* getToken(int n) {$/;" f file: +forward object.h /^ Object *forward;$/;" m struct:Object +func object.h /^ Object (*func)(Object, Object);$/;" m union:Object::__anon1 +getToken calc.c /^static inline char* getToken(int8_t n) {$/;" f file: init calc.c /^static void init(void) {$/;" f file: -int_to_fixed fixed.c /^fixed int_to_fixed(int n)$/;" f isDigit tokens.c /^int isDigit(const char c) {$/;" f isSingle tokens.c /^int isSingle(const char c) {$/;" f isWhitespace tokens.c /^int isWhitespace(const char c) {$/;" f -length pebblisp.h /^ int length;$/;" m struct:Slice -list pebblisp.h /^ Object *list;$/;" m union:Object::__anon1 +length pebblisp.h /^ char length;$/;" m struct:Slice +list object.h /^ Object *list;$/;" m union:Object::__anon1 +listLength object.c /^int listLength(const Object *listObj)$/;" f +listObject object.c /^inline Object listObject()$/;" f main calc.c /^int main(void) {$/;" f main pebblisp.c /^int main(void)$/;" f mytext calc.h /^char mytext[SMAX_LENGTH] = "";$/;" v -name pebblisp.h /^ char name[MAX_TOK_LEN];$/;" m union:Object::__anon1 -number pebblisp.h /^ int number;$/;" m union:Object::__anon1 +name object.h /^ char name[MAX_TOK_LEN];$/;" m union:Object::__anon1 +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 +numberObject object.c /^inline Object numberObject(int num)$/;" f obj pebblisp.h /^ Object obj;$/;" m struct:Result objects pebblisp.h /^ Object *objects;$/;" m struct:Environment 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 -printObj pebblisp.c /^void printObj(const Object *obj)$/;" f +printList object.c /^void printList(const Object *list)$/;" f +printObj object.c /^void printObj(const Object *obj)$/;" f +printf object.c 7;" d file: printf pebblisp.c 8;" d file: printf tokens.c 7;" d file: readSeq pebblisp.c /^Result readSeq(struct Slice *tokens)$/;" f @@ -87,17 +89,16 @@ s_input_text_layer calc.h /^TextLayer *s_input_text_layer;$/;" v s_result_text_layer calc.h /^TextLayer *s_result_text_layer;$/;" v s_window calc.h /^Window *s_window;$/;" v select_handler calc.c /^static void select_handler(ClickRecognizerRef recognizer, void *context){$/;" f file: -selected_token calc.c /^static int8_t selected_token = 1; \/\/Currently selected button, starts on '5'$/;" v file: +selected_token calc.c /^static int8_t selected_token = 1;$/;" v file: singleTokens tokens.c /^static const char singleTokens[] = "()+-*\/=";$/;" v file: slices pebblisp.h /^ struct Slice *slices;$/;" m struct:Result typeref:struct:Result::Slice -str_to_fixed fixed.c /^fixed str_to_fixed(const char* str, bool* overflow)$/;" f -str_to_int fixed.c /^int str_to_int(const char *str, char **endptr, int maxnum) {$/;" f -stringObj pebblisp.c /^char* stringObj(char *dest, const Object *obj)$/;" f +stringObj object.c /^char* stringObj(char *dest, const Object *obj)$/;" f strings pebblisp.h /^ char **strings;$/;" m struct:Environment +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 -tokenize tokens.c /^struct Slice *tokenize(const char *input)$/;" f +tokenCount calc.c /^static inline int8_t tokenCount() {$/;" f file: tokens calc.h /^char *tokens[] = {$/;" v -type pebblisp.h /^ Type type;$/;" m struct:Object +type object.h /^ Type type;$/;" m struct:Object up_down_handler calc.c /^static void up_down_handler(ClickRecognizerRef recognizer, void *context){$/;" f file: updateText calc.c /^static void updateText()$/;" f file: diff --git a/src/tokens.c b/src/tokens.c index 8d7d8ff..2bc418d 100644 --- a/src/tokens.c +++ b/src/tokens.c @@ -4,7 +4,7 @@ #ifdef STANDALONE #include #else -#define printf(...) tokenize(NULL) +#define printf(...) nf_tokenize(NULL) #endif /* @@ -39,7 +39,8 @@ int notWhitespace(const char c) { return !isWhitespace(c); } -struct Slice *tokenize(const char *input) +// Return needs to be freed, if not null +struct Slice *nf_tokenize(const char *input) { if(!input) return NULL; @@ -51,7 +52,7 @@ struct Slice *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++; @@ -77,6 +78,8 @@ struct Slice *tokenize(const char *input) int l = 1; while(!isWhitespace(input[++i]) && !isSingle(input[i])) { l++; + //slices[slice].length = l; + //debugSlice(&slices[slice]); } slices[slice].length = l; slice++; diff --git a/src/tokens.h b/src/tokens.h index 0ec7d8c..03a2fe0 100644 --- a/src/tokens.h +++ b/src/tokens.h @@ -4,6 +4,6 @@ #include "pebblisp.h" int isSingle(const char c); int isDigit(const char c); -struct Slice *tokenize(const char *input); +struct Slice *nf_tokenize(const char *input); #endif