Finally some consistent styling.

Centralized printf/printd defines in object.h
Removed null/isList checking from FOR_POINTER_IN_LIST
This commit is contained in:
Sage Vaillancourt 2022-01-07 16:55:03 -05:00 committed by Sage Vaillancourt
parent 8d22bf575c
commit e2c977e95a
14 changed files with 892 additions and 708 deletions

View File

@ -7,18 +7,18 @@
#include "calc.h" #include "calc.h"
// Custom layers that users can build // Custom layers that users can build
Window *s_custom_window; Window* s_custom_window;
TextLayer *s_heading_text_layer; TextLayer* s_heading_text_layer;
char header[30] = ""; char header[30] = "";
// Code display // Code display
Window *s_code_window; Window* s_code_window;
TextLayer *s_input_text_layer; TextLayer* s_input_text_layer;
TextLayer *s_result_text_layer; TextLayer* s_result_text_layer;
// Script selection // Script selection
Window *s_script_menu_window; Window* s_script_menu_window;
MenuLayer *s_script_select_layer; MenuLayer* s_script_select_layer;
int current_script_num; int current_script_num;
// PebbLisp environment // PebbLisp environment
@ -32,12 +32,12 @@ int excess_chars = 1;
#define RESULT_PREFIX "R:" #define RESULT_PREFIX "R:"
char result_text[RESULT_LENGTH] = RESULT_PREFIX; char result_text[RESULT_LENGTH] = RESULT_PREFIX;
const char *tokens[] = { const char* tokens[] = {
" ", "(", ")", " ", "(", ")",
"+ ", "- ", "* ", "/ ", "+ ", "- ", "* ", "/ ",
"1","2","3", "1", "2", "3",
"4","5","6", "4", "5", "6",
"7","8","9", "0", "x", "7", "8", "9", "0", "x",
"a", "b", "c", "d", "e", "a", "b", "c", "d", "e",
"= ", "< ", "> ", "= ", "< ", "> ",
"\"", "\"",
@ -51,7 +51,7 @@ const char *tokens[] = {
// Currently selected button, starts on '(' // Currently selected button, starts on '('
static int8_t selected_token = 1; static int8_t selected_token = 1;
const char *func_tokens[] = { const char* func_tokens[] = {
"window ", "window ",
"sc ", "cw ", "pw ", "rw ", "atl ", "utl ", "sc ", "cw ", "pw ", "rw ", "atl ", "utl ",
"sec ", "mnt ", "hr ", "hrt ", "vibe ", "sub " "sec ", "mnt ", "hr ", "hrt ", "vibe ", "sub "
@ -68,16 +68,16 @@ const uint32_t outbox_size = 1024;
// Get the number of tokens in the current list // Get the number of tokens in the current list
static inline int8_t tokenCount() static inline int8_t tokenCount()
{ {
return using_func_tokens? return using_func_tokens ?
sizeof(func_tokens) / sizeof(func_tokens[0]) : sizeof(func_tokens) / sizeof(func_tokens[0]) :
sizeof(tokens) / sizeof(tokens[0]); sizeof(tokens) / sizeof(tokens[0]);
} }
// Get current token from tokens[] or func_tokens[], as appropriate // Get current token from tokens[] or func_tokens[], as appropriate
static inline const char* getToken(int8_t n) static inline const char* getToken(int8_t n)
{ {
int8_t t = n % tokenCount(); int8_t t = n % tokenCount();
return using_func_tokens? func_tokens[t] : tokens[t]; return using_func_tokens ? func_tokens[t] : tokens[t];
} }
static void trim(size_t len) static void trim(size_t len)
@ -93,11 +93,11 @@ static void trim(size_t len)
static void updateText() static void updateText()
{ {
trim(excess_chars); trim(excess_chars);
const char *token = getToken(selected_token); const char* token = getToken(selected_token);
const char* add = const char* add =
token[0] == ' ' ? "_": // Display space as underscore token[0] == ' ' ? "_" : // Display space as underscore
token[0] == '\n'? "\\n": // Display newline as \n token[0] == '\n' ? "\\n" : // Display newline as \n
token; // Display others literally token; // Display others literally
strcat(displayed_code, add); strcat(displayed_code, add);
@ -107,19 +107,19 @@ static void updateText()
} }
// Cycle through the current list of tokens // Cycle through the current list of tokens
static void cycle_tokens(ClickRecognizerRef recognizer, void *context) static void cycle_tokens(ClickRecognizerRef recognizer, void* context)
{ {
// Change current token // Change current token
if(click_recognizer_get_button_id(recognizer) == BUTTON_ID_DOWN) { if (click_recognizer_get_button_id(recognizer) == BUTTON_ID_DOWN) {
selected_token++; selected_token++;
} else { } else {
selected_token--; selected_token--;
} }
// If selected token is outside of range, wrap around // If selected token is outside of range, wrap around
if(selected_token < 0) { if (selected_token < 0) {
selected_token = tokenCount() - 1; selected_token = tokenCount() - 1;
} else if(selected_token >= tokenCount()) { } else if (selected_token >= tokenCount()) {
selected_token = 0; selected_token = 0;
} }
@ -127,7 +127,7 @@ static void cycle_tokens(ClickRecognizerRef recognizer, void *context)
} }
static GFont tiny_font; static GFont tiny_font;
static const char *fonts[] = { static const char* fonts[] = {
FONT_KEY_GOTHIC_28_BOLD, FONT_KEY_GOTHIC_28_BOLD,
FONT_KEY_GOTHIC_24_BOLD, FONT_KEY_GOTHIC_24_BOLD,
FONT_KEY_GOTHIC_18_BOLD, FONT_KEY_GOTHIC_18_BOLD,
@ -140,26 +140,28 @@ static void adjustFont()
{ {
int i = 0; int i = 0;
int size = 0; int size = 0;
while(displayed_code[i++]) { while (displayed_code[i++]) {
if(displayed_code[i] == '\n') if (displayed_code[i] == '\n') {
size += 10; size += 10;
}
size++; size++;
} }
// Use various system fonts for most text // Use various system fonts for most text
if(size <= 100) { if (size <= 100) {
int f = size < 50 ? smallestFont - 3 : const char* f = fonts[
size < 80 ? smallestFont - 2 : size < 50 ? smallestFont - 3 :
size < 100 ? smallestFont - 1 : size < 80 ? smallestFont - 2 :
smallestFont; size < 100 ? smallestFont - 1 :
text_layer_set_font(s_input_text_layer, smallestFont
fonts_get_system_font(fonts[f])); ];
text_layer_set_font(s_input_text_layer, fonts_get_system_font(f));
} else { } else {
// Use custom extra small font for lots of text // Use custom extra small font for lots of text
text_layer_set_font(s_input_text_layer, tiny_font); text_layer_set_font(s_input_text_layer, tiny_font);
} }
} }
static void custom_unload(Window *window) static void custom_unload(Window* window)
{ {
text_layer_destroy(s_heading_text_layer); text_layer_destroy(s_heading_text_layer);
@ -171,15 +173,15 @@ static void custom_unload(Window *window)
* In normal token list, backspace if possible, otherwise return to script list * In normal token list, backspace if possible, otherwise return to script list
* In function token list, return to normal token list * In function token list, return to normal token list
*/ */
static void click_backspace(ClickRecognizerRef recognizer, void *context) static void click_backspace(ClickRecognizerRef recognizer, void* context)
{ {
if(s_custom_window) { if (s_custom_window) {
window_stack_remove(s_custom_window, true); window_stack_remove(s_custom_window, true);
return; return;
} }
if(!using_func_tokens) { if (!using_func_tokens) {
if(displayed_code[0] == '\0') { if (displayed_code[0] == '\0') {
window_stack_remove(window_stack_get_top_window(), true); window_stack_remove(window_stack_get_top_window(), true);
} else { } else {
trim(excess_chars + 1); trim(excess_chars + 1);
@ -198,7 +200,7 @@ static void add_token()
{ {
strcat(displayed_code, getToken(selected_token)); strcat(displayed_code, getToken(selected_token));
selected_token = 0; selected_token = 0;
if(using_func_tokens) { if (using_func_tokens) {
using_func_tokens = false; using_func_tokens = false;
} }
@ -219,21 +221,23 @@ static void calculate()
updateText(); updateText();
stringNObj(temp, &obj, RESULT_LENGTH); stringNObj(temp, &obj, RESULT_LENGTH);
if(obj.type == TYPE_ERROR) { if (obj.type == TYPE_ERROR) {
text_layer_set_font(s_result_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD)); text_layer_set_font(s_result_text_layer,
fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD));
} else { } else {
text_layer_set_font(s_result_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD)); text_layer_set_font(s_result_text_layer,
fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
} }
snprintf(result_text, RESULT_LENGTH, RESULT_PREFIX "%s", temp); snprintf(result_text, RESULT_LENGTH, RESULT_PREFIX "%s", temp);
text_layer_set_text(s_result_text_layer, result_text); text_layer_set_text(s_result_text_layer, result_text);
} }
// Button press handler // Button press handler
static void click_select(ClickRecognizerRef recognizer, void *context) static void click_select(ClickRecognizerRef recognizer, void* context)
{ {
if(!using_func_tokens && selected_token == tokenCount() - 1) { if (!using_func_tokens && selected_token == tokenCount() - 1) {
calculate(); calculate();
} else if(!using_func_tokens && selected_token == tokenCount() - 2) { } else if (!using_func_tokens && selected_token == tokenCount() - 2) {
using_func_tokens = true; using_func_tokens = true;
selected_token = 0; selected_token = 0;
updateText(); updateText();
@ -243,13 +247,13 @@ static void click_select(ClickRecognizerRef recognizer, void *context)
} }
// Saves text in editor to persistent storage // Saves text in editor to persistent storage
static void click_save(ClickRecognizerRef recognizer, void *context) static void click_save(ClickRecognizerRef recognizer, void* context)
{ {
int8_t i = strlen(displayed_code); int8_t i = strlen(displayed_code);
unsigned token_len = strlen(getToken(selected_token)); unsigned token_len = strlen(getToken(selected_token));
printf("%s", displayed_code); printf("%s", displayed_code);
for(unsigned j = 0; j < token_len; j++) { for (unsigned j = 0; j < token_len; j++) {
displayed_code[i-(1 + j)] = '\0'; displayed_code[i - (1 + j)] = '\0';
printf("%s", displayed_code); printf("%s", displayed_code);
} }
@ -258,7 +262,7 @@ static void click_save(ClickRecognizerRef recognizer, void *context)
} }
// Sets the code_window click functions // Sets the code_window click functions
static void code_click_subscribe(void *context) static void code_click_subscribe(void* context)
{ {
window_single_repeating_click_subscribe(BUTTON_ID_UP, 100, cycle_tokens); window_single_repeating_click_subscribe(BUTTON_ID_UP, 100, cycle_tokens);
window_single_repeating_click_subscribe(BUTTON_ID_DOWN, 100, cycle_tokens); window_single_repeating_click_subscribe(BUTTON_ID_DOWN, 100, cycle_tokens);
@ -268,13 +272,13 @@ static void code_click_subscribe(void *context)
} }
#ifdef LOW_MEM #ifdef LOW_MEM
#define TIME_FUNC \ #define TIME_FUNC \
"(def time (fn ()(utl tt \n"\ "(def time (fn ()(utl tt \n"\
" (cat \"Hey, it's \" \n"\ " (cat \"Hey, it's \" \n"\
" (hrt) \":\" (mnt)\n" \ " (hrt) \":\" (mnt)\n" \
"))))\n" "))))\n"
#else #else
#define TIME_FUNC \ #define TIME_FUNC \
"(def time (fn () ((def m (mnt)) (utl tt \n"\ "(def time (fn () ((def m (mnt)) (utl tt \n"\
" (cat \"Hey, it's \"\n"\ " (cat \"Hey, it's \"\n"\
" (hrt) \":\" (if (< m 10) \"0\" \"\") m)\n"\ " (hrt) \":\" (if (< m 10) \"0\" \"\") m)\n"\
@ -290,9 +294,9 @@ static void code_click_subscribe(void *context)
// Remove to re-enable // Remove to re-enable
#undef FORCE_TEXT #undef FORCE_TEXT
static void code_window_load(Window *window) static void code_window_load(Window* window)
{ {
Layer *window_layer = window_get_root_layer(window); Layer* window_layer = window_get_root_layer(window);
GRect bounds = layer_get_bounds(window_layer); GRect bounds = layer_get_bounds(window_layer);
// Register click config provider // Register click config provider
@ -301,44 +305,51 @@ static void code_window_load(Window *window)
// Input text layer setup // Input text layer setup
s_input_text_layer = text_layer_create(bounds); s_input_text_layer = text_layer_create(bounds);
text_layer_set_text(s_input_text_layer, getToken(1)); 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)); text_layer_set_font(s_input_text_layer,
layer_add_child(window_get_root_layer(s_code_window), text_layer_get_layer(s_input_text_layer)); fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD));
layer_add_child(window_get_root_layer(s_code_window),
text_layer_get_layer(s_input_text_layer));
// Result text layer setup // Result text layer setup
GRect result_bounds = GRect(6, 148, 132, 132); GRect result_bounds = GRect(6, 148, 132, 132);
s_result_text_layer = text_layer_create(result_bounds); s_result_text_layer = text_layer_create(result_bounds);
text_layer_set_text(s_result_text_layer, result_text); text_layer_set_text(s_result_text_layer, result_text);
text_layer_set_font(s_result_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD)); text_layer_set_font(s_result_text_layer,
fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
text_layer_set_text_alignment(s_result_text_layer, GTextAlignmentRight); text_layer_set_text_alignment(s_result_text_layer, GTextAlignmentRight);
layer_add_child(window_get_root_layer(s_code_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' // Push the window, setting the window animation to 'true'
window_stack_push(s_code_window, true); window_stack_push(s_code_window, true);
// If possible, load the previous code text // If possible, load the previous code text
#ifdef FORCE_TEXT #ifdef FORCE_TEXT
strncpy(displayed_code, FORCE_TEXT, SMAX_LENGTH); strncpy(displayed_code, FORCE_TEXT, SMAX_LENGTH);
updateText(); updateText();
adjustFont(); adjustFont();
#else #else
if(persist_exists(current_script_num)) { if (persist_exists(current_script_num)) {
persist_read_string(current_script_num, displayed_code, SMAX_LENGTH); persist_read_string(current_script_num, displayed_code, SMAX_LENGTH);
updateText(); updateText();
adjustFont(); adjustFont();
} }
#endif #endif
} }
void debug_result(const char* d) { void debug_result(const char* d)
{
snprintf(result_text, RESULT_LENGTH, "%s", d); snprintf(result_text, RESULT_LENGTH, "%s", d);
text_layer_set_text(s_result_text_layer, result_text); text_layer_set_text(s_result_text_layer, result_text);
psleep(300); psleep(300);
} }
static Object run_script(Object script_num, Object obj, struct Environment *e) { static Object run_script(Object script_num, Object obj,
struct Environment* e)
{
int n = script_num.number - 1; int n = script_num.number - 1;
if(persist_exists(n)) { if (persist_exists(n)) {
char *code = malloc(sizeof(char) * SMAX_LENGTH); char* code = malloc(sizeof(char) * SMAX_LENGTH);
persist_read_string(n, code, SMAX_LENGTH); persist_read_string(n, code, SMAX_LENGTH);
Object o = parseEval(code, e); Object o = parseEval(code, e);
free(code); free(code);
@ -347,7 +358,7 @@ static Object run_script(Object script_num, Object obj, struct Environment *e) {
return errorObject(SCRIPT_NOT_FOUND); return errorObject(SCRIPT_NOT_FOUND);
} }
static void code_window_unload(Window *window) static void code_window_unload(Window* window)
{ {
// Save the current code text // Save the current code text
persist_write_string(current_script_num, displayed_code); persist_write_string(current_script_num, displayed_code);
@ -361,11 +372,11 @@ static void code_window_unload(Window *window)
void code_window_push() void code_window_push()
{ {
if(!s_code_window) { if (!s_code_window) {
s_code_window = window_create(); s_code_window = window_create();
WindowHandlers wh = { WindowHandlers wh = {
.load = code_window_load, .load = code_window_load,
.unload = code_window_unload }; .unload = code_window_unload};
window_set_window_handlers(s_code_window, wh); window_set_window_handlers(s_code_window, wh);
} }
@ -374,47 +385,50 @@ void code_window_push()
/** Menu Window **/ /** Menu Window **/
static void select_callback(struct MenuLayer *menu_layer, static void select_callback(MenuLayer* menu_layer, MenuIndex* cell_index,
MenuIndex *cell_index, void *context) void* context)
{ {
current_script_num = cell_index->row; current_script_num = cell_index->row;
code_window_push(); code_window_push();
} }
static uint16_t get_num_rows_callback(MenuLayer *menu_layer, static uint16_t get_num_rows_callback(MenuLayer* menu_layer,
uint16_t section_index, void *context) uint16_t section_index, void* context)
{ {
return SCRIPT_COUNT; return SCRIPT_COUNT;
} }
static void draw_row_callback(GContext *ctx, const Layer *cell_layer, static void draw_row_callback(GContext* ctx, const Layer* cell_layer,
MenuIndex *cell_index, void *context) MenuIndex* cell_index, void* context)
{ {
static char s_buff[16]; static char s_buff[16];
snprintf(s_buff, sizeof(s_buff), "Script %d", 1 + (int)cell_index->row); snprintf(s_buff, sizeof(s_buff), "Script %d", 1 + (int) cell_index->row);
// Draw this row's index // Draw this row's index
menu_cell_basic_draw(ctx, cell_layer, s_buff, NULL, NULL); menu_cell_basic_draw(ctx, cell_layer, s_buff, NULL, NULL);
} }
static int16_t get_cell_height_callback(struct MenuLayer *menu_layer, static int16_t get_cell_height_callback(MenuLayer* menu_layer,
MenuIndex *cell_index, void *context) MenuIndex* cell_index, void* context)
{ {
return CELL_HEIGHT; return CELL_HEIGHT;
} }
static void script_menu_load(Window *window) static void script_menu_load(Window* window)
{ {
Layer *window_layer = window_get_root_layer(window); Layer* window_layer = window_get_root_layer(window);
GRect bounds = layer_get_bounds(window_layer); GRect bounds = layer_get_bounds(window_layer);
s_script_select_layer = menu_layer_create(bounds); s_script_select_layer = menu_layer_create(bounds);
menu_layer_set_click_config_onto_window(s_script_select_layer, window); menu_layer_set_click_config_onto_window(s_script_select_layer, window);
#if defined(PBL_COLOR) #if defined(PBL_COLOR)
menu_layer_set_normal_colors(s_script_select_layer, GColorBlack, GColorWhite); menu_layer_set_normal_colors(s_script_select_layer,
menu_layer_set_highlight_colors(s_script_select_layer, GColorDukeBlue, GColorWhite); GColorBlack, GColorWhite);
#endif
menu_layer_set_highlight_colors(s_script_select_layer,
GColorDukeBlue, GColorWhite);
#endif
menu_layer_set_callbacks(s_script_select_layer, NULL, (MenuLayerCallbacks) { menu_layer_set_callbacks(s_script_select_layer, NULL, (MenuLayerCallbacks) {
.get_num_rows = get_num_rows_callback, .get_num_rows = get_num_rows_callback,
@ -422,19 +436,20 @@ static void script_menu_load(Window *window)
.get_cell_height = get_cell_height_callback, .get_cell_height = get_cell_height_callback,
.select_click = select_callback, .select_click = select_callback,
}); });
layer_add_child(window_layer, menu_layer_get_layer(s_script_select_layer)); layer_add_child(window_layer, menu_layer_get_layer(s_script_select_layer));
} }
static void script_menu_unload(Window *window) static void script_menu_unload(Window* window)
{ {
menu_layer_destroy(s_script_select_layer); menu_layer_destroy(s_script_select_layer);
} }
/** Custom Window **/ /** Custom Window **/
static void custom_load(Window *window) static void custom_load(Window* window)
{ {
Layer *window_layer = window_get_root_layer(window); Layer* window_layer = window_get_root_layer(window);
GRect bounds = layer_get_bounds(window_layer); GRect bounds = layer_get_bounds(window_layer);
// Register click config provider // Register click config provider
@ -452,16 +467,17 @@ static void custom_load(Window *window)
window_stack_push(s_custom_window, true); window_stack_push(s_custom_window, true);
} }
Object add_window(Object obj1, Object _, struct Environment *env) Object add_window(Object obj1, Object _, struct Environment* env)
{ {
printf("ADD_WINDOW\n"); printf("ADD_WINDOW\n");
stringObj(header, &obj1); stringObj(header, &obj1);
if(!s_custom_window) { if (!s_custom_window) {
s_custom_window = window_create(); s_custom_window = window_create();
WindowHandlers wh = { WindowHandlers wh = {
.load = custom_load, .load = custom_load,
.unload = custom_unload }; .unload = custom_unload
};
window_set_window_handlers(s_custom_window, wh); window_set_window_handlers(s_custom_window, wh);
} }
@ -470,14 +486,15 @@ Object add_window(Object obj1, Object _, struct Environment *env)
return numberObject(1); return numberObject(1);
} }
static void inbox_received_callback(DictionaryIterator *iter, void *context) { static void inbox_received_callback(DictionaryIterator* iter, void* context)
Tuple *script_tuple = dict_find(iter, MESSAGE_KEY_ScriptText); {
if(script_tuple) { Tuple* script_tuple = dict_find(iter, MESSAGE_KEY_ScriptText);
if(!s_code_window) { if (script_tuple) {
if (!s_code_window) {
current_script_num = 0; current_script_num = 0;
code_window_push(); code_window_push();
} }
char *script_text = script_tuple->value->cstring; char* script_text = script_tuple->value->cstring;
snprintf(displayed_code, sizeof(displayed_code), "%s", script_text); snprintf(displayed_code, sizeof(displayed_code), "%s", script_text);
updateText(); updateText();
} }

View File

@ -9,6 +9,6 @@
#define SCRIPT_COUNT 5 #define SCRIPT_COUNT 5
void debug_result(const char *d); void debug_result(const char* d);
#endif #endif

133
src/env.c
View File

@ -1,21 +1,18 @@
#include "env.h" #include "env.h"
#include "pebblisp.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#ifndef STANDALONE #include "pebblisp.h"
#include <pebble.h>
#undef printf
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
#endif
Object fetchFromEnvironment(const char *name, struct Environment *env) Object fetchFromEnvironment(const char* name, struct Environment* env)
{ {
if(!env) if (!env) {
return errorObject(NULL_ENV); return errorObject(NULL_ENV);
}
if(env->size == 0) { if (env->size == 0) {
if (env->outer) { if (env->outer) {
return fetchFromEnvironment(name, env->outer); return fetchFromEnvironment(name, env->outer);
} else { } else {
@ -23,52 +20,51 @@ Object fetchFromEnvironment(const char *name, struct Environment *env)
} }
} }
for(int i = 0; i < env->size; i++) { for (int i = 0; i < env->size; i++) {
if(env->strings[i] == NULL) { if (env->strings[i] == NULL) {
printd("Try %d (NULL)\n", i); printd("Try %d (NULL)\n", i);
break; break;
} }
printd("Try %d (%s)\n", i, env->strings[i]); printd("Try %d (%s)\n", i, env->strings[i]);
debugObj(&env->objects[i]); debugObj(&env->objects[i]);
if(strcmp(name, env->strings[i]) == 0) { if (strcmp(name, env->strings[i]) == 0) {
printd("Returning!\n"); printd("Returning!\n");
return cloneObject(env->objects[i]); return cloneObject(env->objects[i]);
} }
} }
printd("Trying outer %p\n", env->outer); printd("Trying outer %p\n", env->outer);
if(env->outer) { if (env->outer) {
return fetchFromEnvironment(name, env->outer); return fetchFromEnvironment(name, env->outer);
} }
return errorWithContext(DID_NOT_FIND_SYMBOL, name); return errorWithContext(DID_NOT_FIND_SYMBOL, name);
} }
struct Environment envForLambda(const Object *params, const Object *arg_forms, struct Environment envForLambda(const Object* params, const Object* arg_forms,
struct Environment *outer) struct Environment* outer)
{ {
int paramCount = listLength(params); int paramCount = listLength(params);
struct Environment env = { struct Environment env = {.outer = outer,
.outer = outer,
.strings = NULL, .strings = NULL,
.objects = NULL, .objects = NULL,
.size = paramCount .size = paramCount};
};
if(paramCount == 0) if (paramCount == 0) {
return env; return env;
}
env.strings = calloc(sizeof(char*), paramCount + 1); env.strings = calloc(sizeof(char*), paramCount + 1);
env.objects = malloc(sizeof(Object) * (paramCount + 1)); env.objects = malloc(sizeof(Object) * (paramCount + 1));
const Object *march = arg_forms; const Object* march = arg_forms;
for(int i = 0; i < paramCount; i++) { for (int i = 0; i < paramCount; i++) {
const char *newObjName = itemAt(params, i)->string; const char* newObjName = itemAt(params, i)->string;
// Eval the `march` list // Eval the `march` list
Object newEnvObj = eval(march, outer); Object newEnvObj = eval(march, outer);
addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms? addToEnv(&env, newObjName, newEnvObj); // Could use eval_forms?
cleanObject(&newEnvObj); cleanObject(&newEnvObj);
march = march->forward; march = march->forward;
} }
@ -82,15 +78,15 @@ struct Environment envForLambda(const Object *params, const Object *arg_forms,
// symbol was found // symbol was found
// //
// Returns the index of the symbol in the environment, if found. Otherwise, -1 // Returns the index of the symbol in the environment, if found. Otherwise, -1
int findInEnv(struct Environment **env, const char *name) int findInEnv(struct Environment** env, const char* name)
{ {
struct Environment *temp_env = *env; struct Environment* temp_env = *env;
while(temp_env) { while (temp_env) {
for(int i = 0; i < temp_env->size; i++) { for (int i = 0; i < temp_env->size; i++) {
if(temp_env->strings[i] == NULL) { if (temp_env->strings[i] == NULL) {
break; break;
} }
if(strcmp(temp_env->strings[i], name) == 0) { if (strcmp(temp_env->strings[i], name) == 0) {
*env = temp_env; *env = temp_env;
return i; return i;
} }
@ -101,7 +97,7 @@ int findInEnv(struct Environment **env, const char *name)
} }
// TODO Maybe extend environment using a new outer, instead of realloc // TODO Maybe extend environment using a new outer, instead of realloc
void addToEnv(struct Environment *env, const char *name, const Object obj) void addToEnv(struct Environment* env, const char* name, const Object obj)
{ {
// int sym_pos = findInEnv(&env, name); // int sym_pos = findInEnv(&env, name);
// if(sym_pos != -1) { // if(sym_pos != -1) {
@ -112,20 +108,21 @@ void addToEnv(struct Environment *env, const char *name, const Object obj)
// } // }
int i; int i;
struct Environment *temp_env = env; struct Environment* temp_env = env;
int is_local = 1; int is_local = 1;
while(temp_env) { while (temp_env) {
for(i = 0; i < temp_env->size; i++) { for (i = 0; i < temp_env->size; i++) {
// Add *new* item to env only if we're in the local scope // Add *new* item to env only if we're in the local scope
if(temp_env->strings[i] == NULL) { if (temp_env->strings[i] == NULL) {
if (is_local) { if (is_local) {
temp_env->strings[i] = calloc(sizeof(char), strlen(name) + 1); temp_env->strings[i] =
calloc(sizeof(char), strlen(name) + 1);
strncpy(temp_env->strings[i], name, strlen(name)); strncpy(temp_env->strings[i], name, strlen(name));
temp_env->objects[i] = cloneObject(obj); temp_env->objects[i] = cloneObject(obj);
return; return;
} }
break; break;
} else if(strcmp(temp_env->strings[i], name) == 0) { } else if (strcmp(temp_env->strings[i], name) == 0) {
Object o = cloneObject(obj); Object o = cloneObject(obj);
cleanObject(&temp_env->objects[i]); cleanObject(&temp_env->objects[i]);
temp_env->objects[i] = o; temp_env->objects[i] = o;
@ -143,7 +140,7 @@ void addToEnv(struct Environment *env, const char *name, const Object obj)
env->strings = realloc(env->strings, sizeof(char*) * env->size); env->strings = realloc(env->strings, sizeof(char*) * env->size);
env->objects = realloc(env->objects, sizeof(Object) * env->size); env->objects = realloc(env->objects, sizeof(Object) * env->size);
for(int j = 0; j < inc; j++) { for (int j = 0; j < inc; j++) {
env->strings[old_size + j] = NULL; env->strings[old_size + j] = NULL;
} }
@ -152,14 +149,14 @@ void addToEnv(struct Environment *env, const char *name, const Object obj)
env->objects[old_size] = cloneObject(obj); env->objects[old_size] = cloneObject(obj);
} }
void printEnv(struct Environment *env) void printEnv(struct Environment* env)
{ {
if(!env) { if (!env) {
printf("NULL env\n"); printf("NULL env\n");
return; return;
} }
for(int i = 0; i < env->size; i++) { for (int i = 0; i < env->size; i++) {
if(env->strings[i] == NULL) { if (env->strings[i] == NULL) {
printf("env[%d]: NULL %p\n", i, env->strings[i]); printf("env[%d]: NULL %p\n", i, env->strings[i]);
break; break;
} }
@ -170,19 +167,20 @@ void printEnv(struct Environment *env)
} }
} }
void addFunc(const char *name, Object (*func)(Object, Object, struct Environment*), void addFunc(const char* name,
struct Environment *env) Object (* func)(Object, Object, struct Environment*),
struct Environment* env)
{ {
Object o = newObject(TYPE_FUNC); Object o = newObject(TYPE_FUNC);
o.func = func; o.func = func;
addToEnv(env, name, o); addToEnv(env, name, o);
} }
void deleteEnv(struct Environment *e) void deleteEnv(struct Environment* e)
{ {
if (e->strings) { if (e->strings) {
int i = 0; int i = 0;
while(e->strings[i]) { while (e->strings[i]) {
free(e->strings[i]); free(e->strings[i]);
cleanObject(&e->objects[i]); cleanObject(&e->objects[i]);
i++; i++;
@ -196,8 +194,9 @@ void deleteEnv(struct Environment *e)
} }
struct symFunc { struct symFunc {
const char *sym; const char* sym;
Object (*func)(Object, Object, struct Environment*);
Object (* func)(Object, Object, struct Environment*);
}; };
struct Environment defaultEnv() struct Environment defaultEnv()
@ -214,27 +213,43 @@ struct Environment defaultEnv()
}; };
struct symFunc symFuncs[] = { struct symFunc symFuncs[] = {
{"+", &add}, {"-", &sub}, {"*", &mul}, {"/", &dvi}, {"%", &mod}, {"+", &add},
{"=", &equ}, {">", &gth}, {"<", &lth}, {"-", &sub},
{"cat", &catObjects}, {"fil", &filter}, {"len", &len}, {"*", &mul},
{"ap", &append}, {"pre", &prepend}, {"/", &dvi},
{"at", &at}, {"rest", &rest}, {"%", &mod},
{"=", &equ},
{">", &gth},
{"<", &lth},
{"&", &and},
{"|", &or},
{"cat", &catObjects},
{"fil", &filter},
{"len", &len},
{"ap", &append},
{"pre", &prepend},
{"at", &at},
{"rest", &rest},
{"chat", &charAt}, {"chat", &charAt},
#ifndef LOW_MEM #ifndef LOW_MEM
{"rev", &reverse}, {"rev", &reverse},
#endif #endif
{"isnum", &isNum}, {"isstr", &isString}, {"iserr", &isErr}, {"isnum", &isNum},
{"isstr", &isString},
{"iserr", &isErr},
{"char", &charVal}, {"char", &charVal},
{"eval", &parseEvalO}, {"eval", &parseEvalO},
#ifdef STANDALONE #ifdef STANDALONE
{"prn", &print}, {"pch", &pChar}, {"penv", &printEnvO}, {"prn", &print},
{"pch", &pChar},
{"penv", &printEnvO},
{"sys", &systemCall}, {"sys", &systemCall},
{"loadfile", &loadFile}, {"loadfile", &loadFile},
{"inp", &takeInput}, {"inp", &takeInput},
#endif #endif
}; };
for(unsigned i = 0; i < sizeof(symFuncs)/sizeof(symFuncs[0]); i++) { for (unsigned i = 0; i < sizeof(symFuncs) / sizeof(symFuncs[0]); i++) {
addFunc(symFuncs[i].sym, symFuncs[i].func, &e); addFunc(symFuncs[i].sym, symFuncs[i].func, &e);
} }

View File

@ -5,20 +5,27 @@
struct Environment; struct Environment;
struct Environment { struct Environment {
char **strings; char** strings;
Object *objects; Object* objects;
struct Environment *outer; struct Environment* outer;
char size; int size;
}; };
Object fetchFromEnvironment(const char *name, struct Environment *env); Object fetchFromEnvironment(const char* name, struct Environment* env);
struct Environment envForLambda(const Object *params, const Object *arg_forms,
struct Environment *outer); struct Environment envForLambda(const Object* params, const Object* arg_forms,
void addToEnv(struct Environment *env, const char *name, const Object obj); struct Environment* outer);
void printEnv(struct Environment *env);
void addFunc(const char *name, Object (*func)(Object, Object, struct Environment*), void addToEnv(struct Environment* env, const char* name, const Object obj);
struct Environment *env);
void deleteEnv(struct Environment *e); void printEnv(struct Environment* env);
void addFunc(const char* name,
Object (* func)(Object, Object, struct Environment*),
struct Environment* env);
void deleteEnv(struct Environment* e);
struct Environment defaultEnv(); struct Environment defaultEnv();
#endif #endif

View File

@ -1,40 +1,30 @@
#include "object.h" #include "object.h"
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#ifdef DEBUG
#define printd(...) printf(__VA_ARGS__)
#else
#define printd(...) ;
#endif
#ifndef STANDALONE
#include <pebble.h>
#undef printf
#undef printd
#define printf(...) ;
#define printd(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
#endif
/** /**
* Returns the length of a given list Object * Returns the length of a given list Object
* @param listObj The list to get the length of * @param listObj The list to get the length of
* @return Length of the list if non-null and of the list type. Otherwise -1 * @return Length of the list if non-null and of the list type. Otherwise -1
*/ */
int listLength(const Object *listObj) int listLength(const Object* listObj)
{ {
if(!listObj || !isListy(*listObj)) if (!listObj || !isListy(*listObj)) {
return -1; return -1;
}
int len = 0; int len = 0;
FOR_POINTER_IN_LIST(listObj) { len++; } FOR_POINTER_IN_LIST(listObj) {
len++;
}
return len; return len;
} }
Object len(Object obj1, Object o_ignore, struct Environment *e_ignore) Object len(Object obj1, Object o_ignore, struct Environment* e_ignore)
{ {
Object o = numberObject(listLength(&obj1)); Object o = numberObject(listLength(&obj1));
if(o.number < 0) { if (o.number < 0) {
return errorObject(NOT_A_LIST); return errorObject(NOT_A_LIST);
} }
return o; return o;
@ -46,16 +36,19 @@ Object len(Object obj1, Object o_ignore, struct Environment *e_ignore)
* @param n The index to to fetch from the list * @param n The index to to fetch from the list
* @return A pointer to the Object, if it is found, or NULL on an error * @return A pointer to the Object, if it is found, or NULL on an error
*/ */
Object *itemAt(const Object *listObj, int n) Object* itemAt(const Object* listObj, int n)
{ {
if(!listObj || !isListy(*listObj)) if (!listObj || !isListy(*listObj)) {
return NULL; return NULL;
}
FOR_POINTER_IN_LIST(listObj) { FOR_POINTER_IN_LIST(listObj) {
if(POINTER == NULL) if (POINTER == NULL) {
return NULL; return NULL;
if(n-- == 0) }
if (n-- == 0) {
return POINTER; return POINTER;
}
} }
return NULL; return NULL;
} }
@ -65,12 +58,13 @@ Object *itemAt(const Object *listObj, int n)
* @param listObj The list to find the tail of * @param listObj The list to find the tail of
* @return A pointer to the last Object if it is found, or NULL on an error * @return A pointer to the last Object if it is found, or NULL on an error
*/ */
Object *tail(const Object *listObj) Object* tail(const Object* listObj)
{ {
if(!listObj || !isListy(*listObj)) if (!listObj || !isListy(*listObj)) {
return NULL; return NULL;
}
Object *tail = NULL; Object* tail = NULL;
FOR_POINTER_IN_LIST(listObj) { FOR_POINTER_IN_LIST(listObj) {
tail = POINTER; tail = POINTER;
} }
@ -86,12 +80,13 @@ Object *tail(const Object *listObj)
* @param obj A pointer to the object to check * @param obj A pointer to the object to check
* @return True only if the non-null Object is empty/non-zero * @return True only if the non-null Object is empty/non-zero
*/ */
inline int isEmpty(const Object *obj) inline int isEmpty(const Object* obj)
{ {
if(obj == NULL) if (obj == NULL) {
return 0; return 0;
}
switch(obj->type) { switch (obj->type) {
case TYPE_NUMBER: case TYPE_NUMBER:
case TYPE_BOOL: case TYPE_BOOL:
return obj->number == 0; return obj->number == 0;
@ -120,7 +115,7 @@ inline int isEmpty(const Object *obj)
* @param spot A pointer to the Object pointer that needs allocating * @param spot A pointer to the Object pointer that needs allocating
* @param src The Object to copy from * @param src The Object to copy from
*/ */
void allocObject(Object **spot, const Object src) void allocObject(Object** spot, const Object src)
{ {
*spot = malloc(sizeof(struct Object)); *spot = malloc(sizeof(struct Object));
**spot = src; **spot = src;
@ -138,20 +133,21 @@ void allocObject(Object **spot, const Object src)
* @warning UNTESTED * @warning UNTESTED
*/ */
void insertIntoList(Object *dest, int ind, const Object src) void insertIntoList(Object* dest, int ind, const Object src)
{ {
if(!dest || !isListy(*dest)) if (!dest || !isListy(*dest)) {
return; return;
}
// Merely append, when possible // Merely append, when possible
if(ind >= listLength(dest)) { if (ind >= listLength(dest)) {
nf_addToList(dest, src); nf_addToList(dest, src);
return; return;
} }
// The Objects to preceed and follow the new one // The Objects to preceed and follow the new one
Object *beforeNew = itemAt(dest, ind - 1); Object* beforeNew = itemAt(dest, ind - 1);
Object *afterNew = beforeNew->forward; Object* afterNew = beforeNew->forward;
// Replace the `before` Object's pointer // Replace the `before` Object's pointer
allocObject(&beforeNew->forward, src); allocObject(&beforeNew->forward, src);
@ -167,12 +163,13 @@ void insertIntoList(Object *dest, int ind, const Object src)
* @param i The index of the element to replace * @param i The index of the element to replace
* @param src The Object to copy into the list * @param src The Object to copy into the list
*/ */
void replaceListing(Object *list, int i, const Object src) void replaceListing(Object* list, int i, const Object src)
{ {
if(!list || isListy(*list)) if (!list || isListy(*list)) {
return; return;
Object *replace = itemAt(list, i); }
Object *oldForward = replace->forward; Object* replace = itemAt(list, i);
Object* oldForward = replace->forward;
cleanObject(replace); cleanObject(replace);
*replace = src; *replace = src;
replace->forward = oldForward; replace->forward = oldForward;
@ -184,12 +181,13 @@ void replaceListing(Object *list, int i, const Object src)
* @param dest The list to append to * @param dest The list to append to
* @param src The Object to copy into the list * @param src The Object to copy into the list
*/ */
void nf_addToList(Object *dest, const Object src) void nf_addToList(Object* dest, const Object src)
{ {
if(!dest || !isListy(*dest)) if (!dest || !isListy(*dest)) {
return; return;
}
if(isEmpty(dest)) { if (isEmpty(dest)) {
allocObject(&dest->list, src); allocObject(&dest->list, src);
return; return;
} }
@ -198,32 +196,30 @@ void nf_addToList(Object *dest, const Object src)
} }
#ifndef SIMPLE_ERRORS #ifndef SIMPLE_ERRORS
static const char *errorText[] = { static const char* errorText[] = {"MISMATCHED_PARENS",
"MISMATCHED_PARENS", "BAD_LIST_OF_SYMBOL_STRINGS",
"BAD_LIST_OF_SYMBOL_STRINGS", "TYPE_LIST_NOT_CAUGHT",
"TYPE_LIST_NOT_CAUGHT", "NULL_ENV",
"NULL_ENV", "EMPTY_ENV",
"EMPTY_ENV", "BUILT_IN_NOT_FOUND",
"BUILT_IN_NOT_FOUND", "NULL_PARSE",
"NULL_PARSE", "NULL_LAMBDA_LIST",
"NULL_LAMBDA_LIST", "NULL_MAP_ARGS",
"NULL_MAP_ARGS", "LAMBDA_ARGS_NOT_LIST",
"LAMBDA_ARGS_NOT_LIST", "DID_NOT_FIND_SYMBOL",
"DID_NOT_FIND_SYMBOL", "BAD_TYPE",
"BAD_TYPE", "UNEXPECTED_FORM",
"UNEXPECTED_FORM", "LISTS_NOT_SAME_SIZE",
"LISTS_NOT_SAME_SIZE", "BAD_NUMBER",
"BAD_NUMBER", "UNSUPPORTED_NUMBER_TYPE",
"UNSUPPORTED_NUMBER_TYPE", "NOT_A_SYMBOL",
"NOT_A_SYMBOL", "ONLY_ONE_ARGUMENT",
"ONLY_ONE_ARGUMENT", "NOT_A_LIST",
"NOT_A_LIST", "SCRIPT_NOT_FOUND",
"SCRIPT_NOT_FOUND", "NO_CLONE_SPECIFIED",
"NO_CLONE_SPECIFIED", "CAN_ONLY_EVAL_STRINGS",
"CAN_ONLY_EVAL_STRINGS", "UNEXPECTED_EOF",
"UNEXPECTED_EOF", "INDEX_PAST_END"};
"INDEX_PAST_END"
};
#endif #endif
/** /**
@ -233,10 +229,11 @@ static const char *errorText[] = {
* @param dest The string to copy the list text into * @param dest The string to copy the list text into
* @param obj The list Object to make a string from * @param obj The list Object to make a string from
*/ */
void stringList(char *dest, const Object *obj) void stringList(char* dest, const Object* obj)
{ {
if(!dest || !isListy(*obj)) if (!dest || !isListy(*obj)) {
return; return;
}
dest[0] = '('; dest[0] = '(';
dest[1] = '\0'; dest[1] = '\0';
@ -266,11 +263,13 @@ void stringList(char *dest, const Object *obj)
* @param dest The string to copy the list text into * @param dest The string to copy the list text into
* @param obj The list Object to make a string from * @param obj The list Object to make a string from
*/ */
char* stringNObj(char *dest, const Object *obj, const size_t len) { char* stringNObj(char* dest, const Object* obj, const size_t len)
if(!dest || !obj) {
if (!dest || !obj) {
return NULL; return NULL;
}
switch(obj->type) { switch (obj->type) {
case TYPE_NUMBER: case TYPE_NUMBER:
snprintf(dest, len, "%d", obj->number); snprintf(dest, len, "%d", obj->number);
break; break;
@ -289,16 +288,16 @@ char* stringNObj(char *dest, const Object *obj, const size_t len) {
break; break;
case TYPE_ERROR: { case TYPE_ERROR: {
int code = getErrorCode(*obj); int code = getErrorCode(*obj);
#ifdef SIMPLE_ERRORS #ifdef SIMPLE_ERRORS
snprintf(dest, len, "E[%d]", (int)code); snprintf(dest, len, "E[%d]", (int)code);
#else #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],
errorText[code], obj->error->context); obj->error->context);
} else { } else {
snprintf(dest, len, "%s", errorText[code]); snprintf(dest, len, "%s", errorText[code]);
} }
#endif #endif
break; break;
} }
case TYPE_FUNC: case TYPE_FUNC:
@ -310,13 +309,15 @@ char* stringNObj(char *dest, const Object *obj, const size_t len) {
break; break;
} }
if(!isValidType(*obj)) if (!isValidType(*obj)) {
snprintf(dest, len, "BAD_TYPE(%d) X%d", obj->type, obj->number); snprintf(dest, len, "BAD_TYPE(%d) X%d", obj->type, obj->number);
}
return dest; return dest;
} }
char* stringObj(char *dest, const Object *obj) { char* stringObj(char* dest, const Object* obj)
{
return stringNObj(dest, obj, RESULT_LENGTH); return stringNObj(dest, obj, RESULT_LENGTH);
} }
@ -324,7 +325,7 @@ char* stringObj(char *dest, const Object *obj) {
* Prints a given Object only if the DEBUG flag is set * Prints a given Object only if the DEBUG flag is set
* @param obj The Object to debug * @param obj The Object to debug
*/ */
void debugObj(const Object *obj) void debugObj(const Object* obj)
{ {
#ifdef DEBUG #ifdef DEBUG
printObj(obj); printObj(obj);
@ -333,9 +334,10 @@ void debugObj(const Object *obj)
} }
#if defined(DEBUG) || defined(STANDALONE) #if defined(DEBUG) || defined(STANDALONE)
void printType(const Object *obj)
void printType(const Object* obj)
{ {
switch(obj->type) { switch (obj->type) {
case TYPE_NUMBER: case TYPE_NUMBER:
printf("TYPE_NUMBER"); printf("TYPE_NUMBER");
return; return;
@ -367,16 +369,18 @@ void printType(const Object *obj)
return; return;
} }
if(!isValidType(*obj)) if (!isValidType(*obj)) {
printf("UNKNOWN TYPE (%d)", obj->type); printf("UNKNOWN TYPE (%d)", obj->type);
}
} }
void _printList(const Object *list, int newline); void nestedPrintList(const Object* list, int newline);
void _printObj(const Object *obj, int newline)
void _printObj(const Object* obj, int newline)
{ {
#ifdef DEBUG #ifdef DEBUG
printType(obj); printType(obj);
#endif #endif
if (obj->type == TYPE_LAMBDA) { if (obj->type == TYPE_LAMBDA) {
printObj(&obj->lambda->params); printObj(&obj->lambda->params);
@ -387,10 +391,11 @@ void _printObj(const Object *obj, int newline)
char temp[100] = ""; char temp[100] = "";
stringObj(temp, obj); stringObj(temp, obj);
if(newline) if (newline) {
printf("%s\n", temp); printf("%s\n", temp);
else } else {
printf("%s", temp); printf("%s", temp);
}
} }
/** /**
@ -399,32 +404,36 @@ void _printObj(const Object *obj, int newline)
* If the DEBUG flag is set, the Object's type will be printed first * If the DEBUG flag is set, the Object's type will be printed first
* @param obj The Object to print * @param obj The Object to print
*/ */
inline void printObj(const Object *obj) inline void printObj(const Object* obj)
{ {
_printObj(obj, 1); _printObj(obj, 1);
} }
void _printList(const Object *list, int newline) void nestedPrintList(const Object* list, int newline)
{ {
printf("("); printf("(");
FOR_POINTER_IN_LIST(list) { if (list && isListy(*list)) {
printf(" "); FOR_POINTER_IN_LIST(list) {
_printObj(POINTER, 0); printf(" ");
_printObj(POINTER, 0);
}
} }
printf(" )"); printf(" )");
if(newline) if (newline) {
printf("\n"); printf("\n");
}
} }
/** /**
* Prints each Object in a given list, surrounded by parentheses * Prints each Object in a given list, surrounded by parentheses
* @param list The list Object to print * @param list The list Object to print
*/ */
void printList(const Object *list) void printList(const Object* list)
{ {
_printList(list, 1); nestedPrintList(list, 1);
} }
#endif #endif
/** /**
@ -437,12 +446,13 @@ void printList(const Object *list)
* *
* @param target The object to clean * @param target The object to clean
*/ */
void cleanObject(Object *target) void cleanObject(Object* target)
{ {
if(target == NULL) if (target == NULL) {
return; return;
}
switch(target->type) { switch (target->type) {
case TYPE_STRING: case TYPE_STRING:
case TYPE_SYMBOL: case TYPE_SYMBOL:
free(target->string); free(target->string);
@ -465,7 +475,7 @@ void cleanObject(Object *target)
#endif #endif
break; break;
case TYPE_OTHER: case TYPE_OTHER:
if(target->other->cleanup) { if (target->other->cleanup) {
target->other->cleanup(target); target->other->cleanup(target);
} }
break; break;
@ -483,11 +493,13 @@ void cleanObject(Object *target)
* @param target The object to print and clean * @param target The object to print and clean
*/ */
#ifdef STANDALONE #ifdef STANDALONE
void printAndClean(Object *target)
void printAndClean(Object* target)
{ {
printObj(target); printObj(target);
cleanObject(target); cleanObject(target);
} }
#endif #endif
/** /**
@ -496,19 +508,20 @@ void printAndClean(Object *target)
* *
* @param dest The list object to clean up * @param dest The list object to clean up
*/ */
void deleteList(Object *dest) void deleteList(Object* dest)
{ {
if(!dest) if (!dest) {
return; return;
}
if(!isListy(*dest)) { if (!isListy(*dest)) {
printf("Tried to delete something other than a list\n"); printf("Tried to delete something other than a list\n");
return; return;
} }
Object *march = dest->list; Object* march = dest->list;
while(march != NULL) { while (march != NULL) {
Object *prevMarch = march; Object* prevMarch = march;
march = march->forward; march = march->forward;
cleanObject(prevMarch); cleanObject(prevMarch);
free(prevMarch); free(prevMarch);
@ -516,22 +529,23 @@ void deleteList(Object *dest)
dest->list = NULL; dest->list = NULL;
} }
void _copyList(Object *dest, const Object *src, int delete) void _copyList(Object* dest, const Object* src, int delete)
{ {
if(!dest || !src) { if (!dest || !src) {
printd("NULL\n"); printd("NULL\n");
return; return;
} }
if(!isListy(*dest) || !isListy(*src)) { if (!isListy(*dest) || !isListy(*src)) {
printd("NOT A LIST\n"); printd("NOT A LIST\n");
return; return;
} }
if(delete) if (delete) {
deleteList(dest); deleteList(dest);
}
FOR_POINTER_IN_LIST(src) { FOR_POINTER_IN_LIST(src) {
if(isListy(*POINTER)) { if (isListy(*POINTER)) {
nf_addToList(dest, *POINTER); nf_addToList(dest, *POINTER);
tail(dest)->list = NULL; tail(dest)->list = NULL;
_copyList(tail(dest), POINTER, 0); _copyList(tail(dest), POINTER, 0);
@ -552,7 +566,7 @@ void _copyList(Object *dest, const Object *src, int delete)
* @param dest The list to copy to * @param dest The list to copy to
* @param src The list to copy from * @param src The list to copy from
*/ */
void copyList(Object *dest, const Object *src) void copyList(Object* dest, const Object* src)
{ {
_copyList(dest, src, 1); _copyList(dest, src, 1);
} }
@ -565,7 +579,7 @@ void copyList(Object *dest, const Object *src)
* @param dest The list to copy to * @param dest The list to copy to
* @param src The list to copy from * @param src The list to copy from
*/ */
void appendList(Object *dest, const Object *src) void appendList(Object* dest, const Object* src)
{ {
_copyList(dest, src, 0); _copyList(dest, src, 0);
} }
@ -611,7 +625,7 @@ inline int isStringy(const Object test)
inline int isValidType(const Object test) inline int isValidType(const Object test)
{ {
switch(test.type) { switch (test.type) {
case TYPE_NUMBER: case TYPE_NUMBER:
case TYPE_BOOL: case TYPE_BOOL:
case TYPE_LIST: case TYPE_LIST:
@ -654,15 +668,14 @@ inline Object cloneList(const Object src)
return list; return list;
} }
inline Object cloneOther(const Object src) { inline Object cloneOther(const Object src)
return src.other->clone? {
src.other->clone(src.other) : return src.other->clone ? src.other->clone(src.other) : src;
src;
} }
inline Object cloneObject(const Object src) inline Object cloneObject(const Object src)
{ {
switch(src.type) { switch (src.type) {
case TYPE_SLIST: case TYPE_SLIST:
case TYPE_LIST: case TYPE_LIST:
return cloneList(src); return cloneList(src);
@ -677,7 +690,7 @@ inline Object cloneObject(const Object src)
case TYPE_NUMBER: case TYPE_NUMBER:
case TYPE_FUNC: case TYPE_FUNC:
case TYPE_OTHER: case TYPE_OTHER:
; // Fall through to plain return return src;
} }
return src; return src;
@ -698,19 +711,19 @@ inline Object boolObject(int b)
} }
// Skips first and last chars! Assumed to be '"' // Skips first and last chars! Assumed to be '"'
inline Object objFromSlice(const char *string, int len) inline Object objFromSlice(const char* string, int len)
{ {
return stringFromSlice(&string[1], len - 1); return stringFromSlice(&string[1], len - 1);
} }
inline Object stringFromSlice(const char *string, int len) inline Object stringFromSlice(const char* string, int len)
{ {
Object o = symFromSlice(string, len); Object o = symFromSlice(string, len);
o.type = TYPE_STRING; o.type = TYPE_STRING;
return o; return o;
} }
inline Object symFromSlice(const char *string, int len) inline Object symFromSlice(const char* string, int len)
{ {
Object o = newObject(TYPE_SYMBOL); Object o = newObject(TYPE_SYMBOL);
o.string = calloc(sizeof(char), len + 1); o.string = calloc(sizeof(char), len + 1);
@ -718,13 +731,15 @@ inline Object symFromSlice(const char *string, int len)
return o; return o;
} }
inline Object constructLambda(const Object *params, const Object *body) inline Object constructLambda(const Object* params, const Object* body)
{ {
if(!params || !body) if (!params || !body) {
return errorObject(NULL_LAMBDA_LIST); return errorObject(NULL_LAMBDA_LIST);
}
if(params->type != TYPE_LIST || body->type != TYPE_LIST) if (params->type != TYPE_LIST || body->type != TYPE_LIST) {
return errorObject(LAMBDA_ARGS_NOT_LIST); return errorObject(LAMBDA_ARGS_NOT_LIST);
}
Object o = newObject(TYPE_LAMBDA); Object o = newObject(TYPE_LAMBDA);
o.lambda = malloc(sizeof(struct Lambda)); o.lambda = malloc(sizeof(struct Lambda));
@ -740,17 +755,17 @@ inline int isError(const Object obj, const enum errorCode err)
return obj.type == TYPE_ERROR && getErrorCode(obj) == 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)
{ {
return (obj1->type == type) && (obj2->type == type); return (obj1->type == type) && (obj2->type == type);
} }
inline int eitherIs(const enum Type type, const Object *o1, const Object *o2) inline int eitherIs(const enum Type type, const Object* o1, const Object* o2)
{ {
return (o1->type == type) || (o2->type == type); return (o1->type == type) || (o2->type == type);
} }
inline int areSameType(const Object *obj1, const Object *obj2) inline int areSameType(const Object* obj1, const Object* obj2)
{ {
return obj1->type == obj2->type; return obj1->type == obj2->type;
} }
@ -786,12 +801,13 @@ inline enum errorCode getErrorCode(const Object obj)
} }
#ifndef SIMPLE_ERRORS #ifndef SIMPLE_ERRORS
inline void errorAddContext(Object *o, const char* context)
inline void errorAddContext(Object* o, const char* context)
{ {
//printf("o: %p\n", o); // printf("o: %p\n", o);
//printf("o->error: %s\n", o->error); // printf("o->error: %s\n", o->error);
o->error->context = calloc(sizeof(char), RESULT_LENGTH); o->error->context = calloc(sizeof(char), RESULT_LENGTH);
//printf("context: %p\n", context); // printf("context: %p\n", context);
strncpy(o->error->context, context, RESULT_LENGTH); strncpy(o->error->context, context, RESULT_LENGTH);
} }
@ -803,6 +819,7 @@ inline Object errorWithContext(enum errorCode code, const char* context)
} }
return o; return o;
} }
#endif #endif
struct Error noError() struct Error noError()
@ -814,7 +831,8 @@ struct Error noError()
inline Object toBool(const Object test) inline Object toBool(const Object test)
{ {
if(test.number == 0) if (test.number == 0) {
return boolObject(0); return boolObject(0);
}
return boolObject(1); return boolObject(1);
} }

View File

@ -3,30 +3,41 @@
#include <stdlib.h> #include <stdlib.h>
#ifndef STANDALONE
#include <pebble.h>
#undef printf
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
#else
#ifdef DEBUG
#define printd(...) printf(__VA_ARGS__)
#else
#define printd(...) (0)
#endif
#endif
#define MAX_TOK_CNT 1024 #define MAX_TOK_CNT 1024
#define MAX_ENV_ELM 100 #define MAX_ENV_ELM 100
#define RESULT_LENGTH 128 #define RESULT_LENGTH 128
#define FOR_POINTER_IN_LIST(_list) \ #define FOR_POINTER_IN_LIST(_list) \
if(_list && isListy(*_list)) \ for(Object *_element = (_list)->list; \
for(Object *_element = _list->list; \
_element != NULL;\ _element != NULL;\
_element = _element->forward) _element = _element->forward)
#define POINTER _element #define POINTER _element
#define FOR_POINTERS_IN_LISTS(_list, _list2) \ #define FOR_POINTERS_IN_LISTS(_list, _list2) \
for(Object *_element = _list->list, *_element2 = _list2->list; \ for(Object *_element = (_list)->list, *_element2 = (_list2)->list; \
_element != NULL && _element2 != NULL; \ _element != NULL && _element2 != NULL; \
_element = _element->forward, _element2 = _element2->forward) _element = _element->forward, _element2 = _element2->forward)
#define P1 POINTER #define P1 POINTER
#define P2 _element2 #define P2 _element2
#ifdef PBL_PLATFORM_APLITE #ifdef PBL_PLATFORM_APLITE
#define LOW_MEM #define LOW_MEM
#endif #endif
#ifdef LOW_MEM #ifdef LOW_MEM
#define SIMPLE_ERRORS #define SIMPLE_ERRORS
#endif #endif
enum errorCode { enum errorCode {
@ -76,24 +87,27 @@ struct Slice;
struct Other; struct Other;
struct Error { struct Error {
enum errorCode code; enum errorCode code;
char* context; char *context;
}; };
struct Object { struct Object {
Type type; Type type;
Object *forward; Object *forward;
union { union {
int number; int number;
Object *list; Object *list;
char *string; char *string;
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 #ifdef SIMPLE_ERRORS
enum errorCode error; enum errorCode error;
#else #else
struct Error *error; struct Error *error;
#endif #endif
}; };
}; };
@ -103,67 +117,110 @@ struct Lambda {
}; };
struct Other { struct Other {
void (*cleanup)(Object*); void (*cleanup)(Object *);
Object (*clone)(struct Other*);
Object (*clone)(struct Other *);
void *data; void *data;
}; };
char* stringNObj(char *dest, const Object *obj, size_t len); char *stringNObj(char *dest, const Object *obj, size_t len);
char* stringObj(char *dest, const Object *obj);
char *stringObj(char *dest, const Object *obj);
void printList(const Object *list); void printList(const Object *list);
void printType(const Object *obj); void printType(const Object *obj);
void printObj(const Object *obj); void printObj(const Object *obj);
void _printObj(const Object *obj, int newline); void _printObj(const Object *obj, int newline);
void debugObj(const Object *obj); void debugObj(const Object *obj);
void printErr(const Object *obj); void printErr(const Object *obj);
int isEmpty(const Object *obj); int isEmpty(const Object *obj);
Object *tail(const Object *listObj); Object *tail(const Object *listObj);
void insertIntoList(Object *dest, int ind, const Object src); void insertIntoList(Object *dest, int ind, const Object src);
void replaceListing(Object *list, int i, const Object src); void replaceListing(Object *list, int i, const Object src);
void nf_addToList(Object *dest, Object src); void nf_addToList(Object *dest, Object src);
void deleteList(Object *dest); void deleteList(Object *dest);
int listLength(const Object *listObj); int listLength(const Object *listObj);
Object *itemAt(const Object *listObj, int n); Object *itemAt(const Object *listObj, int n);
void copyList(Object *dest, const Object *src); void copyList(Object *dest, const Object *src);
void cleanObject(Object *target); void cleanObject(Object *target);
void printAndClean(Object *target); void printAndClean(Object *target);
void allocObject(Object **spot, const Object src); void allocObject(Object **spot, const Object src);
void appendList(Object *dest, const Object *src); void appendList(Object *dest, const Object *src);
int isListy(const Object test); int isListy(const Object test);
int isStringy(const Object test); int isStringy(const Object test);
int isValidType(const Object test); int isValidType(const Object test);
int isError(const Object obj, const enum errorCode err); int isError(const Object obj, const enum errorCode err);
int bothAre(const enum Type type, const Object *obj1, const Object *obj2); int bothAre(const enum Type type, const Object *obj1, const Object *obj2);
int eitherIs(const enum Type type, const Object *obj1, const Object *obj2); int eitherIs(const enum Type type, const Object *obj1, const Object *obj2);
int areSameType(const Object *obj1, const Object *obj2); int areSameType(const Object *obj1, const Object *obj2);
Object cloneList(const Object src); Object cloneList(const Object src);
Object cloneString(Object obj); Object cloneString(Object obj);
Object cloneLambda(const Object old); Object cloneLambda(const Object old);
Object cloneObject(const Object src); Object cloneObject(const Object src);
Object newObject(Type type); Object newObject(Type type);
Object listObject(); Object listObject();
Object startList(const Object start); Object startList(const Object start);
Object objFromSlice(const char *string, int len); Object objFromSlice(const char *string, int len);
Object stringFromSlice(const char *string, int len); Object stringFromSlice(const char *string, int len);
Object symFromSlice(const char *string, int len); Object symFromSlice(const char *string, int len);
Object boolObject(int b); 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); enum errorCode getErrorCode(const Object obj);
#ifdef SIMPLE_ERRORS #ifdef SIMPLE_ERRORS
#define errorWithContext(code, context) errorObject(code) #define errorWithContext(code, context) errorObject(code)
#define errorAddContext(x, y) ; #define errorAddContext(x, y) ;
#else #else
Object errorWithContext(enum errorCode err, const char* context);
void errorAddContext(Object *o, const char* context); Object errorWithContext(enum errorCode err, const char *context);
void errorAddContext(Object *o, const char *context);
#endif #endif
struct Error noError(); struct Error noError();
Object constructLambda(const Object *params, const Object *body); Object constructLambda(const Object *params, const Object *body);

View File

@ -1,15 +1,13 @@
#include "pebbleobject.h" #include "pebbleobject.h"
#include "calc.h" #include "calc.h"
#include "object.h" #include "object.h"
Object pebbleOther( Object pebbleOther(enum PebbleType type, void* data, void (* cleanup)(Object*),
enum PebbleType type, Object (* clone)(struct Other*))
void* data,
void (*cleanup)(Object*),
Object (*clone)(struct Other*))
{ {
struct Object o = otherObject(); struct Object o = otherObject();
struct PebbleObject *po = malloc(sizeof(struct PebbleObject)); struct PebbleObject* po = malloc(sizeof(struct PebbleObject));
o.other->data = po; o.other->data = po;
o.other->cleanup = cleanup; o.other->cleanup = cleanup;
o.other->clone = clone; o.other->clone = clone;
@ -20,57 +18,63 @@ Object pebbleOther(
enum PebbleType getPebbleType(const Object o1) enum PebbleType getPebbleType(const Object o1)
{ {
if(o1.type == TYPE_OTHER) { if (o1.type == TYPE_OTHER) {
struct PebbleObject *po = o1.other->data; struct PebbleObject* po = o1.other->data;
enum PebbleType t = po->type; enum PebbleType t = po->type;
return t; return t;
} }
return P_ERROR; return P_ERROR;
} }
struct PebbleObject* accessPebbleObject(Object obj) { struct PebbleObject* accessPebbleObject(Object obj)
if(getPebbleType(obj) != P_ERROR) { {
if (getPebbleType(obj) != P_ERROR) {
return obj.other->data; return obj.other->data;
} }
return NULL; return NULL;
} }
void custom_window_load(Window *window) { void custom_window_load(Window* window)
{
} }
void custom_window_unload(Window *window) { void custom_window_unload(Window* window)
{
window_destroy(window); window_destroy(window);
} }
Object createWindow(Object o1, Object o2, struct Environment *env) { Object createWindow(Object o1, Object o2, struct Environment* env)
Window *window = window_create(); {
WindowHandlers wh = { Window* window = window_create();
.load = custom_window_load, WindowHandlers wh = {.load = custom_window_load,
.unload = custom_window_unload }; .unload = custom_window_unload};
window_set_window_handlers(window, wh); window_set_window_handlers(window, wh);
return pebbleOther(WINDOW, window, NULL, NULL); return pebbleOther(WINDOW, window, NULL, NULL);
} }
Object deleteWindow(Object window, Object o2, struct Environment *env) { Object deleteWindow(Object window, Object o2, struct Environment* env)
{
/* Maintain a list of layers to delete? */ /* Maintain a list of layers to delete? */
if(getPebbleType(window) == WINDOW) { if (getPebbleType(window) == WINDOW) {
window_stack_remove(accessPebbleObject(window)->window, true); window_stack_remove(accessPebbleObject(window)->window, true);
return boolObject(1); return boolObject(1);
} }
return boolObject(0); return boolObject(0);
} }
Object pushWindow(Object window, Object o2, struct Environment *env) { Object pushWindow(Object window, Object o2, struct Environment* env)
if(getPebbleType(window) == WINDOW) { {
if (getPebbleType(window) == WINDOW) {
window_stack_push(accessPebbleObject(window)->window, true); window_stack_push(accessPebbleObject(window)->window, true);
return boolObject(1); return boolObject(1);
} }
return boolObject(0); return boolObject(0);
} }
Object updateTextLayer(Object textLayer, Object text, struct Environment *env) { Object updateTextLayer(Object textLayer, Object text, struct Environment* env)
if(getPebbleType(textLayer) == TEXT_LAYER) { {
struct PebbleObject *po = accessPebbleObject(textLayer); if (getPebbleType(textLayer) == TEXT_LAYER) {
struct PebbleObject* po = accessPebbleObject(textLayer);
stringObj(po->textLayer->text, &text); stringObj(po->textLayer->text, &text);
text_layer_set_text(po->textLayer->layer, po->textLayer->text); text_layer_set_text(po->textLayer->layer, po->textLayer->text);
return boolObject(1); return boolObject(1);
@ -78,49 +82,55 @@ Object updateTextLayer(Object textLayer, Object text, struct Environment *env) {
return boolObject(0); return boolObject(0);
} }
Object addTextLayer(Object window, Object text, struct Environment *env) { Object addTextLayer(Object window, Object text, struct Environment* env)
if(getPebbleType(window) != WINDOW) { {
if (getPebbleType(window) != WINDOW) {
return errorObject(0); return errorObject(0);
} }
Layer *window_layer = window_get_root_layer(accessPebbleObject(window)->window); Layer* window_layer =
window_get_root_layer(accessPebbleObject(window)->window);
GRect bounds = layer_get_bounds(window_layer); GRect bounds = layer_get_bounds(window_layer);
struct PLTextLayer *textLayer = malloc(sizeof(struct PLTextLayer)); struct PLTextLayer* textLayer = malloc(sizeof(struct PLTextLayer));
textLayer->text = calloc(sizeof(char), 100); textLayer->text = calloc(sizeof(char), 100);
textLayer->layer = text_layer_create(bounds); textLayer->layer = text_layer_create(bounds);
stringObj(textLayer->text, &text); stringObj(textLayer->text, &text);
text_layer_set_text(textLayer->layer, textLayer->text); text_layer_set_text(textLayer->layer, textLayer->text);
text_layer_set_font(textLayer->layer, text_layer_set_font(textLayer->layer,
fonts_get_system_font(FONT_KEY_BITHAM_42_BOLD)); fonts_get_system_font(FONT_KEY_BITHAM_42_BOLD));
layer_add_child(window_layer, text_layer_get_layer(textLayer->layer)); layer_add_child(window_layer, text_layer_get_layer(textLayer->layer));
return pebbleOther(TEXT_LAYER, textLayer, NULL, NULL); return pebbleOther(TEXT_LAYER, textLayer, NULL, NULL);
} }
Object subscription; Object subscription;
struct Environment *subscriptionEnv; struct Environment* subscriptionEnv;
static void subscriptionHandler(struct tm *tick_time, TimeUnits changed) { static void subscriptionHandler(struct tm* tick_time, TimeUnits changed)
{
eval(&subscription, subscriptionEnv); eval(&subscription, subscriptionEnv);
} }
Object subscribe(Object function, Object time, struct Environment *env) { Object subscribe(Object function, Object time, struct Environment* env)
if(function.type == TYPE_LAMBDA) { {
if (function.type == TYPE_LAMBDA) {
subscription = cloneObject(function); subscription = cloneObject(function);
subscriptionEnv = env; subscriptionEnv = env;
int unit = time.type != TYPE_NUMBER ? MINUTE_UNIT : int unit = time.type != TYPE_NUMBER ? MINUTE_UNIT
time.number == 1 ? SECOND_UNIT : : time.number == 1 ? SECOND_UNIT
time.number == 2 ? MINUTE_UNIT : : time.number == 2 ? MINUTE_UNIT
time.number == 3 ? HOUR_UNIT : : time.number == 3 ? HOUR_UNIT
time.number == 4 ? DAY_UNIT : : time.number == 4
time.number == 5 ? MONTH_UNIT : ? DAY_UNIT
time.number == 6 ? YEAR_UNIT : : time.number ==
MINUTE_UNIT; 5 ? MONTH_UNIT
:
time.number ==
6 ? YEAR_UNIT
: MINUTE_UNIT;
tick_timer_service_subscribe(unit, subscriptionHandler); tick_timer_service_subscribe(unit, subscriptionHandler);
return boolObject(1); return boolObject(1);
} }
return boolObject(0); return boolObject(0);
} }

View File

@ -1,30 +1,34 @@
#include <pebble.h> #include <pebble.h>
#include "pebblisp.h" #include "pebblisp.h"
enum PebbleType { enum PebbleType {
WINDOW, WINDOW, TEXT_LAYER, P_ERROR
TEXT_LAYER,
P_ERROR
}; };
struct PLTextLayer { struct PLTextLayer {
TextLayer *layer; TextLayer* layer;
char *text; char* text;
}; };
typedef struct PebbleObject PebbleObject; typedef struct PebbleObject PebbleObject;
struct PebbleObject { struct PebbleObject {
enum PebbleType type; enum PebbleType type;
union { union {
Window *window; Window* window;
struct PLTextLayer *textLayer; struct PLTextLayer* textLayer;
void *ptr; void* ptr;
}; };
}; };
Object createWindow(Object o1, Object o2, struct Environment *env); Object createWindow(Object o1, Object o2, struct Environment* env);
Object deleteWindow(Object window, Object o2, struct Environment *env);
Object pushWindow(Object o1, Object o2, struct Environment *env); Object deleteWindow(Object window, Object o2, struct Environment* env);
Object addTextLayer(Object window, Object text, struct Environment *env);
Object updateTextLayer(Object textLayer, Object text, struct Environment *env); Object pushWindow(Object o1, Object o2, struct Environment* env);
Object subscribe(Object function, Object time, struct Environment *env);
Object addTextLayer(Object window, Object text, struct Environment* env);
Object updateTextLayer(Object textLayer, Object text, struct Environment* env);
Object subscribe(Object function, Object time, struct Environment* env);

View File

@ -1,14 +1,12 @@
#pragma ide diagnostic ignored "misc-no-recursion"
#include "pebblisp.h" #include "pebblisp.h"
#include "tokens.h"
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#ifndef STANDALONE #include "tokens.h"
#undef printf
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
#include <pebble.h>
#endif
/** /**
* Inserts a variable into the environment with a given name and value. * Inserts a variable into the environment with a given name and value.
@ -21,16 +19,14 @@
* @param env The environment to add the new definition to * @param env The environment to add the new definition to
* @return The symbol(s) defined * @return The symbol(s) defined
*/ */
Object evalDefArgs( Object evalDefArgs(const Object* symbol, const Object* value,
const Object *symbol, struct Environment* env)
const Object *value, {
struct Environment *env const char* name = symbol->string;
) {
const char *name = symbol->string;
// Handles multi-definitions // Handles multi-definitions
if(bothAre(TYPE_LIST, symbol, value) if (bothAre(TYPE_LIST, symbol, value) &&
&& listLength(symbol) == listLength(value)) { listLength(symbol) == listLength(value)) {
FOR_POINTERS_IN_LISTS(symbol, value) { FOR_POINTERS_IN_LISTS(symbol, value) {
Object finalValue = eval(P2, env); Object finalValue = eval(P2, env);
addToEnv(env, P1->string, finalValue); addToEnv(env, P1->string, finalValue);
@ -47,80 +43,80 @@ Object evalDefArgs(
return cloneObject(*symbol); return cloneObject(*symbol);
} }
Object evalIfArgs(const Object *argForms, struct Environment *env) Object evalIfArgs(const Object* argForms, struct Environment* env)
{ {
Object condition = eval(argForms, env); Object condition = eval(argForms, env);
Object result = condition.number ? Object result = condition.number ? eval(argForms->forward, env)
eval(argForms->forward, env) : : eval(argForms->forward->forward, env);
eval(argForms->forward->forward, env);
cleanObject(&condition); cleanObject(&condition);
return result; return result;
} }
Object evalLambdaArgs(const Object *argForms) Object evalLambdaArgs(const Object* argForms)
{ {
return constructLambda( return constructLambda(argForms, // Params
argForms, // Params argForms ? argForms->forward : NULL // Body
argForms ? argForms->forward : NULL // Body
); );
} }
Object evalMapArgs(const Object *argForms, struct Environment *env) Object evalMapArgs(const Object* argForms, struct Environment* env)
{ {
if(!argForms) { if (!argForms) {
return errorObject(NULL_MAP_ARGS); return errorObject(NULL_MAP_ARGS);
} }
Object lambda = eval(argForms, env); Object lambda = eval(argForms, env);
const Object *inputList = argForms->forward; const Object* inputList = argForms->forward;
Object outputList = listObject(); Object outputList = listObject();
if(lambda.type != TYPE_LAMBDA) { if (lambda.type != TYPE_LAMBDA) {
return errorObject(BAD_TYPE); return errorObject(BAD_TYPE);
} }
FOR_POINTER_IN_LIST(inputList) { if (inputList) {
// Create a new list for each element, FOR_POINTER_IN_LIST(inputList) {
// since lambda evaluation looks for a list // Create a new list for each element,
Object tempList = startList(cloneObject(*POINTER)); // since lambda evaluation looks for a list
Object tempList = startList(cloneObject(*POINTER));
Object *params = &lambda.lambda->params; Object* params = &lambda.lambda->params;
struct Environment newEnv = envForLambda(params, &tempList, env); struct Environment newEnv = envForLambda(params, &tempList, env);
// Add the lambda evaluation to the list // Add the lambda evaluation to the list
Object lambda_output = eval(&lambda.lambda->body, &newEnv); Object lambda_output = eval(&lambda.lambda->body, &newEnv);
Object delisted = cloneObject(*lambda_output.list); Object delisted = cloneObject(*lambda_output.list);
nf_addToList(&outputList, delisted); nf_addToList(&outputList, delisted);
deleteEnv(&newEnv); deleteEnv(&newEnv);
cleanObject(&tempList); cleanObject(&tempList);
cleanObject(&lambda_output); cleanObject(&lambda_output);
}
} }
cleanObject(&lambda); cleanObject(&lambda);
return outputList; return outputList;
} }
Object evalBuiltIns(const Object *first, const Object *rest, Object evalBuiltIns(const Object* first, const Object* rest,
struct Environment *env) struct Environment* env)
{ {
if(first->type != TYPE_SYMBOL) { if (first->type != TYPE_SYMBOL) {
return errorObject(NOT_A_SYMBOL); return errorObject(NOT_A_SYMBOL);
} }
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 #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 #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) {
return evalLambdaArgs(rest); return evalLambdaArgs(rest);
} else if(strcmp(first->string, "map") == 0) { } else if (strcmp(first->string, "map") == 0) {
return evalMapArgs(rest, env); return evalMapArgs(rest, env);
} }
@ -138,10 +134,10 @@ Object evalBuiltIns(const Object *first, const Object *rest,
* @param start The Object element to start with * @param start The Object element to start with
* @param env The environment to use while evaluating * @param env The environment to use while evaluating
*/ */
void evalForms(Object *destArr, const Object *start, struct Environment *env) void evalForms(Object* destArr, const Object* start, struct Environment* env)
{ {
int i = 0; int i = 0;
while(start) { while (start) {
destArr[i] = eval(start, env); destArr[i] = eval(start, env);
start = start->forward; start = start->forward;
i++; i++;
@ -159,13 +155,10 @@ void evalForms(Object *destArr, const Object *start, struct Environment *env)
* @param length Length of `list` - 1, to exclude the already-evaluated element * @param length Length of `list` - 1, to exclude the already-evaluated element
* @param env The environment to evaluate in * @param env The environment to evaluate in
*/ */
Object listEvalFunc( Object listEvalFunc(const Object* list, const Object* function,
const Object *list, const int length, struct Environment* env)
const Object *function,
const int length,
struct Environment *env)
{ {
if(length == 0) { if (length == 0) {
return function->func(boolObject(0), boolObject(0), env); return function->func(boolObject(0), boolObject(0), env);
} }
@ -173,10 +166,9 @@ Object listEvalFunc(
evalForms(rest, list->list->forward, env); evalForms(rest, list->list->forward, env);
Object func_result = rest[0]; Object func_result = rest[0];
if(length == 1) { if (length == 1) {
Object oneArg = errorObject(ONLY_ONE_ARGUMENT); Object oneArg = errorObject(ONLY_ONE_ARGUMENT);
func_result = function->func( func_result = function->func(func_result, oneArg, env);
func_result, oneArg, env);
// Return a partial function if more parameters are required // Return a partial function if more parameters are required
// Otherwise, return the function result // Otherwise, return the function result
cleanObject(&rest[0]); cleanObject(&rest[0]);
@ -192,7 +184,7 @@ Object listEvalFunc(
} else { } else {
// With two args, will apply function once // With two args, will apply function once
// With more than two args, apply the function repeatedly // With more than two args, apply the function repeatedly
for(int i = 1; i < length; i++) { for (int i = 1; i < length; i++) {
Object toClean = func_result; Object toClean = func_result;
func_result = function->func(func_result, rest[i], env); func_result = function->func(func_result, rest[i], env);
cleanObject(&toClean); cleanObject(&toClean);
@ -212,23 +204,18 @@ Object listEvalFunc(
* @param remaining The first element after `lambda` * @param remaining The first element after `lambda`
* @param env The environment to evaluate in * @param env The environment to evaluate in
*/ */
Object listEvalLambda( Object listEvalLambda(Object* lambda, const Object* remaining,
Object *lambda, struct Environment* env)
const Object *remaining, {
struct Environment *env struct Environment newEnv =
) { envForLambda(&lambda->lambda->params, remaining, env);
struct Environment newEnv = envForLambda(
&lambda->lambda->params,
remaining,
env
);
Object ret = eval(&lambda->lambda->body, &newEnv); Object ret = eval(&lambda->lambda->body, &newEnv);
deleteEnv(&newEnv); deleteEnv(&newEnv);
cleanObject(lambda); cleanObject(lambda);
Object *t = tail(&ret); Object* t = tail(&ret);
if(t) { if (t) {
Object o = cloneObject(*t); Object o = cloneObject(*t);
cleanObject(&ret); cleanObject(&ret);
return o; return o;
@ -250,20 +237,20 @@ Object listEvalLambda(
* @param obj The list to be evaluated * @param obj The list to be evaluated
* @param env The environment to evaluate in * @param env The environment to evaluate in
*/ */
Object evalList(const Object *obj, struct Environment *env) Object evalList(const Object* obj, struct Environment* env)
{ {
const int evalLength = listLength(obj); const int evalLength = listLength(obj);
if(evalLength == 0) { if (evalLength == 0) {
return cloneObject(*obj); return cloneObject(*obj);
} }
Object *first_form = obj->list; Object* first_form = obj->list;
{ // Try to eval built-ins { // Try to eval built-ins
Object builtIn = evalBuiltIns(first_form, first_form->forward, env); Object builtIn = evalBuiltIns(first_form, first_form->forward, env);
if(!isError(builtIn, BUILT_IN_NOT_FOUND) && if (!isError(builtIn, BUILT_IN_NOT_FOUND) &&
!isError(builtIn, NOT_A_SYMBOL)) { !isError(builtIn, NOT_A_SYMBOL)) {
return builtIn; return builtIn;
} }
@ -272,7 +259,7 @@ Object evalList(const Object *obj, struct Environment *env)
// Evaluate the list based on the first element's type // Evaluate the list based on the first element's type
Object first_eval = eval(first_form, env); Object first_eval = eval(first_form, env);
switch(first_eval.type) { switch (first_eval.type) {
case TYPE_FUNC: case TYPE_FUNC:
// Passes evalLength - 1, because we skip the first form // Passes evalLength - 1, because we skip the first form
return listEvalFunc(obj, &first_eval, evalLength - 1, env); return listEvalFunc(obj, &first_eval, evalLength - 1, env);
@ -280,12 +267,12 @@ Object evalList(const Object *obj, struct Environment *env)
case TYPE_LAMBDA: case TYPE_LAMBDA:
return listEvalLambda(&first_eval, first_form->forward, env); return listEvalLambda(&first_eval, first_form->forward, env);
default: { // Return list with each element evaluated default: { // Return list with each element evaluated
Object list = listObject(); Object list = listObject();
int i = 0; int i = 0;
nf_addToList(&list, first_eval); nf_addToList(&list, first_eval);
FOR_POINTER_IN_LIST(obj) { FOR_POINTER_IN_LIST(obj) {
if(i != 0) { if (i != 0) {
nf_addToList(&list, eval(POINTER, env)); nf_addToList(&list, eval(POINTER, env));
} }
i++; i++;
@ -295,9 +282,9 @@ Object evalList(const Object *obj, struct Environment *env)
} }
} }
Object eval(const Object *obj, struct Environment *env) Object eval(const Object* obj, struct Environment* env)
{ {
switch(obj->type) { switch (obj->type) {
case TYPE_FUNC: case TYPE_FUNC:
case TYPE_ERROR: case TYPE_ERROR:
case TYPE_OTHER: case TYPE_OTHER:
@ -325,7 +312,7 @@ Object eval(const Object *obj, struct Environment *env)
return errorObject(BAD_TYPE); return errorObject(BAD_TYPE);
} }
Object catObjects(const Object obj1, const Object obj2, struct Environment *env) Object catObjects(const Object obj1, const Object obj2, struct Environment* env)
{ {
Object evalObj1 = eval(&obj1, env); Object evalObj1 = eval(&obj1, env);
Object evalObj2 = eval(&obj2, env); Object evalObj2 = eval(&obj2, env);
@ -346,25 +333,25 @@ Object catObjects(const Object obj1, const Object obj2, struct Environment *env)
return o; return o;
} }
Object listEquality(const Object *list1, const Object *list2) Object listEquality(const Object* list1, const Object* list2)
{ {
FOR_POINTERS_IN_LISTS(list1, list2) { FOR_POINTERS_IN_LISTS(list1, list2) {
if(P1->type != P2->type || P1->number != P2->number) { if (P1->type != P2->type || P1->number != P2->number) {
return boolObject(0); return boolObject(0);
} }
} }
return boolObject(1); return boolObject(1);
} }
Object _basicOp(const Object *obj1, const Object *obj2, const char op, Object _basicOp(const Object* obj1, const Object* obj2, const char op,
struct Environment *env) struct Environment* env)
{ {
const int n1 = obj1->number; const int n1 = obj1->number;
const int n2 = obj2->number; const int n2 = obj2->number;
switch(op){ switch (op) {
case '+': case '+':
if(eitherIs(TYPE_STRING, obj1, obj2)) { if (eitherIs(TYPE_STRING, obj1, obj2)) {
return catObjects(*obj1, *obj2, env); return catObjects(*obj1, *obj2, env);
} }
return numberObject(n1 + n2); return numberObject(n1 + n2);
@ -377,11 +364,16 @@ Object _basicOp(const Object *obj1, const Object *obj2, const char op,
case '%': case '%':
return numberObject(n1 % n2); return numberObject(n1 % n2);
case '&':
return boolObject(n1 != 0 && n2 != 0);
case '|':
return boolObject(n1 != 0 || n2 != 0);
case '=': case '=':
if(bothAre(TYPE_STRING, obj1, obj2)) { if (bothAre(TYPE_STRING, obj1, obj2)) {
return boolObject(!strcmp(obj1->string, obj2->string)); return boolObject(!strcmp(obj1->string, obj2->string));
} }
if(bothAre(TYPE_LIST, obj1, obj2)) { if (bothAre(TYPE_LIST, obj1, obj2)) {
return listEquality(obj1, obj2); return listEquality(obj1, obj2);
} }
return boolObject(n1 == n2 && areSameType(obj1, obj2)); return boolObject(n1 == n2 && areSameType(obj1, obj2));
@ -394,20 +386,21 @@ Object _basicOp(const Object *obj1, const Object *obj2, const char op,
return *obj1; return *obj1;
} }
Object basicOp(const Object *obj1, const Object *obj2, const char op, Object basicOp(const Object* obj1, const Object* obj2, const char op,
struct Environment *env) struct Environment* env)
{ {
if(isError(*obj2, ONLY_ONE_ARGUMENT)) { if (isError(*obj2, ONLY_ONE_ARGUMENT)) {
return *obj2; return *obj2;
} }
int lists = (obj1->type == TYPE_LIST) + (obj2->type == TYPE_LIST); int lists = (obj1->type == TYPE_LIST) + (obj2->type == TYPE_LIST);
if(lists == 0) { if (lists == 0) {
return _basicOp(obj1, obj2, op, env); return _basicOp(obj1, obj2, op, env);
} else if(lists == 1) { // Single operand is applied to each element in list } else if (lists ==
const Object *listObj = (obj1->type == TYPE_LIST)? obj1 : obj2; 1) { // Single operand is applied to each element in list
const Object *singleObj = (obj1->type == TYPE_LIST)? obj2 : obj1; const Object* listObj = (obj1->type == TYPE_LIST) ? obj1 : obj2;
const Object* singleObj = (obj1->type == TYPE_LIST) ? obj2 : obj1;
Object newList = listObject(); Object newList = listObject();
FOR_POINTER_IN_LIST(listObj) { FOR_POINTER_IN_LIST(listObj) {
@ -416,8 +409,8 @@ Object basicOp(const Object *obj1, const Object *obj2, const char op,
} }
return newList; return newList;
} else { // 2 lists with the op applied to matching indices of both lists } else { // 2 lists with the op applied to matching indices of both lists
if(listLength(obj1) == listLength(obj2)) { if (listLength(obj1) == listLength(obj2)) {
Object newList = listObject(); Object newList = listObject();
FOR_POINTERS_IN_LISTS(obj1, obj2) { FOR_POINTERS_IN_LISTS(obj1, obj2) {
const Object ev1 = eval(P1, env); const Object ev1 = eval(P1, env);
@ -431,45 +424,58 @@ Object basicOp(const Object *obj1, const Object *obj2, const char op,
} }
} }
#define BASIC_OP(_name, _char) \ #define BASIC_OP(_name, _char) \
Object _name(Object obj1, Object obj2, struct Environment *env) \ Object _name(Object obj1, Object obj2, struct Environment *env) \
{ return basicOp(&obj1, &obj2, _char, env); } { \
return basicOp(&obj1, &obj2, _char, env); \
}
BASIC_OP(add, '+'); BASIC_OP(add, '+');
BASIC_OP(sub, '-'); BASIC_OP(sub, '-');
BASIC_OP(mul, '*'); BASIC_OP(mul, '*');
BASIC_OP(dvi, '/'); BASIC_OP(dvi, '/');
BASIC_OP(mod, '%'); BASIC_OP(mod, '%');
BASIC_OP(equ, '='); BASIC_OP(equ, '=');
BASIC_OP(gth, '>'); BASIC_OP(gth, '>');
BASIC_OP(lth, '<'); BASIC_OP(lth, '<');
BASIC_OP(and, '&');
BASIC_OP(or, '|');
#undef BASIC_OP #undef BASIC_OP
Object filter(Object obj1, Object obj2, struct Environment *env) Object filter(Object obj1, Object obj2, struct Environment* env)
{ {
Object filteredList = listObject(); Object filteredList = listObject();
Object *filteringList = &obj2; Object* filteringList = &obj2;
FOR_POINTER_IN_LIST(filteringList) { FOR_POINTER_IN_LIST(filteringList) {
Object conditional = cloneObject(obj1); Object conditional = cloneObject(obj1);
nf_addToList(&conditional, *POINTER); // cloneObject()? nf_addToList(&conditional, *POINTER); // cloneObject()?
Object result = eval(&conditional, env); Object result = eval(&conditional, env);
cleanObject(&conditional); cleanObject(&conditional);
if(result.number == 1) { if (result.number == 1) {
nf_addToList(&filteredList, *POINTER); nf_addToList(&filteredList, *POINTER);
} }
} }
return filteredList; return filteredList;
} }
Object append(Object list, Object newElement, struct Environment *env) Object append(Object list, Object newElement, struct Environment* env)
{ {
Object newList = cloneObject(list); Object newList = cloneObject(list);
nf_addToList(&newList, cloneObject(newElement)); nf_addToList(&newList, cloneObject(newElement));
return newList; return newList;
} }
Object prepend(Object list, Object newElement, struct Environment *env) Object prepend(Object list, Object newElement, struct Environment* env)
{ {
Object newList = listObject(); Object newList = listObject();
nf_addToList(&newList, cloneObject(newElement)); nf_addToList(&newList, cloneObject(newElement));
@ -477,22 +483,22 @@ Object prepend(Object list, Object newElement, struct Environment *env)
return newList; return newList;
} }
Object at(Object index, Object list, struct Environment *env) Object at(Object index, Object list, struct Environment* env)
{ {
const Object *found = itemAt(&list, index.number); const Object* found = itemAt(&list, index.number);
if(found) { if (found) {
return cloneObject(*found); return cloneObject(*found);
} else { } else {
return errorObject(INDEX_PAST_END); return errorObject(INDEX_PAST_END);
} }
} }
Object rest(Object list, Object ignore, struct Environment *env) Object rest(Object list, Object ignore, struct Environment* env)
{ {
Object ret = listObject(); Object ret = listObject();
Object *l = &list; Object* l = &list;
FOR_POINTER_IN_LIST(l) { FOR_POINTER_IN_LIST(l) {
if(POINTER == l->list) { if (POINTER == l->list) {
continue; continue;
} }
nf_addToList(&ret, cloneObject(*POINTER)); nf_addToList(&ret, cloneObject(*POINTER));
@ -500,16 +506,16 @@ Object rest(Object list, Object ignore, struct Environment *env)
return ret; return ret;
} }
Object reverse(Object _list, Object ignore, struct Environment *ignore2) Object reverse(Object _list, Object ignore, struct Environment* ignore2)
{ {
const Object *list = &_list; const Object* list = &_list;
Object rev = listObject(); Object rev = listObject();
Object *tail = NULL; Object* tail = NULL;
FOR_POINTER_IN_LIST(list) { FOR_POINTER_IN_LIST(list) {
Object *oldTail = tail; Object* oldTail = tail;
allocObject(&tail, cloneObject(*POINTER)); allocObject(&tail, cloneObject(*POINTER));
if(oldTail) { if (oldTail) {
tail->forward = oldTail; tail->forward = oldTail;
} }
} }
@ -518,33 +524,30 @@ Object reverse(Object _list, Object ignore, struct Environment *ignore2)
return rev; return rev;
} }
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);
} }
// Get the int value of a string's first character // Get the int value of a string's first character
Object charVal(Object test, Object ignore, struct Environment *ignore2) Object charVal(Object test, Object ignore, struct Environment* ignore2)
{ {
return numberObject(test.string[0]); return numberObject(test.string[0]);
// return test.type == TYPE_STRING && test.string[0] == '\0' ? // return test.type == TYPE_STRING && test.string[0] == '\0' ?
// 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);
} }
Object charAt(Object string, Object at, struct Environment *ignore) Object charAt(Object string, Object at, struct Environment* ignore)
{ {
char* c = malloc(sizeof(char) * 2); char* c = malloc(sizeof(char) * 2);
c[0] = string.string[at.number]; c[0] = string.string[at.number];
@ -554,7 +557,8 @@ Object charAt(Object string, Object at, struct Environment *ignore)
} }
#ifdef STANDALONE #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);
p = eval(&p, env); p = eval(&p, env);
@ -562,67 +566,71 @@ Object print(Object p, Object ignore, struct Environment *env)
return numberObject(0); return numberObject(0);
} }
Object pChar(Object c, Object i1, struct Environment *i2) Object pChar(Object c, Object i1, struct Environment* i2)
{ {
if(c.type != TYPE_NUMBER) { if (c.type != TYPE_NUMBER) {
return errorObject(BAD_NUMBER); return errorObject(BAD_NUMBER);
} }
printf("%c", c.number % 256); printf("%c", c.number % 256);
return numberObject(0); return numberObject(0);
} }
Object printEnvO(Object i1, Object i2, struct Environment *env) { Object printEnvO(Object i1, Object i2, struct Environment* env)
while(env->outer) { {
env = env-> outer; while (env->outer) {
env = env->outer;
} }
printEnv(env); printEnv(env);
return numberObject(0); return numberObject(0);
} }
#endif #endif
Object parseEvalO(Object text, Object ignore, struct Environment *env) Object parseEvalO(Object text, Object ignore, struct Environment* env)
{ {
if(text.type == TYPE_SYMBOL) { if (text.type == TYPE_SYMBOL) {
Object string = eval(&text, env); Object string = eval(&text, env);
Object parsed = parseEval(string.string, env); Object parsed = parseEval(string.string, env);
cleanObject(&string); cleanObject(&string);
return parsed; return parsed;
} else if(text.type != TYPE_STRING) { } else if (text.type != TYPE_STRING) {
return errorObject(CAN_ONLY_EVAL_STRINGS); return errorObject(CAN_ONLY_EVAL_STRINGS);
} }
return parseEval(text.string, env); return parseEval(text.string, env);
} }
#ifdef STANDALONE #ifdef STANDALONE
Object takeInput(Object i1, Object i2, struct Environment *i3)
Object takeInput(Object i1, Object i2, struct Environment* i3)
{ {
char input[256] = ""; char input[256] = "";
fgets(input, 256, stdin); fgets(input, 256, stdin);
return stringFromSlice(input, strlen(input) - 1); return stringFromSlice(input, strlen(input) - 1);
} }
#endif #endif
void copySlice(char * dest, struct Slice *src) void copySlice(char* dest, struct Slice* src)
{ {
if(!dest || !src) { if (!dest || !src) {
return; return;
} }
strncpy(dest, src->text, src->length); strncpy(dest, src->text, src->length);
dest[(int)src->length] = '\0'; dest[(int) src->length] = '\0';
} }
void debugSlice(struct Slice *s) void debugSlice(struct Slice* s)
{ {
#ifdef DEBUG #ifdef DEBUG
if(!s) { if (!s) {
printf("NULL SLICE\n"); printf("NULL SLICE\n");
return; return;
} }
printf("Debug Slice\n text:'"); printf("Debug Slice\n text:'");
for(int i = 0; i < s->length; i++) { for (int i = 0; i < s->length; i++) {
printf("%c", s->text[i]); printf("%c", s->text[i]);
if(s->text[i] == '\0') { if (s->text[i] == '\0') {
printf("NULLCHAR\n"); printf("NULLCHAR\n");
} }
} }
@ -631,37 +639,37 @@ void debugSlice(struct Slice *s)
#endif #endif
} }
Result parse(struct Slice *slices) Result parse(struct Slice* slices)
{ {
struct Slice *token = slices; struct Slice* token = slices;
if(token && token->text) { if (token && token->text) {
struct Slice *rest = &slices[1]; struct Slice* rest = &slices[1];
if(token->text[0] == '\'' && token->text[1] == '(') { if (token->text[0] == '\'' && token->text[1] == '(') {
Result r = readSeq(&slices[2]); Result r = readSeq(&slices[2]);
r.obj.type = TYPE_SLIST; r.obj.type = TYPE_SLIST;
return r; return r;
} else if(token->text[0] == '(') { } else if (token->text[0] == '(') {
// todo check for null rest // todo check for null rest
return readSeq(rest); return readSeq(rest);
} else { // todo error on missing close paren } else { // todo error on missing close paren
return (Result){parseAtom(token), rest}; return (Result) {parseAtom(token), rest};
} }
} else { } else {
return (Result){errorObject(NULL_PARSE), NULL}; return (Result) {errorObject(NULL_PARSE), NULL};
} }
} }
Result readSeq(struct Slice *tokens) Result readSeq(struct Slice* tokens)
{ {
Object res = listObject(); Object res = listObject();
for(;;) { for (;;) {
struct Slice *next = tokens; struct Slice* next = tokens;
struct Slice *rest = next->text? &next[1] : NULL; struct Slice* rest = next->text ? &next[1] : NULL;
if(next->text[0] == ')') { if (next->text[0] == ')') {
return (Result){res, rest}; return (Result) {res, rest};
} }
Result r = parse(tokens); Result r = parse(tokens);
if(r.obj.type == TYPE_ERROR) { if (r.obj.type == TYPE_ERROR) {
return r; return r;
} }
nf_addToList(&res, cloneObject(r.obj)); nf_addToList(&res, cloneObject(r.obj));
@ -670,11 +678,11 @@ Result readSeq(struct Slice *tokens)
} }
} }
Object parseDecimal(struct Slice *s) Object parseDecimal(struct Slice* s)
{ {
int num = 0; int num = 0;
for(int i = 0; i < s->length; i++) { for (int i = 0; i < s->length; i++) {
if(!isDigit(s->text[i])) { if (!isDigit(s->text[i])) {
return errorObject(BAD_NUMBER); return errorObject(BAD_NUMBER);
} }
num *= 10; num *= 10;
@ -683,16 +691,16 @@ Object parseDecimal(struct Slice *s)
return numberObject(num); return numberObject(num);
} }
Object parseHex(struct Slice *s) Object parseHex(struct Slice* s)
{ {
int num = 0; int num = 0;
for(int i = 2; i < s->length; i++) { for (int i = 2; i < s->length; i++) {
const char c = s->text[i]; const char c = s->text[i];
if(!isHex(c)) { if (!isHex(c)) {
return errorObject(BAD_NUMBER); return errorObject(BAD_NUMBER);
} }
num *= 16; num *= 16;
if(isDigit(c)) { if (isDigit(c)) {
num += c - '0'; num += c - '0';
} else /* is hex */ { } else /* is hex */ {
num += c - 'a' + 10; num += c - 'a' + 10;
@ -701,12 +709,12 @@ Object parseHex(struct Slice *s)
return numberObject(num); return numberObject(num);
} }
Object parseBin(struct Slice *s) Object parseBin(struct Slice* s)
{ {
int num = 0; int num = 0;
for(int i = 2; i < s->length; i++) { for (int i = 2; i < s->length; i++) {
const char c = s->text[i]; const char c = s->text[i];
if(c != '0' && c != '1') { if (c != '0' && c != '1') {
return errorObject(BAD_NUMBER); return errorObject(BAD_NUMBER);
} }
num *= 2; num *= 2;
@ -715,18 +723,18 @@ Object parseBin(struct Slice *s)
return numberObject(num); return numberObject(num);
} }
Object parseAtom(struct Slice *s) Object parseAtom(struct Slice* s)
{ {
const char c = s->text[0]; const char c = s->text[0];
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 #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 #endif
} else { } else {
return errorObject(UNSUPPORTED_NUMBER_TYPE); return errorObject(UNSUPPORTED_NUMBER_TYPE);
} }
@ -741,52 +749,52 @@ Object parseAtom(struct Slice *s)
} }
} }
Object parseEval(const char *input, struct Environment *env) Object parseEval(const char* input, struct Environment* env)
{ {
struct Error err = noError(); struct Error err = noError();
struct Slice *tokens = nf_tokenize(input, &err); struct Slice* tokens = nf_tokenize(input, &err);
if(err.context != NULL) { if (err.context != NULL) {
Object o = errorWithContext(err.code, err.context); Object o = errorWithContext(err.code, err.context);
free(err.context); free(err.context);
return o; return o;
} }
if(!tokens->text) { if (!tokens->text) {
return symFromSlice(" ", 1); return symFromSlice(" ", 1);
} }
#ifdef DEBUG #ifdef DEBUG
struct Slice *debug = tokens; struct Slice *debug = tokens;
printd("start slice\n"); printd("start slice\n");
if(debug) { if (debug) {
while(debug->text) { while (debug->text) {
char tok[100]; char tok[100];
copySlice(tok, debug); copySlice(tok, debug);
printd("slice: '%s'\n", tok); printd("slice: '%s'\n", tok);
debug++; debug++;
} }
} }
#endif #endif
int i = 0; int i = 0;
int parens = 0; int parens = 0;
Object obj = numberObject(0); Object obj = numberObject(0);
struct Slice *tok = tokens; struct Slice* tok = tokens;
while(tok[i].text != NULL) { while (tok[i].text != NULL) {
if(tok[i].text[0] == '(') { if (tok[i].text[0] == '(') {
parens++; parens++;
} else if(tok[i].text[0] == ')') { } else if (tok[i].text[0] == ')') {
parens--; parens--;
} }
if(parens == 0) { if (parens == 0) {
cleanObject(&obj); cleanObject(&obj);
Object parsed = parse(tok).obj; Object parsed = parse(tok).obj;
if(parsed.type == TYPE_ERROR) { if (parsed.type == TYPE_ERROR) {
obj = parsed; // TODO Check necessity obj = parsed; // TODO Check necessity
break; break;
} }
if(tok[i].text[0] == ')') { if (tok[i].text[0] == ')') {
// Skip `tok` past end of list that just closed // Skip `tok` past end of list that just closed
tok = &tok[i + 1]; tok = &tok[i + 1];
i = -1; i = -1;
@ -806,26 +814,28 @@ Object parseEval(const char *input, struct Environment *env)
} }
#ifdef STANDALONE #ifdef STANDALONE
int _readFile(FILE *input, struct Environment *env) {
int _readFile(FILE* input, struct Environment* env)
{
Object r = numberObject(0); Object r = numberObject(0);
char page[4096] = ""; char page[4096] = "";
const unsigned LINE_MAX = 256; const int LINE_MAX = 256;
char line[LINE_MAX]; char line[LINE_MAX];
if(fgets(line, LINE_MAX, input)){ if (fgets(line, LINE_MAX, input)) {
if(line[0] != '#' || line[1] != '!') { if (line[0] != '#' || line[1] != '!') {
strncat(page, line, strlen(line) - 1); strncat(page, line, strlen(line) - 1);
} }
} }
while(fgets(line, LINE_MAX, input)) { while (fgets(line, LINE_MAX, input)) {
int i; int i;
for(i = 0; i < LINE_MAX; i++) { for (i = 0; i < LINE_MAX; i++) {
if(line[i] != ' ') { if (line[i] != ' ') {
if(line[i] == ';') { if (line[i] == ';') {
break; break;
} else { } else {
int j = 0; int j = 0;
for(j = i; j < LINE_MAX; j++) { for (j = i; j < LINE_MAX; j++) {
if(line[j] == ';' || line[j] == '\0') { if (line[j] == ';' || line[j] == '\0') {
break; break;
} }
} }
@ -843,16 +853,19 @@ int _readFile(FILE *input, struct Environment *env) {
fclose(input); fclose(input);
return 0; return 0;
} }
int readFile(const char *filename, struct Environment *env) {
FILE *input = fopen(filename, "r"); int readFile(const char* filename, struct Environment* env)
if(!input) { {
FILE* input = fopen(filename, "r");
if (!input) {
return 1; return 1;
} }
_readFile(input, env); _readFile(input, env);
return 0; return 0;
} }
Object loadFile(Object filename, Object _, struct Environment *env) { Object loadFile(Object filename, Object _, struct Environment* env)
{
if (isStringy(filename)) { if (isStringy(filename)) {
readFile(filename.string, env); readFile(filename.string, env);
return numberObject(0); return numberObject(0);
@ -860,23 +873,26 @@ Object loadFile(Object filename, Object _, struct Environment *env) {
return numberObject(1); return numberObject(1);
} }
Object systemCall(Object process, Object _, struct Environment *env) { Object systemCall(Object process, Object _, struct Environment* env)
{
if (isStringy(process)) { if (isStringy(process)) {
return numberObject(system(process.string)); return numberObject(system(process.string));
} }
return numberObject(255); return numberObject(255);
} }
void repl(struct Environment *env) { void repl(struct Environment* env)
{
if (readFile(SCRIPTDIR "/repl.pbl", env) == 1) { if (readFile(SCRIPTDIR "/repl.pbl", env) == 1) {
fprintf(stderr, "Could not read '%s'\n", SCRIPTDIR "/repl.pbl"); fprintf(stderr, "Could not read '%s'\n", SCRIPTDIR "/repl.pbl");
fprintf(stderr, "Consider installing or reinstalling pebblisp.\n"); fprintf(stderr, "Consider installing or reinstalling pebblisp.\n");
} }
} }
void loadArgsIntoEnv(int argc, const char* argv[], struct Environment* env) { void loadArgsIntoEnv(int argc, const char* argv[], struct Environment* env)
{
Object args = listObject(); Object args = listObject();
for(int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
nf_addToList(&args, stringFromSlice(argv[i], strlen(argv[i]))); nf_addToList(&args, stringFromSlice(argv[i], strlen(argv[i])));
} }
addToEnv(env, "args", args); addToEnv(env, "args", args);
@ -886,16 +902,16 @@ int main(int argc, const char* argv[])
{ {
struct Environment env = defaultEnv(); struct Environment env = defaultEnv();
readFile(SCRIPTDIR "/lib.pbl", &env); readFile(SCRIPTDIR "/lib.pbl", &env);
if(argc >= 2) { if (argc >= 2) {
FILE *file = fopen(argv[1], "r"); FILE* file = fopen(argv[1], "r");
if(file) { if (file) {
// Executing a file // Executing a file
loadArgsIntoEnv(argc, argv, &env); loadArgsIntoEnv(argc, argv, &env);
_readFile(file, &env); _readFile(file, &env);
} else { } else {
// Running arguments directly as pl code // Running arguments directly as pl code
Object r = numberObject(0); Object r = numberObject(0);
for(int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
r = parseEval(argv[i], &env); r = parseEval(argv[i], &env);
printAndClean(&r); printAndClean(&r);
} }
@ -907,4 +923,5 @@ int main(int argc, const char* argv[])
} }
deleteEnv(&env); deleteEnv(&env);
} }
#endif #endif

View File

@ -1,76 +1,105 @@
#ifndef PEBBLISP_H #ifndef PEBBLISP_H
#define PEBBLISP_H #define PEBBLISP_H
#include "object.h"
#include "env.h" #include "env.h"
#include "object.h"
#ifndef STANDALONE
#include <pebble.h>
#define printd(...) ;
#endif
#ifdef DEBUG
#define printd(...) printf(__VA_ARGS__)
#else
#define printd(...) ;
#endif
struct Slice { struct Slice {
const char *text; const char* text;
char length; char length;
}; };
typedef struct Result { typedef struct Result {
Object obj; Object obj;
struct Slice *slices; struct Slice* slices;
} Result; } Result;
Object eval(const Object *obj, struct Environment *env); Object eval(const Object* obj, struct Environment* env);
Result parse(struct Slice *slices);
Result readSeq(struct Slice *slices);
Object parseAtom(struct Slice *slice);
Object parseEval(const char *input, struct Environment *env);
void evalForms(Object *destList, const Object *src, struct Environment *env);
void copySlice(char * dest, struct Slice *src);
Object evalLambdaArgs(const Object *arg_forms); Result parse(struct Slice* slices);
Result readSeq(struct Slice* slices);
Object parseAtom(struct Slice* slice);
Object parseEval(const char* input, struct Environment* env);
void evalForms(Object* destList, const Object* src, struct Environment* env);
void copySlice(char* dest, struct Slice* src);
Object evalLambdaArgs(const Object* arg_forms);
// Slices // Slices
void copySlice(char * dest, struct Slice *src); void copySlice(char* dest, struct Slice* src);
void debugSlice(struct Slice *s);
void debugSlice(struct Slice* s);
#define BASIC_OP(_name) \ #define BASIC_OP(_name) \
Object _name(Object obj1, Object obj2, struct Environment *env); Object _name(Object obj1, Object obj2, struct Environment *env);
BASIC_OP(add); BASIC_OP(sub);
BASIC_OP(mul); BASIC_OP(dvi); BASIC_OP(add);
BASIC_OP(mod); BASIC_OP(equ);
BASIC_OP(gth); BASIC_OP(lth); BASIC_OP(sub);
BASIC_OP(mul);
BASIC_OP(dvi);
BASIC_OP(mod);
BASIC_OP(equ);
BASIC_OP(gth);
BASIC_OP(lth);
BASIC_OP(and);
BASIC_OP(or);
#undef BASIC_OP #undef BASIC_OP
Object catObjects(const Object obj1, const Object obj2, struct Environment *env); Object catObjects(const Object obj1, const Object obj2,
Object filter(Object obj1, Object obj2, struct Environment *env); struct Environment* env);
Object append(Object list, Object newElement, struct Environment *env);
Object prepend(Object list, Object newElement, struct Environment *env);
Object at(Object index, Object list, struct Environment *env);
Object rest(Object list, Object ignore, struct Environment *env);
Object reverse(Object _list, Object ignore, struct Environment *ignore2);
Object isNum(Object test, Object ignore, struct Environment *ignore2); Object filter(Object obj1, Object obj2, struct Environment* env);
Object isString(Object test, Object ignore, struct Environment *ignore2);
Object isErr(Object test, Object ignore, struct Environment *ignore2);
Object charAt(Object string, Object at, struct Environment *ignore); Object append(Object list, Object newElement, struct Environment* env);
Object charVal(Object test, Object ignore, struct Environment *ignore2);
Object print(Object p, Object ignore, struct Environment *ignore2); Object prepend(Object list, Object newElement, struct Environment* env);
Object pChar(Object c, Object i1, struct Environment *i2);
Object printEnvO(Object i1, Object i2, struct Environment *env); Object at(Object index, Object list, struct Environment* env);
Object parseEvalO(Object text, Object ignore, struct Environment *env);
Object rest(Object list, Object ignore, struct Environment* env);
Object reverse(Object _list, Object ignore, struct Environment* ignore2);
Object isNum(Object test, Object ignore, struct Environment* ignore2);
Object isString(Object test, Object ignore, struct Environment* ignore2);
Object isErr(Object test, Object ignore, struct Environment* ignore2);
Object charAt(Object string, Object at, struct Environment* ignore);
Object charVal(Object test, Object ignore, struct Environment* ignore2);
Object print(Object p, Object ignore, struct Environment* ignore2);
Object pChar(Object c, Object i1, struct Environment* i2);
Object printEnvO(Object i1, Object i2, struct Environment* env);
Object parseEvalO(Object text, Object ignore, struct Environment* env);
#ifdef STANDALONE #ifdef STANDALONE
Object takeInput(Object i1, Object i2, struct Environment *i3);
Object systemCall(Object call, Object _, struct Environment *i3); Object takeInput(Object i1, Object i2, struct Environment* i3);
Object loadFile(Object filename, Object _, struct Environment *env);
Object systemCall(Object call, Object _, struct Environment* i3);
Object loadFile(Object filename, Object _, struct Environment* env);
#endif #endif
#endif #endif

View File

@ -1,44 +1,49 @@
#include <pebble.h>
#include "pebcom.h" #include "pebcom.h"
struct tm* getTime() { #include <pebble.h>
struct tm* getTime()
{
time_t t = time(NULL); time_t t = time(NULL);
return localtime(&t); return localtime(&t);
} }
Object getSeconds(Object o1, Object o2, struct Environment *env) { Object getSeconds(Object o1, Object o2, struct Environment* env)
{
return numberObject(getTime()->tm_sec); return numberObject(getTime()->tm_sec);
} }
Object getMinutes(Object o1, Object o2, struct Environment *env) { Object getMinutes(Object o1, Object o2, struct Environment* env)
{
return numberObject(getTime()->tm_min); return numberObject(getTime()->tm_min);
} }
Object getHours(Object o1, Object o2, struct Environment *env) { Object getHours(Object o1, Object o2, struct Environment* env)
{
return numberObject(getTime()->tm_hour); return numberObject(getTime()->tm_hour);
} }
Object getTwelveHours(Object o1, Object o2, struct Environment *env) { Object getTwelveHours(Object o1, Object o2, struct Environment* env)
{
int hour = (getTime()->tm_hour % 12) ?: 12; int hour = (getTime()->tm_hour % 12) ?: 12;
return numberObject(hour); return numberObject(hour);
} }
Object doVibe(Object patternList, Object o2, struct Environment *env) { Object doVibe(Object patternList, Object o2, struct Environment* env)
{
int length = listLength(&patternList); int length = listLength(&patternList);
uint32_t pattern[length]; uint32_t pattern[length];
if(length > 0) { if (length > 0) {
int i = 0; int i = 0;
Object *pl = &patternList; Object* pl = &patternList;
FOR_POINTER_IN_LIST(pl) { FOR_POINTER_IN_LIST(pl) {
if(POINTER->type == TYPE_NUMBER) { if (POINTER->type == TYPE_NUMBER) {
pattern[i] = POINTER->number; pattern[i] = POINTER->number;
} }
i++; i++;
} }
vibes_enqueue_custom_pattern((VibePattern) { vibes_enqueue_custom_pattern(
.durations = pattern, (VibePattern) {.durations = pattern, .num_segments = length});
.num_segments = length
});
return boolObject(1); return boolObject(1);
} else { } else {
return errorObject(NOT_A_LIST); return errorObject(NOT_A_LIST);

View File

@ -1,8 +1,11 @@
#include "pebblisp.h" #include "pebblisp.h"
Object getSeconds(Object o1, Object o2, struct Environment *env); Object getSeconds(Object o1, Object o2, struct Environment* env);
Object getMinutes(Object o1, Object o2, struct Environment *env);
Object getHours(Object o1, Object o2, struct Environment *env);
Object getTwelveHours(Object o1, Object o2, struct Environment *env);
Object doVibe(Object patternList, Object o2, struct Environment *env); Object getMinutes(Object o1, Object o2, struct Environment* env);
Object getHours(Object o1, Object o2, struct Environment* env);
Object getTwelveHours(Object o1, Object o2, struct Environment* env);
Object doVibe(Object patternList, Object o2, struct Environment* env);

View File

@ -1,19 +1,8 @@
#include "tokens.h" #include "tokens.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef STANDALONE
#include <stdio.h>
#undef printd
#define printd(...) fprintf(stderr, __VA_ARGS__)
#else
#include <pebble.h>
#undef printd
#undef printf
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
#define printd(...) printf(__VA_ARGS__)
#endif
#define ERR_LEN 256 #define ERR_LEN 256
/* /*
@ -26,44 +15,51 @@
// Is the char a standalone token? // Is the char a standalone token?
static const char singleTokens[] = "()+-*/='"; static const char singleTokens[] = "()+-*/='";
int isSingle(const char c) {
int isSingle(const char c)
{
int i = 0; int i = 0;
while(singleTokens[i] != '\0'){ while (singleTokens[i] != '\0') {
if(singleTokens[i] == c) if (singleTokens[i] == c) {
return singleTokens[i]; return singleTokens[i];
}
i++; i++;
} }
return 0; return 0;
} }
int isDigit(const char c) { int isDigit(const char c)
{
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
int isHex(const char c) { int isHex(const char c)
{
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
} }
int isWhitespace(const char c) { int isWhitespace(const char c)
{
return c == ' ' || c == '\t' || c == '\n'; return c == ' ' || c == '\t' || c == '\n';
} }
int notWhitespace(const char c) { int notWhitespace(const char c)
{
return !isWhitespace(c); return !isWhitespace(c);
} }
// Return needs to be freed, if not null // Return needs to be freed, if not null
struct Slice *nf_tokenize(const char *input, struct Error *err) struct Slice* nf_tokenize(const char* input, struct Error* err)
{ {
if(!input) { if (!input) {
err->context = malloc(sizeof(char) * ERR_LEN); err->context = malloc(sizeof(char) * ERR_LEN);
strcpy(err->context, "no input"); strcpy(err->context, "no input");
return NULL; return NULL;
} }
int token_count = MAX_TOK_CNT; int token_count = MAX_TOK_CNT;
struct Slice *slices = malloc(sizeof(struct Slice) * token_count); struct Slice* slices = malloc(sizeof(struct Slice) * token_count);
while(slices == NULL) { while (slices == NULL) {
token_count /= 2; token_count /= 2;
slices = malloc(sizeof(struct Slice) * token_count); slices = malloc(sizeof(struct Slice) * token_count);
} }
@ -72,20 +68,20 @@ struct Slice *nf_tokenize(const char *input, struct Error *err)
int slice = 0; int slice = 0;
int parens = 0; int parens = 0;
while(input[i] != '\0') { while (input[i] != '\0') {
int l = 1; int l = 1;
// printd("input: '%c'\n", input[i]); // printd("input: '%c'\n", input[i]);
if(isWhitespace(input[i]) || input[i] == ';') { if (isWhitespace(input[i]) || input[i] == ';') {
i++; i++;
continue; continue;
} }
if(input[i] == '(') { if (input[i] == '(') {
parens++; parens++;
} else if (input[i] == ')') { } else if (input[i] == ')') {
parens--; parens--;
if(parens < 0) { if (parens < 0) {
err->context = malloc(sizeof(char) * ERR_LEN + 1); err->context = malloc(sizeof(char) * ERR_LEN + 1);
err->code = MISMATCHED_PARENS; err->code = MISMATCHED_PARENS;
int start = i > ERR_LEN ? i - ERR_LEN : 0; int start = i > ERR_LEN ? i - ERR_LEN : 0;
@ -97,19 +93,21 @@ struct Slice *nf_tokenize(const char *input, struct Error *err)
slices[slice].text = &input[i]; slices[slice].text = &input[i];
if(isSingle(input[i])) { if (isSingle(input[i])) {
i++; i++;
} else if(input[i] == '"') { } else if (input[i] == '"') {
if(input[i + 1] == '"' && input [i + 2] == '"') { if (input[i + 1] == '"' && input[i + 2] == '"') {
// Triple-quoted block // Triple-quoted block
i += 2; i += 2;
slices[slice].text += 2; slices[slice].text += 2;
for(;;) { for (;;) {
i++; i++;
if(input[i] == '"' && input[i + 1] == '"' && input[i + 2] == '"') { if (input[i] == '"' && input[i + 1] == '"' &&
input[i + 2] == '"') {
break; break;
} }
if(input[i] == '\0' || input[i + 1] == '\0' || input[i + 2] == '\0') { if (input[i] == '\0' || input[i + 1] == '\0' ||
input[i + 2] == '\0') {
err->context = malloc(sizeof(char) * ERR_LEN + 1); err->context = malloc(sizeof(char) * ERR_LEN + 1);
err->code = UNEXPECTED_EOF; err->code = UNEXPECTED_EOF;
int start = i > ERR_LEN ? i - ERR_LEN : 0; int start = i > ERR_LEN ? i - ERR_LEN : 0;
@ -120,13 +118,14 @@ struct Slice *nf_tokenize(const char *input, struct Error *err)
} }
} else { } else {
// Simple string // Simple string
while(input[++i] != '"' && input[i] != '\0') { while (input[++i] != '"' && input[i] != '\0') {
l++; l++;
} }
} }
i++; i++;
} else { } else {
while(!isWhitespace(input[++i]) && !isSingle(input[i]) && input[i] != '\0') { while (!isWhitespace(input[++i]) && !isSingle(input[i]) &&
input[i] != '\0') {
l++; l++;
} }
} }
@ -135,7 +134,7 @@ struct Slice *nf_tokenize(const char *input, struct Error *err)
slice++; slice++;
} }
if(parens != 0){ if (parens != 0) {
err->context = malloc(sizeof(char) * ERR_LEN); err->context = malloc(sizeof(char) * ERR_LEN);
err->code = MISMATCHED_PARENS; err->code = MISMATCHED_PARENS;
int start = i > ERR_LEN ? i - ERR_LEN : 0; int start = i > ERR_LEN ? i - ERR_LEN : 0;

View File

@ -4,8 +4,11 @@
#include "pebblisp.h" #include "pebblisp.h"
int isSingle(const char c); int isSingle(const char c);
int isDigit(const char c); int isDigit(const char c);
int isHex(const char c); int isHex(const char c);
struct Slice *nf_tokenize(const char *input, struct Error *err);
struct Slice* nf_tokenize(const char* input, struct Error* err);
#endif #endif